如何 fork n 个进程(n > 2)
讲到fork, 一个经典的例子如下:
if ((pid = fork()) == 0) {
? ? printf("in child %d\n", getpid());
} else if (pid > 0) {
? ? printf("in parent\n");
} else {
? ? perror("fork");
? ? exit(0);
}
现在, 我要创建5个进程, 每个进程都打印出自己的pid, ?写下如下代码:
?
#include <stdio.h>#include <stdlib.h>#define N_PROCESS 5int main(){ pid_t pid[N_PROCESS]; int i; /* create child process */ for (i = 0; i < N_PROCESS; i++) { if ((pid[i] = fork()) == 0) { printf("in child %d\n", getpid()); } else if (pid[i] > 0) { printf("in parent\n"); } } return 0;}?看似没有问题, 编译运行, 结果令人惊讶:
?
in parentin parentin parentin parentin parentin child 11799in parentin parentin parentin parentin child 11799in parentin parentin parentin child 11807in parentin parentin parentin child 11803in parentin parentin parentin parentin parentin child 11805in child 11799in parentin child 11804in parentin parentin child 11799in parentin parentin child 11806in child 11808in parentin parentin parentin child 11803in child 11809in parentin parentin child 11802in parentin parentin child 11799in child 11801in parentin parentin parentin child 11799in parentin child 11804in parentin child 11811in child 11799in child 11801in parentin child 11815in parentin parentin parentin child 11802in child 11812in parentin child 11799in child 11801in child 11813in parentin parentin parentin child 11800in parentin parentin parentin child 11799in parentin child 11804in child 11810in child 11817in parentin parentin child 11802in child 11812in child 11819in child 11799in child 11801in parentin parentin child 11816in parentin parentin child 11802in parentin child 11814in child 11799in child 11801in parentin child 11815in child 11818in parentin child 11800in parentin child 11822in parentin parentin child 11800in parentin parentin child 11824in child 11799in child 11801in child 11813in parentin child 11823in parentin child 11800in child 11820in parentin parentin parentin child 11800in parentin child 11822in child 11825in child 11799in child 11801in child 11813in child 11821in parentin parentin child 11800in child 11820in parentin child 11828in child 11799in child 11801in child 11813in child 11821in child 11826in parentin child 11800in child 11820in child 11827in child 11829
?
数一数, 程序创建了31个子进程! 怪哉, 哪里出问题了呢??
仔细分析一下, 第一次fork调用时, i = 0, fork完成后, 子进程和父进程拥有相同的存储,
即两者的 i = 0,然后父进程执行parent代码段, 打印 "in parent", 子进程执行child代码
段, 打印自己的pid. 关键是, 到了这里, 子进程没有退出, 处于for循环中, 于是子进程接着
执行 i = 1 时的for循环, 子进程执行fork,?又创建子进程, 这样就产生孙子进程. 按照这种
步骤, 孙子进程又会创建子进程....稍微分析一下, 可以得到递推公式,如果想创建n个子进程,
将执行 2^n - 1次fork调用并产生2^n-1个子进程, 真是子子孙孙无穷尽也...
可见, 问题的关键是, 终止子进程继续执行for循环, 修改代码:
?
#include <stdio.h>#include <stdlib.h>#define N_PROCESS 5int main(){ pid_t pid[N_PROCESS]; int i; /* create child process */ for (i = 0; i < N_PROCESS; i++) { if ((pid[i] = fork()) == 0) { printf("in child %d\n", getpid()); exit(0); /* 让子进程退出 */ } else if (pid[i] > 0) { printf("in parent\n"); } } return 0;}?运行结果如下:
?
in parentin child 12037in parentin parentin child 12039in child 12038in parentin child 12040in parentin child 12041
?
这次只创建了5个进程, 但parent代码段执行了5次, 不符合我们的要求, 再改:
?
#include <stdio.h>#include <stdlib.h>#define N_PROCESS 5int main(){ pid_t pid[N_PROCESS]; int i; /* create child process */ for (i = 0; i < N_PROCESS; i++) { if ((pid[i] = fork()) == 0) { printf("in child %d\n", getpid()); exit(0); /* 让子进程退出 */ } } printf("in parent\n"); return 0;}?
运行结果如下:
?
in child 12072in parentin child 12074in child 12075in child 12073in child 12076
?
嘎嘎, 这是我们期望的结果.