2

I don't get how the value is returned by a child process and to whom?

Output is 6, 7 ; question source: http://www.cs.utexas.edu/~mwalfish/classes/s11-cs372h/hw/sol1.html

Program 1: 
main() 
{ 
    val = 5; 
    if(fork()) 
    wait(&val); 
    val++; 
    printf("%d\n", val); 
    return val; 
}
Mayank Dixit
  • 71
  • 2
  • 5
  • @Zeta Running didn't explain the meaning of "wait(&val);" I tried :) – Mayank Dixit Dec 13 '12 at 07:20
  • On which platform is the output 6, 7? On Unix-based systems, the output would normally be 6, 1537. I would be willing to believe that on Windows, the result is 6, 7 — I'd be surprised if that was so on most other main-stream desktop platforms. What happens in the embedded world depends on the O/S, of course. – Jonathan Leffler Aug 26 '16 at 20:46

4 Answers4

5

Main process:

val = 5; 
wait(&val); // wait until child finishes

Child process:

val++; // val becomes 6
printf("%d\n", val); // prints 6
return val; // return val back to main process

Main process:

wait(&val); // val becomes 6
val++; // val becomes 7
printf("%d\n", val); // prints 7
return val; 
Vaughn Cato
  • 63,448
  • 5
  • 82
  • 132
  • Yah @VaughnCato the implementation is exactly like this. But i dont get the "wait(&val); // wait until child finishes" line. how this line means 'wait until child finishes' and also what happens to 'return val;' line when it is executed by child process. – Mayank Dixit Dec 13 '12 at 07:24
  • @MayankDixit: The man page for wait() says "The wait() system call suspends execution of the calling process until one of its children terminates." – Vaughn Cato Dec 13 '12 at 07:27
  • @MayankDixit: The function works by asking the kernel to wait for the child process. Are you wanting to know how it works internally to the kernel? – Vaughn Cato Dec 13 '12 at 07:29
  • look: wait(time_in_milisec.) means wait for given time, how come this understands wait for child to finish :( wait(&val) in my view should wait 30789 milisec. if &val=30789 .this is how I am looking the code. – Mayank Dixit Dec 13 '12 at 07:36
  • 1
    @MayankDixit: This is the `wait` function that the code is using: http://pubs.opengroup.org/onlinepubs/7908799/xsh/wait.html. I'm not sure which `wait` you are talking about. – Vaughn Cato Dec 13 '12 at 07:38
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/21055/discussion-between-mayank-dixit-and-vaughn-cato) – Mayank Dixit Dec 13 '12 at 07:59
  • Running on a Mac, the output is `6` from the child (which agrees with this answer) and `1537` from the parent, which is not the what I understand this answer to be saying. The classic layout for the value returned by `wait()` splits the result into two 8-bit fields. The low-order 8 bits are set to 0 to indicate a normal exit, or larger than zero to indicate death as a result of a signal, which signal, and whether a core was dumped; the high-order 8 bits (of a 16-bit value) are set to the low-order 8 bits of the value provided to `exit()` — or the value returned from `main()`, … _[…continued…]_ – Jonathan Leffler Aug 26 '16 at 20:40
  • 1
    _[…continuation…]_ The observed output (1537 = 0x0601) is consistent with this. The `val` set by `wait()` was 1536 or 0x0600, indicating controlled (normal) exit with status 6, and that was incremented to 1537 before being printed. This is the behaviour that I'd expect on any Unix-like system — Windows might produce the 6, 7 output claimed in the question. – Jonathan Leffler Aug 26 '16 at 20:47
  • Check below the output sorry to say that it is wrong. you need to mul it with 256. – Sohaib Aslam Mar 27 '18 at 20:23
  • @SohaibAslam The OP claims that their output is 6 and 7. My answer is just based on that. With a similar program, I get different output on my system, but I don't think that is relevant to the question. – Vaughn Cato Mar 27 '18 at 21:38
  • @VaughnCato if user claims that there output is 6 and 7 it doesn't mean that he is right, our duty is to awar users that what is right and what is wrong. Thanks brother ! But according to my output, user is wrong. – Sohaib Aslam Mar 27 '18 at 22:00
1
if(fork()) 

Creates a child process. Each process gets a copy of the var. fork returns a non-zero value in parent process. so the if gets executed only for the parent process. and wait is only called for parent process. It waits for child process to complete execution.

Child process increments val prints it and returns. Once it returns parent process resumes and executes further by incrementing var, printing its value and then returning from it from the main().

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

A fork() basically creates a new process. This means that all current values are going to be copied. This also concludes that val in your parent process isn't the val in your child process. This is the reason you'll have to communicate somehow with the child process, which you do by using wait.

      Parent Process       |       Child process
---------------------------|---------------------------
main()                     |
{                          | #########################
    int val = 5;           | // int val = parent.val;
**  int tmp = fork();      | ** int tmp = 0;
    if(tmp) // true        |    if(tmp) // false
        wait(&val);        |        // doesn't use wait
        // waits until     |    val++; // val = 6
        // child process   |    printf("%d\n", val); 
        // returns.        |    return val; // return 6
        // saves return    | ###########|############
        // value in val <---------------+
    val++; // val = 7      | #########################
    printf("%d\n", val);   | #########################
    return val;            | #########################
}

Whenever a process exits in Linux, the return value is stored temporary. As long as the parent process doesn't get this stored value the child process is still listed as zombie. This value can be acquired with wait. So whenever you use return <value> at the end of your application wait() in your caller will give you this return value.

Zeta
  • 103,620
  • 13
  • 194
  • 236
  • agin @zeta I really don't get how "return 6;" in child returns a value to variable val :( – Mayank Dixit Dec 13 '12 at 07:41
  • Function returns a value to calling function; if it is caught somewhere by calling function then it is ok.. or else it goes in vain; I get this. But in this code: don't know where value is returned and where it has been caught ? – Mayank Dixit Dec 13 '12 at 07:43
  • @MayankDixit: Added an explanation. Think of it like this: there is a giant tree in the operating system which contains the hierarchy of parent and their child processes. Whenever a child process exits, it will fill its leaf with its return value, which can then be acquired by the parent process. – Zeta Dec 13 '12 at 07:47
  • as in "int newVal= giveVal();" now return value is acquired by 'newVal' varaible. then in given case where the value is acquired, you guess? – Mayank Dixit Dec 13 '12 at 07:56
1

The above output is wrong.

Main process:


val = 5; 
wait(&val); // wait until child finishes

Child process:

val++; // val becomes 6
printf("%d\n", val); // prints 6
return val; // return val*256 back to main process

Main process:

wait(&val); // val becomes 6
val++; // val becomes 1792+1=1793
printf("%d\n", val); // prints 1793
return val; 

The above output is right if you add one line in a code !

Program 1: 
main() 
{ 
    val = 5; 
    if(fork()) 
    wait(&val); 

val=val/256 // if you add this line then the above output is correct

    val++; 
    printf("%d\n", val); 
    return val; 
}

it is due to

#define WEXITSTATUS(status) (((status)>>8) & 0xFF)
Sohaib Aslam
  • 1,245
  • 17
  • 27