在下面显示的特殊情况之一中,使用 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

任何线索为什么?这是未定义行为案例之一吗?

使用 psstrace ,我可以看到正确的 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/

10-13 07:24