vfork将值返回给父级和子级

时间:2012-09-04 21:39:16

标签: c linux-kernel fork system-calls

#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);
    }

}

上述程序使用vfork创建进程。 因此,父母和孩子之间共享地址空间。 这意味着只有一个pid变量副本。 但是当我在子元素中打印pid变量时,它给出了0.父元素中的相同pid变量给出了子元素的进程id。 如果只有一个pid变量副本,这怎么可能。

2 个答案:

答案 0 :(得分:3)

假设您有一个真正的vfork,它不仅仅是根据fork实现的,那么该程序会调用严重的未定义行为。子进程中的printf将修改父进程的地址空间中的相同FILE对象(stdout),可能使其处于对父进程无效的状态。在实践中它可能会起作用,但如果确实如此,这是实施细节的结果,你不能依靠不改变。 vfork _exit之后唯一可以安全执行的操作是execprintf系列函数。

至于 如何工作(以vfork问题为模),vfork暂停父进程直到子进程终止,所以当{{1}}返回时父,孩子已经退出,新的返回值可以存储在旧孩子存放的同一位置。

答案 1 :(得分:0)

父节点从子节点后面的vfork()返回,所以pid被“正确”值覆盖。

在内核源代码树中,kernel / fork.c

在函数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.

}

您可以看到对 wait_for_vfork_done 的调用。 所以父母在这里等待vfork返回。 一旦孩子退出,父母就会从这里恢复。 孩子的pid从这里退回。 所以相同的pid变量在父级和子级中给出不同的值。