我想知道为以下代码创建的进程数。我从我的老师那里知道答案是 41,但我无法遵循相同的答案。请用进程树解释相同的内容。
void main() {
for (i=0;i<2;i++){
fork();
if(!fork()) {
execl("/bin/ls","ls",NULL);
fork();
}
fork();
}
fork();
}
这看起来像一个家庭作业问题。如果我们为您绘制一个进程树,您现在可能会得到一些分数,但您将不会学习如何分析程序,这可能会在以后伤害您。您将通过了解该程序的工作原理了解更多信息。(当然,这个程序是一个学术例子,除了学习之外不是很有用。
我建议用字母标记fork
电话。
int main(void) {
for (int i = 0; i < 2; i++) {
fork(); /* A */
if(!fork()) { /* B */
execl("/bin/ls","ls",NULL);
fork(); /* C */
}
fork(); /* D */
}
fork(); /* E */
}
拿起纸和铅笔,写下发生的事情,并使用循环计数器和标记的fork
调用绘制一棵树。
例:
程序运行两个循环(0 和 1),循环在所有进程中继续。
在父P
,循环循环0
,fork
A
将创建子1
.P -(0,A)-> 1
仍然在循环循环0
中,P
和1
都将在条件内运行fork
B
,分别创建一个新的子项.P -(0,B)-> 2
,1 -(0,B)-> 3
。
考虑条件的含义,并确定哪些进程运行条件块。
想想execl
之后会发生什么,例如进程x
执行ls
,导致......
一些进程(命名它们)将达到D
并为每个进程创建一个子进程,所有进程将继续循环循环1
......
等。
要查看会发生什么,您可以在每次fork
后添加一些输出以显示发生的情况:哪个循环索引,哪个fork
,是此fork
,PID,父PID的进程父或子。在execl
显示哪个PID即将调用它之前。(请注意,像printf
这样的缓冲输出可能会与fork
结合使用时显示意外行为,因此最好使用sprintf
和write
。运行该程序将产生可以帮助您绘制进程树的输出。甚至可以格式化输出,以便使用graphviz或PlantUML自动生成树。所有这些都是高级主题。