在unix中使用fork

问题描述:

我正在尝试学习fork并在两个fork()之间碰到&&。在使用fork()命令时,&&||如何工作。举例来说,如果我有类似如下─在unix中使用fork

fork(); 
fork() && fork() || fork(); 
fork() && fork(); 

这些行执行后催生的进程数为29或30怎么能够得到这样一个结论?

+0

'fork'返回0给孩子。 –

+0

是的,我知道它返回0给孩子和孩子的进程ID本身。所以他们是正常的逻辑运算符。但是,为什么最后没有进程是29或30 – Joker

+1

它不是* 29或30 *。 29生成。 30是进程的总数。原来的过程算作一个,另外29个在执行过程中产生。查看我的答案获取更多详情。 –

让我们暂时搁置一会儿,考虑&&||操作员的行为。对这些使用fork(2)没有什么特别之处(尽管这是不必要的混淆,应该只为教育目的而完成)。

回想一下,这些是短路操作,即只评估必要的操作数。在a || b中,首先评估a;如果它具有真实值,则b未被评估,因为||的结果已知,否则将评估b。同样,首先评估a && b,a;如果它有一个错误值,b不会被评估,否则,b被评估以确定结果。

考虑到这一点,让我们逐步计算进程的数量。这个答案的其余部分假定fork(2)总是成功的。

第一行

fork(); 

这条线之后,我们产生了总共1个的过程,和有2个上运行的活动进程。

二线

fork() && fork() || fork(); 

&&||更高的优先级,所以这相当于:

(fork() && fork()) || fork(); 

所以,我们有2个进程执行此。对第一个fork()进行评估并创建一个新过程。它在新进程中返回0,因此该进程中的第二个fork()将不会被评估。请记住,这会发生两次(我们有2个进程) - 我们现在有4个进程。其中两个,第一个fork(2)返回0,所以第二个fork()没有执行,但是,第三个fork(2)将因为||语义。在另外两个,fork()返回非零,所以第二个fork()将被评估,因为它是&&的一部分。

所以前两个调用最后一个fork()||右边的那个),再次分叉,为进程池添加2个新进程。我们现在有6个进程。其他2在第二fork():再次,2个新进程的创建,提高了处理计数到8

现在的情况是类似的:这两个新流程的家长看到fork()回报不为零,所以他们不要致电第三个fork(),因为||的结果现在已知。这两个孩子看到fork()返回0,所以他们继续评估该线上的第三个和最后一个fork(),创建2个更多的进程:我们现在有10个进程。

三线

fork() && fork(); 

好吧,我们有10个流程,要执行这条线。语义相同:10个进程中的每一个执行第一个fork(),使进程数量为20个。在20个进程中,其中10个进程(该行中第一个fork()的所有子进程)将看到fork(2)返回0 ,所以他们不会移动到第二个fork()。其他10位 - 父母 - 将会看到fork()返回非零,因此他们会拨打第二位fork()来确定&&的最终结果。一起,它们都创建10个以上过程,提高的进程总数为30。

摘要

最后,我们有30个正在运行的进程(总共29个生成)。您可以通过在最终打印和输出计算行数证实了这一点:

#include <stdio.h> 
#include <unistd.h> 

int main(void) { 
    fork(); 
    fork() && fork() || fork(); 
    fork() && fork(); 
    printf("PID = %ld\n", (long) getpid()); 
    return 0; 
} 

实例运行:

$ ./a.out | wc -l 
     30 
+2

你是一个圣人;-) – shellter