请考虑以下代码:
#include <stdio.h>
#include <unistd.h>
int main()
{
fork();
fork() && fork() || fork();
fork();
printf("forked\n");
return 0;
}
问题是forked
将被打印多少次。根据我的分析,它应该被打印20次。此外,this的答案也证实了这一点。
但是,当我在onlinegdb.com和ideone.com上运行代码时,它们分别打印18次和5次。为什么这样?
答案 0 :(得分:4)
您的代码不会创建任何线程。这些线程在Linux上称为Pthreads,您将使用pthread_create(3)(内部使用clone(2))创建它们。
当然,您的代码正在(错误地)使用fork(2),因此它会创建processes (除非fork
失败)。请注意, fork
难以理解(并且难以解释),并且难以解释(因此我什至不在这里尝试)。您可能需要阅读很多相关内容,例如fork Wikipage,ALP,甚至还有Operating Systems: Three Easy Pieces(都有几个章节对其进行解释)。
您应该处理fork
的失败。如here所述,每种fork
都需要考虑三种情况,您最好重写代码,使每个语句最多执行fork
个(像pid_t pida = fork();
)
顺便说一句,最好在每个fork
前刷新标准流(及其缓冲区中的数据)。我建议通过在每个fflush(NULL);
之前调用fork
来使用fflush(3)。
请注意,每个进程都有自己的(唯一)pid(请参见getpid(2)和credentials(7))。如果您进行打印,可能会更好地理解,因此请尝试使用
printf("forked in %ld\n", (long) getpid());
运行代码时
您确实应该在Linux下的您的计算机上运行该代码。考虑在笔记本电脑或台式机上安装Linux distribution(可能在某些虚拟机中)。请注意,Linux非常适合开发人员和学生,并且主要由free software组成,您可以学习其源代码。
它们分别打印18次和5次。为什么这样?
免费的Web服务应限制外部客户端使用的资源(在Linux上,它们可能会为此目的使用setrlimit(2))。显然,此类站点能够运行几乎任意的C代码,都希望避免使用fork bombs。很可能您的某些fork
失败了(并且由于原始代码不检查失败,所以您没有注意到)。
即使在您自己的桌面上,您也无法创建很多进程。根据经验,您的计算机上可能有数百个进程,其中大多数进程为idle(正在等待,可能是poll(2)或阻塞的read(2)等,...有关某些IO或某些超时的信息,另请参见time(7)),并且其中只有十几个是可运行的(由process scheduler的kernel来运行)。换句话说,过程是相当昂贵的计算资源。如果您有太多可运行的进程,则可以尝试thrashing。
使用ps(1)和top(1)(还有htop
和pgrep(1))来查询Linux系统上的进程。如果要通过编程方式执行此操作,请使用/proc/
(并参见proc(5))-ps
,top
,pgrep
,{{ 1}}等...