Perl Monk, Perl Meditation | |
PerlMonks |
comment on |
( [id://3333]=superdoc: print w/replies, xml ) | Need Help?? |
Dear wise ones,
I am working on a program that will execute a forked child that will return information back to the parent process. I know that when a fork is executed, the parent and child processes initially have identical copies of the pre-forked environment but that these copies are independent of each other, such that changes made to any part of its environment by either process are not reflected in the other environment. I decided to see if I could come up with a method whereby a child could in fact modify the value of a variable in the parent. It involves encapsulating the child code into a subroutine to which a reference to a variable in the parent process is passed as an argument. The child modifies the value of the parent variable by accessing that variable via its address, not via its name. My code is as follows: use strict; use warnings; my $string = "First value"; my $ref_to_string = \$string; unless (fork) { do_subroutine ($ref_to_string); exit; } print "\nI am the invoking process and my PID is $$\n"; print "invoker $$: The value of \$ref_to_string is $ref_to_string\n"; print "invoker $$: The value of \$\$ref_to_string is $$ref_to_string\n\n"; my $waited_upon_child = wait; print "invoker $$: The PID of the child upon whom I waited was $waited_upon_child\n\n"; print "invoker $$: The value of \$ref_to_string is $ref_to_string\n"; print "invoker $$: After the call to the subroutine, the value of \$\$ref_to_string is finally $$ref_to_string\n\n"; print "invoker $$: I will now invoke the subroutine directly.\n\n"; do_subroutine ($ref_to_string); print "invoker $$: The value of \$ref_to_string is $ref_to_string\n"; print "invoker $$: After the call to the subroutine, the value of \$\$ref_to_string is finally $$ref_to_string\n\n"; sub do_subroutine { print "I am the subroutine and my PID is $$\n"; my $sub_ref_to_string = shift; print "Sub $$: The value of \$sub_ref_to_string is $sub_ref_to_string\n"; print "Sub $$: The value of \$\$sub_ref_to_string is $$sub_ref_to_string\n\n"; print "Sub $$: The preceding two messages confirm that I have access to the same\n"; print "Sub $$: memory location as the calling process even though I may be running\n"; print "Sub $$: in a different process from that of the calling process.\n\n"; # The following sleep instruction simulates time expended if this subroutine # were doing real work sleep (4); $$sub_ref_to_string = "Second value"; print "Sub $$: The value of \$sub_ref_to_string is still $sub_ref_to_string\n"; print "Sub $$: The value of \$\$sub_ref_to_string is now $$sub_ref_to_string\n"; print "Sub $$: I have changed the value of the scalar referenced by \$\$sub_ref_to_string (Heh-heh)\n\n"; } The output from this program is the following: I am the invoking process and my PID is 95864 invoker 95864: The value of $ref_to_string is SCALAR(0xe96dc0) invoker 95864: The value of $$ref_to_string is First value I am the subroutine and my PID is 95876 Sub 95876: The value of $sub_ref_to_string is SCALAR(0xe96dc0) Sub 95876: The value of $$sub_ref_to_string is First value Sub 95876: The preceding two messages confirm that I have access to the same Sub 95876: memory location as the calling process even though I may be running Sub 95876: in a different process from that of the calling process. Sub 95876: The value of $sub_ref_to_string is still SCALAR(0xe96dc0) Sub 95876: The value of $$sub_ref_to_string is now Second value Sub 95876: I have changed the value of the scalar referenced by $$sub_ref_to_string (Heh-heh) invoker 95864: The PID of the child upon whom I waited was 95876 invoker 95864: The value of $ref_to_string is SCALAR(0xe96dc0) invoker 95864: After the call to the subroutine, the value of $$ref_to_string is finally First value invoker 95864: I will now invoke the subroutine directly. I am the subroutine and my PID is 95864 Sub 95864: The value of $sub_ref_to_string is SCALAR(0xe96dc0) Sub 95864: The value of $$sub_ref_to_string is First value Sub 95864: The preceding two messages confirm that I have access to the same Sub 95864: memory location as the calling process even though I may be running Sub 95864: in a different process from that of the calling process. Sub 95864: The value of $sub_ref_to_string is still SCALAR(0xe96dc0) Sub 95864: The value of $$sub_ref_to_string is now Second value Sub 95864: I have changed the value of the scalar referenced by $$sub_ref_to_string (Heh-heh) invoker 95864: The value of $ref_to_string is SCALAR(0xe96dc0) invoker 95864: After the call to the subroutine, the value of $$ref_to_string is finally Second value The dilemma that I have is that it is clear that the child process knows the address of the variable in the parent space that it is to try to change, because upon invocation the child correctly reads and prints the value of the variable at that address. The child then modifies the value of the variable at that address and confirms within itself that the change has correctly taken place, again accessing the value at that address via the reference to that variable. When the child has finished its work, and the parent has finished waiting on the child, the parent then examines the value of the variable the address of which it had passed to the child. It turns out that the value is unchanged, as if the child had never run. Yet repeatedly across the code for the parent and the child, confirmation is printed that the value of the reference to the variable in question never changes. My program then goes on to have the parent invoke the child subroutine directly, not by delegating it to a child process, and then it is clear that the subroutine works as intended. Why would the value at the referenced address be modifiable by the subroutine when running in the same process as the invoker, but not when the subroutine is running in a different process but still clearly has full access to the address of the variable to be changed, as is evident by the fact that at its outset it can read the value at that address placed there by the parent? Thank you. In reply to Perl forked processes and variable sharing by fireblood
|
|