C vWork将值返回到父级和子级 #包括 #包括 int main() { pid_t pid; 如果((pid=vfork())
父项在子项之后从vfork()返回,则pid将被“正确”值覆盖 在内核源代码树中,kernel/fork.c 在函数do_fork()中 } 您可以看到对等待工作完成的调用。 因此,家长正在这里等待vWork返回。 一旦子级退出,父级将从此处恢复。 子pid从这里返回。C vWork将值返回到父级和子级 #包括 #包括 int main() { pid_t pid; 如果((pid=vfork()),c,linux-kernel,fork,system-calls,C,Linux Kernel,Fork,System Calls,父项在子项之后从vfork()返回,则pid将被“正确”值覆盖 在内核源代码树中,kernel/fork.c 在函数do_fork()中 } 您可以看到对等待工作完成的调用。 因此,家长正在这里等待vWork返回。 一旦子级退出,父级将从此处恢复。 子pid从这里返回。 因此,相同的pid变量在父项和子项中给出不同的值。父项在子项之后从vfork()返回,因此pid将被“正确”值覆盖 在内核源代码树中,kernel/fork.c 在函数do_fork()中 } 您可以看到对等待工作完成的调用。
因此,相同的pid变量在父项和子项中给出不同的值。父项在子项之后从vfork()返回,因此pid将被“正确”值覆盖 在内核源代码树中,kernel/fork.c 在函数do_fork()中 } 您可以看到对等待工作完成的调用。 因此,家长正在这里等待vWork返回。 一旦子级退出,父级将从此处恢复。 子pid从这里返回。
因此,同一个pid变量在父对象和子对象中给出不同的值。假设您有一个真正的
vWork
,它不仅仅是按照fork
实现的,这个程序调用严重的未定义行为。printf
子进程中的将修改相同的文件
对象(stdout
)在父进程的地址空间中,可能使其处于对父进程无效的状态。在实践中,它可能会工作,但如果工作,这是实现细节的结果,您不能依赖于不更改。在vWork
之后,唯一可以安全执行的操作是\u exit
和exec
fami功能的多样性
至于它是如何工作的(对printf
问题进行模块化),vfork
暂停父进程,直到子进程终止,因此当vfork
返回父进程时,子进程已经退出,新返回值可以存储在子进程中旧返回值存储的相同位置。假设您有一个真正的vfork
,而不仅仅是在fork
,此程序调用严重的未定义行为。子进程中的printf
将修改相同的文件
对象(stdout
)在父进程的地址空间中,可能使其处于对父进程无效的状态。在实践中,它可能会工作,但如果工作,这是实现细节的结果,您不能依赖于不更改。在vWork
之后,唯一可以安全执行的操作是\u exit
和exec
fami功能的多样性
至于它是如何工作的(对printf
问题进行模块化),vfork
暂停父进程,直到子进程终止,因此当vfork
返回到父进程时,子进程已经退出,新的返回值可以存储在与旧的返回值存储在子进程中相同的位置。只有一个pid副本存在。在子进程和父进程中打印pid的地址是相同的。根据vWork文档,父级和子级共享相同的地址空间。可能重复的我已删除我的答案;重复的问题解释得更好。只有一个pid副本存在。在子级和父级中打印pid地址是相同的。根据vWork文档,父级和子级也共享相同的地址空间相同的地址空间。可能重复的我已经删除了我的答案;重复的问题更好地解释了它。我对child使用了_exit(1)。如果(pid==0){printf(“[child]child id:%d\n”,pid);_exit(1);}这是绝对正确的。只有使用exit(1),它将关闭stdout并导致未定义的错误/调用printf
也是一个问题。这会修改stdout
,稍后将在父级中使用。vfork
不在任何现代标准中,而是原始定义(在SVID中,如果我记得正确的话)指定在vWork
之后调用\u exit
或exec
以外的任何内容都是UB。我已将_exit(1)用于child.if(pid==0){printf(“[child]child id:%d\n”,pid);\u exit(1)}这是绝对正确的。仅当您使用exit(1)时,它将关闭stdout并导致未定义的错误/调用printf
也是一个问题。这会修改stdout,稍后将在父级中使用。vfork
不在任何现代标准中,而是原始定义(在SVID中,如果我记得正确的话)指定在vWork
之后调用除\u exit
或exec
以外的任何内容都是UB。
#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);
}
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.