我使用 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 后才会更改。有几点需要补充:
- 如果我
wait()
在返回之前添加一个,它就可以完美工作 - 当我尝试“拉皮条”虚拟机(比如给它两个处理器、更多的内存等)时,它有时会随机返回正确的输出
所以我认为问题出在虚拟机上,对吗?我怎么解决这个问题?
编辑 当在双引导下从 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()
,这会使父级等待子级完成后再退出。这样孩子就永远不会成为孤儿。