0
votes
#include<stdio.h>
#include<sys/types.h>
int main()
{
   pid_t pid;
   if((pid=vfork())<0)
    {
            perror("FORK ERROR");
            exit(1);
    }
    if(pid==0)
    {
            printf("[CHILD] child id : %d\n" , pid);
            _exit(1);
    }
    else
    {
            printf("[PARENT] process id : %d\n" , pid);
            exit(1);
    }

}

The above program uses vfork to create process. So , address space is shared between parent and child. It implies that there is only a single copy of pid variable. But when i print the pid variable in child it gives 0. The same pid variable in parent gives the process id of the child. How is this possible if there is only one copy of pid variable.

2
Only a single copy of pid is existing. Printing the address of pid in child and parent is same. As per vfork documentation also , both parent and child share the same address space.Prabagaran
possible duplicate of return value in vfork() system callninjalj
I've removed my answer; the duplicate question explains it much better.Kerrek SB

2 Answers

3
votes

Assuming you have a real vfork that's not just implemented in terms of fork, this program invokes serious undefined behavior. printf in the child process will modify the same FILE object (stdout) in the parent process's address space, possibly leaving it in a state that's not valid for the parent. In practice it may work, but if it does, that's a consequence of implementation details you cannot rely on not to change. The only operations that are safe to perform after vfork are _exit and the exec family of functions.

As for how it works (modulo the printf issue), vfork suspends the parent process until the child terminates, so when vfork returns in the parent, the child has already exited and the new return value is able to be stored at the same location the old one was stored in the child.

0
votes

The parent returns from vfork() after the child, so pid gets overwritten with the "correct" value.

In kernel source tree , kernel/fork.c

in function do_fork()

 do_fork()
 {
 ......
 if (clone_flags & CLONE_VFORK) {
                    p->vfork_done = &vfork;
                    init_completion(&vfork);
                    get_task_struct(p);
            }

            wake_up_new_task(p);

            /* forking complete and child started to run, tell ptracer */
            if (unlikely(trace))
                    ptrace_event(trace, nr);

            if (clone_flags & CLONE_VFORK) {
                    if (!wait_for_vfork_done(p, &vfork))
                            ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);
  .....
     return nr; // pid of the child process.

}

you can see that call to wait_for_vfork_done. so the parent is waiting here for vfork to return. once the child exits , parent resumes from here. child pid is returned from here. so the same pid variable gives different values in parent and child.