在下面显示的特殊情况之一中,使用 getpid()
创建的孙子进程的 vfork()
返回父进程的 PID。
#include <stdio.h>
#include <stdlib.h>
int main() {
if(vfork()) { /* parent */
printf("parent pid = %d\n", getpid());
exit(0);
} else {
if(vfork()) { /* child */
printf("child pid = %d\n", getpid());
exit(0);
} else { /* grandchild */
printf("grandchild pid = %d\n", getpid());
exit(0);
}
}
}
编译为
gcc main.c
,这按预期工作:grandchild pid = 12241
child pid = 12240
parent pid = 12239
编译为
gcc main.c -lpthread
,孙子PID不正确:grandchild pid = 12431
child pid = 12432
parent pid = 12431
任何线索为什么?这是未定义行为案例之一吗?
使用
ps
和 strace
,我可以看到正确的 PID。顺便说一句,相同的示例代码适用于 fork()
,即正确的 getpid()
有或没有 -lpthread
。 最佳答案
getpid
不是你被允许在 child 的 vfork
之后执行的两个操作之一;仅有的两个是 execve
和 _exit
。碰巧 glibc 将进程的 pid 缓存在用户空间中,并且不会在 vfork
上更新此缓存(因为它会修改父级的缓存值,并且由于有效代码无法观察结果而不需要它);这就是你所看到的行为机制。缓存行为与链接的 -lpthread
略有不同。但根本原因是您的代码无效。
几乎, 不使用 vfork
。基本上你无能为力。
关于c - 带有 vfork() 和 -lpthread 的孙子的 getpid() 结果不正确,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60006155/