0
#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 变量只有一个副本,这怎么可能。

4

2 回答 2

3

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

至于它是如何工作的(以问题为模printf),vfork暂停父进程直到子进程终止,所以当在父进程中vfork返回时,子进程已经退出并且新的返回值能够存储在旧的相同位置是储存在孩子身上。

于 2012-09-04T22:41:24.127 回答
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 变量在父子节点中给出不同的值。

于 2012-09-04T22:36:11.993 回答