虚拟化 Ubuntu 上的奇怪进程行为

虚拟化 Ubuntu 上的奇怪进程行为

我使用 VirtualBox 在 Windows 8.1 上运行 Ubuntu 14.04 LTS。我正在接近操作系统,以下程序显示了一个奇怪的结果:

#include <stdio.h>
#include <unistd.h>
int main() {
printf("I'm the parent, my PID is %d, my parent is process %d\n",
getpid(), getppid());
fork();
printf("This sentence has been printed by process: %d my parent is process %d\n",
getpid(), getppid());
return 0;
}     

我用GCC编译并运行它。然后输出如下:

kocks@kocks-VirtualBox:~$ ./uno
I'm the parent, my PID is 3746, my parent is process 3507
This sentence has been printed by process: 3746 my parent is process 3507
kocks@kocks-VirtualBox:~$ This sentence has been printed by process: 3747 my parent is process 2857

问题出在第三句:我期望“我的父进程是3746”!特别是,数字 (2857) 始终相同,并且仅在重新启动 VM 后才会更改。有几点需要补充:

  1. 如果我wait()在返回之前添加一个,它就可以完美工作
  2. 当我尝试“拉皮条”虚拟机(比如给它两个处理器、更多的内存等)时,它有时会随机返回正确的输出

所以我认为问题出在虚拟机上,对吗?我怎么解决这个问题?

编辑 当在双引导下从 Ubuntu 运行程序时,输出如下:

I'm the parent, my PID is 3186, my parent is process 2454 
This sentence has been printed by process: 3186 my parent is process 2454
This sentence has been printed by process: 3187 my parent is process 3186

这怎么可能?

答案1

我在 2 个虚拟机设置上进行了测试,均使用 OS X 作为主机,并为每个客户端仅分配 1 个 CPU。

1 Ubuntu 14.04.2

在此设置中,在 X 窗口环境下,行为与 OP 匹配

john@U64D:~$ ./a
I'm the parent, my PID is 2682, my parent is process 2632
This sentence has been printed by process: 2682 my parent is process 2632
john@U64D:~$ This sentence has been printed by process: 2683 my parent is process 1673

父进程1673将保持不变,直到我注销并再次登录

john@U64D:~$ ./a
I'm the parent, my PID is 3787, my parent is process 3740
This sentence has been printed by process: 3787 my parent is process 3740
john@U64D:~$ This sentence has been printed by process: 3788 my parent is process 3107
./a
I'm the parent, my PID is 3790, my parent is process 3740
This sentence has been printed by process: 3790 my parent is process 3740
john@U64D:~$ This sentence has been printed by process: 3791 my parent is process 3107

第3107章初始化--用户

john@U64D:~$ ps -ef|grep 3107
john      3107  2911  0 15:07 ?        00:00:00 init --user

然而,在非 X 环境下(例如 tty1),结果将与 Barmar 答案匹配。

2 Debian 7.8

对于 X 和非 X 环境,此设置与 Barmar 答案相匹配。

约翰@debian:~$ ./a

I'm the parent, my PID is 3455, my parent is process 3406
This sentence has been printed by process: 3455 my parent is process 3406
john@debian:~$ This sentence has been printed by process: 3456 my parent is process 1

结论

OP 观察是 Ubuntu 在默认 X 环境中使用会话初始化的结果。可以找到session init的详细信息这里

答案2

如果您不使用wait(),则父级可以在子级有机会运行之前完成。当子进程调用 时getppid(),父进程已经退出,因此子进程被 收养init。在正常的 Unix 实现上, 的 PIDinit是 1,所以你会期望它说我的父母是进程1当这个情况发生时。但显然 VirtualBox 改变了这一点。

如果您使用wait(),这会使父级等待子级完成后再退出。这样孩子就永远不会成为孤儿。

相关内容