fork() 在这里做什么?
What is fork() doing here?
所以我想弄清楚这段代码在做什么:
int k = 5;
if(fork() == fork()) ++k; else --k;
printf("%d\n", k);
困扰我的是我收到不同的输出:
4
4
4
6
4
4
4
4
4
6
4
4
4
6
4
6
4
4
我添加了一个 PID 检测器,所以我看到了所有进程的 ID:
int main ()
{
int k = 5;
if(fork() == fork()) ++k; else --k;
printf("%d\n", k);
int pid;
pid = fork();
if(pid == 0)
{
printf("\n Process id : %d",getpid());
printf("\n Parrent process id : %d\n" ,getppid());
}
return 0;
}
但有时我得到输出:
Process id : 9472
Parrent process id : 1413
Process id : 9474
Parrent process id : 1413
Process id : 9471
Parrent process id : 1413
Process id : 9473
Parrent process id : 1413
或:
Process id : 9557
Parrent process id : 1413
Process id : 9556
Parrent process id : 1413
Process id : 9558
Parrent process id : 9554
Process id : 9559
Parrent process id : 9553
请让我明白这里发生了什么。
我将 children 的原始代码扩展为 wait
,这样您一定会获得所有输出并添加更多输出。
你有两个fork
所以总共有四个进程。
只有在其中一个过程中,fork() == fork()
才会成为 true
。这是当这两个 fork()
中的第一个 returns 被调用到 child 进程时,下一个 fork()
被调用,同时 returns 被调用到 child 进程。
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
const char *foo(pid_t a, pid_t b) {
if (a == b) return "child,child";
if (a && b) return "parent,parent";
if (a) return "parent,child";
return "child,parent";
}
int main() {
int k = 5;
pid_t p1, p2;
if ((p1 = fork()) == (p2 = fork())) {
++k;
} else {
--k;
}
printf("%d %s\tppid=%d pid=%d\n", k, foo(p1, p2), getppid(), getpid());
int wstatus;
if (p1) wait(&wstatus);
if (p2) wait(&wstatus);
}
示例输出。请注意,顺序可能会更改,因为所有进程同时 运行。
6 child,child ppid=2 pid=4
4 parent,child ppid=1 pid=3
4 child,parent ppid=1 pid=2
4 parent,parent ppid=0 pid=1
这里第一个进程 1
创建了 2
和 3
并且在创建 2
的情况下我们得到了 fork() == fork()
.
1
/ \
2 3
/
4
The thing that bothers me is that I receive different outputs:
代码无条件呈现fork()
s 两次。第一个fork
成功后,原来有一个的进程变成了两个。 两个都执行第二个fork
,所以,假设所有fork
调用都成功,最终有四个进程。
成功时,fork()
returns child PID 到原始进程,0 到 child。失败时,它 returns -1 到 parent(没有 child)。如果实际上两个 fork
都成功,那么所有生成的进程的 PID 都会不同,因此 fork() == fork()
将评估为 true 的唯一情况是第一个 child 的 child =],其中两个 fork()
调用都将返回 0。仅在该过程中,k
将递增;在其他进程中它将被递减。
进程不共享内存,因此增量和减量分别反映在各个进程的单独副本中 k
。没有对各种进程 运行 的顺序施加控制,原则上它们可以按任何顺序打印它们的 k
值。这涵盖了观察到的三个输出。
但是只打印三个 k
值的情况呢?最可能的解释是第一个 fork()
成功,但在其中一个结果过程中,第二个失败,返回 -1。如果 fork()
失败发生在原始进程中,那么第二个 fork()
的成功实例仍将产生一个进程,其中 fork() == fork()
的计算结果为真。另一方面,如果 fork
失败发生在第一个 child 中,那么 fork() == fork()
中的任何进程都不会评估为真。这将解释两个 three-output 结果。
就 PID 和 PPID 而言,似乎让您感到困惑的一件事是某些进程的 parent 进程终止的影响。初始进程 always 以外的进程的 parent 有一个活动进程。如果进程 P
的原始 parent 在 P
本身终止之前终止,则分配一个不同的 parent; 在 POSIX-conforming 系统上,这将是进程 1。
因为您的程序没有做任何事情来确保 parent 进程比它们的 children 更长寿,所以您有时会看到某些原始 parents 在它们的 child仁。这解释了 PPID 模式的变化。但是,关于新 parent 的分配细节,您似乎 运行 在一个不符合 POSIX 的环境(大概是某种容器)中运行您的程序,这在某种程度上掩盖了该问题的根源。
所以我想弄清楚这段代码在做什么:
int k = 5;
if(fork() == fork()) ++k; else --k;
printf("%d\n", k);
困扰我的是我收到不同的输出:
4
4
4
6
4
4
4
4
4
6
4
4
4
6
4
6
4
4
我添加了一个 PID 检测器,所以我看到了所有进程的 ID:
int main ()
{
int k = 5;
if(fork() == fork()) ++k; else --k;
printf("%d\n", k);
int pid;
pid = fork();
if(pid == 0)
{
printf("\n Process id : %d",getpid());
printf("\n Parrent process id : %d\n" ,getppid());
}
return 0;
}
但有时我得到输出:
Process id : 9472
Parrent process id : 1413
Process id : 9474
Parrent process id : 1413
Process id : 9471
Parrent process id : 1413
Process id : 9473
Parrent process id : 1413
或:
Process id : 9557
Parrent process id : 1413
Process id : 9556
Parrent process id : 1413
Process id : 9558
Parrent process id : 9554
Process id : 9559
Parrent process id : 9553
请让我明白这里发生了什么。
我将 children 的原始代码扩展为 wait
,这样您一定会获得所有输出并添加更多输出。
你有两个fork
所以总共有四个进程。
只有在其中一个过程中,fork() == fork()
才会成为 true
。这是当这两个 fork()
中的第一个 returns 被调用到 child 进程时,下一个 fork()
被调用,同时 returns 被调用到 child 进程。
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
const char *foo(pid_t a, pid_t b) {
if (a == b) return "child,child";
if (a && b) return "parent,parent";
if (a) return "parent,child";
return "child,parent";
}
int main() {
int k = 5;
pid_t p1, p2;
if ((p1 = fork()) == (p2 = fork())) {
++k;
} else {
--k;
}
printf("%d %s\tppid=%d pid=%d\n", k, foo(p1, p2), getppid(), getpid());
int wstatus;
if (p1) wait(&wstatus);
if (p2) wait(&wstatus);
}
示例输出。请注意,顺序可能会更改,因为所有进程同时 运行。
6 child,child ppid=2 pid=4
4 parent,child ppid=1 pid=3
4 child,parent ppid=1 pid=2
4 parent,parent ppid=0 pid=1
这里第一个进程 1
创建了 2
和 3
并且在创建 2
的情况下我们得到了 fork() == fork()
.
1
/ \
2 3
/
4
The thing that bothers me is that I receive different outputs:
代码无条件呈现fork()
s 两次。第一个fork
成功后,原来有一个的进程变成了两个。 两个都执行第二个fork
,所以,假设所有fork
调用都成功,最终有四个进程。
成功时,fork()
returns child PID 到原始进程,0 到 child。失败时,它 returns -1 到 parent(没有 child)。如果实际上两个 fork
都成功,那么所有生成的进程的 PID 都会不同,因此 fork() == fork()
将评估为 true 的唯一情况是第一个 child 的 child =],其中两个 fork()
调用都将返回 0。仅在该过程中,k
将递增;在其他进程中它将被递减。
进程不共享内存,因此增量和减量分别反映在各个进程的单独副本中 k
。没有对各种进程 运行 的顺序施加控制,原则上它们可以按任何顺序打印它们的 k
值。这涵盖了观察到的三个输出。
但是只打印三个 k
值的情况呢?最可能的解释是第一个 fork()
成功,但在其中一个结果过程中,第二个失败,返回 -1。如果 fork()
失败发生在原始进程中,那么第二个 fork()
的成功实例仍将产生一个进程,其中 fork() == fork()
的计算结果为真。另一方面,如果 fork
失败发生在第一个 child 中,那么 fork() == fork()
中的任何进程都不会评估为真。这将解释两个 three-output 结果。
就 PID 和 PPID 而言,似乎让您感到困惑的一件事是某些进程的 parent 进程终止的影响。初始进程 always 以外的进程的 parent 有一个活动进程。如果进程 P
的原始 parent 在 P
本身终止之前终止,则分配一个不同的 parent; 在 POSIX-conforming 系统上,这将是进程 1。
因为您的程序没有做任何事情来确保 parent 进程比它们的 children 更长寿,所以您有时会看到某些原始 parents 在它们的 child仁。这解释了 PPID 模式的变化。但是,关于新 parent 的分配细节,您似乎 运行 在一个不符合 POSIX 的环境(大概是某种容器)中运行您的程序,这在某种程度上掩盖了该问题的根源。