这是一个代码,我一个接一个地使用2个fork()系统调用 - 它是如何运作的?
#include <unistd.h>
#include <iostream.h>
using namespace std;
int main()
{
cout << "0. I am process " << getpid() << endl;
(void) fork();
cout << "1. I am process " << getpid() << endl;
(void) fork();
cout << "2. I am process " << getpid() << endl;
}
我得到的输出为:
我是程序27701
1.我是流程25915
1.我是流程27701
2.我是流程27781
2.我是流程26170
2.我是程序27701
这是我使用3个fork系统调用的下一个程序,如何获得这样的输出?如果我手动解决这个代码,逻辑是什么?
#include <unistd.h>
#include <iostream>
using namespace std;
int main()
{
cout << "0. I am process " << getpid() << endl;
(void) fork();
cout << "1. I am process " << getpid() << endl;
(void) fork();
cout << "2. I am process " << getpid() << endl;
(void) fork();
cout << "3. I am process " << getpid() << endl;
}
这里我得到的输出为:
我是流程27116
1.我是流程26147
2.我是程序27371
2.我是流程26147
3.我是程序24416
3.我是流程27371
3.我是流程27508
3.我是流程26147
1.我是程序27116
2.我是流程21406
2.我是程序27116
3.我是流程27369
3.我是程序21406
3.我是流程26752
3.我是程序27116
答案 0 :(得分:5)
fork()
的工作方式都相同。创建一个新进程作为当前进程的精确副本,并且两者都继续执行,就像它们刚从fork()
函数调用返回一样,只是返回值不同。在你的情况下,你扔掉了那个返回值,所以它们只是相同的过程。
让我们为您的第一个例子画一幅画。我刚刚进行的一次运行的示例输出(因为您在问题中输出的输出不完整):
0. I am process 25597
1. I am process 25597
2. I am process 25597
1. I am process 25598
2. I am process 25599
2. I am process 25598
2. I am process 25600
首先使用PID 25597进行单个处理。它打印0
行,然后打印。这产生了两个过程:
25597 # prints "0"
/\
/ \
/ \
25597 25598 # both print "1"
到目前为止一切顺利。现在这两个新进程再次调用fork()
。完整的树最终看起来像这样:
25597
/\
/ \
/ \
/ \
/ \
25597 25598 # both print "1"
/\ /\
/ \ / \
/ \ / \
25597 25599 25598 25600 # all four print "2"
不幸的是,无法从输出中猜出25599和25600的实际位置 - 它们也可能是相反的。
对于你的3 - fork()
示例,你只需要做同样的事情,但它会在图表中有另一个级别 - 你最终将有8个进程,每个进程打印“3”行。< / p>
答案 1 :(得分:1)
你的节目完全错了。您应该永远不会忽略fork
的结果。
阅读Advanced Linux programming书籍和fork(2)手册页(多次仔细阅读该页面)。
典型代码应为:
pid_t pid1 = fork();
if (pid1<0) { perror("fork1 failed"); exit(EXIT_FAILURE); }
else if (pid1 == 0) {
// you are in the child process
}
else // pid1>0
{ // you are in the parent process
}
同样适用于pid_t pid2=fork();
,然后适用于pid_t pid3=fork();
等......
因此,对fork
的每次调用都应该处理fork
的结果的3个案例(失败即<0
,子进程==0
,父进程>0
)
原则上,你有3 3 ,即27种可能性。但你可以尽早处理失败的情况,即2 3 ,即8种可能性
不要忘记处理fork
的失败。您可以降低流程限制(setrlimit(2)使用RLIMIT_NPROC
或等效的ulimit bash内置)以简化fork
失败的测试。
答案 2 :(得分:0)
只需绘制一个树,其中每个根节点都是一个fork调用,叶节点就是它后面的代码。
在第一个程序中,你的cout&lt;&lt;“0 ...”是父程序,在fork调用之后,该行之后的整个程序执行两次.Hen两个“1 .. 。“输出线。
在此之后还有另一个叉号。这次有3个进程在运行(1.你调用的原始父进程,2。它生成的子进程3.子进程产生了另一个孙子。)因此3“2 ......”输出行。
答案 3 :(得分:0)
调用fork()时,会创建并运行子进程。因此,您将在子进程中执行以下语句:
cout << "1. I am process " << getpid() << endl;
此外,当调用另一个fork时,会创建另一个子进程,该进程运行下一个'cout'语句。但是,父进程也会运行。这也发生在第三个fork()上。
所有这些都发生在第一个fork()的子进程中。在此之后,第一个fork的父进程也会运行以显示您的输出。