如何 fork n 个进程(n > 2)

本文通过一个具体的编程案例,深入解析了Fork机制的工作原理及如何正确使用。文章演示了如何利用Fork创建指定数量的子进程,并展示了在实际操作过程中需要注意的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

讲到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,  写下如下代码:

 

C代码   收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define N_PROCESS 5  
  5.   
  6. int main()  
  7. {  
  8.     pid_t pid[N_PROCESS];  
  9.     int i;   
  10.   
  11.     /* create child process */  
  12.     for (i = 0; i < N_PROCESS; i++) {  
  13.         if ((pid[i] = fork()) == 0) {  
  14.             printf("in child %d\n", getpid());  
  15.         } else if (pid[i] > 0) {  
  16.             printf("in parent\n");  
  17.         }  
  18.     }  
  19.   
  20.     return 0;  
  21. }  
 

看似没有问题, 编译运行, 结果令人惊讶:

 

C代码   收藏代码
  1. in parent  
  2. in parent  
  3. in parent  
  4. in parent  
  5. in parent  
  6. in child 11799  
  7. in parent  
  8. in parent  
  9. in parent  
  10. in parent  
  11. in child 11799  
  12. in parent  
  13. in parent  
  14. in parent  
  15. in child 11807  
  16. in parent  
  17. in parent  
  18. in parent  
  19. in child 11803  
  20. in parent  
  21. in parent  
  22. in parent  
  23. in parent  
  24. in parent  
  25. in child 11805  
  26. in child 11799  
  27. in parent  
  28. in child 11804  
  29. in parent  
  30. in parent  
  31. in child 11799  
  32. in parent  
  33. in parent  
  34. in child 11806  
  35. in child 11808  
  36. in parent  
  37. in parent  
  38. in parent  
  39. in child 11803  
  40. in child 11809  
  41. in parent  
  42. in parent  
  43. in child 11802  
  44. in parent  
  45. in parent  
  46. in child 11799  
  47. in child 11801  
  48. in parent  
  49. in parent  
  50. in parent  
  51. in child 11799  
  52. in parent  
  53. in child 11804  
  54. in parent  
  55. in child 11811  
  56. in child 11799  
  57. in child 11801  
  58. in parent  
  59. in child 11815  
  60. in parent  
  61. in parent  
  62. in parent  
  63. in child 11802  
  64. in child 11812  
  65. in parent  
  66. in child 11799  
  67. in child 11801  
  68. in child 11813  
  69. in parent  
  70. in parent  
  71. in parent  
  72. in child 11800  
  73. in parent  
  74. in parent  
  75. in parent  
  76. in child 11799  
  77. in parent  
  78. in child 11804  
  79. in child 11810  
  80. in child 11817  
  81. in parent  
  82. in parent  
  83. in child 11802  
  84. in child 11812  
  85. in child 11819  
  86. in child 11799  
  87. in child 11801  
  88. in parent  
  89. in parent  
  90. in child 11816  
  91. in parent  
  92. in parent  
  93. in child 11802  
  94. in parent  
  95. in child 11814  
  96. in child 11799  
  97. in child 11801  
  98. in parent  
  99. in child 11815  
  100. in child 11818  
  101. in parent  
  102. in child 11800  
  103. in parent  
  104. in child 11822  
  105. in parent  
  106. in parent  
  107. in child 11800  
  108. in parent  
  109. in parent  
  110. in child 11824  
  111. in child 11799  
  112. in child 11801  
  113. in child 11813  
  114. in parent  
  115. in child 11823  
  116. in parent  
  117. in child 11800  
  118. in child 11820  
  119. in parent  
  120. in parent  
  121. in parent  
  122. in child 11800  
  123. in parent  
  124. in child 11822  
  125. in child 11825  
  126. in child 11799  
  127. in child 11801  
  128. in child 11813  
  129. in child 11821  
  130. in parent  
  131. in parent  
  132. in child 11800  
  133. in child 11820  
  134. in parent  
  135. in child 11828  
  136. in child 11799  
  137. in child 11801  
  138. in child 11813  
  139. in child 11821  
  140. in child 11826  
  141. in parent  
  142. in child 11800  
  143. in child 11820  
  144. in child 11827  
  145. in 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循环, 修改代码:

 

C代码   收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define N_PROCESS 5  
  5.   
  6. int main()  
  7. {  
  8.     pid_t pid[N_PROCESS];  
  9.     int i;   
  10.   
  11.     /* create child process */  
  12.     for (i = 0; i < N_PROCESS; i++) {  
  13.         if ((pid[i] = fork()) == 0) {  
  14.             printf("in child %d\n", getpid());  
  15.             exit(0);     /* 让子进程退出 */  
  16.         } else if (pid[i] > 0) {  
  17.             printf("in parent\n");  
  18.         }  
  19.     }  
  20.   
  21.     return 0;  
  22. }  
 

运行结果如下:

 

C代码   收藏代码
  1. in parent  
  2. in child 12037  
  3. in parent  
  4. in parent  
  5. in child 12039  
  6. in child 12038  
  7. in parent  
  8. in child 12040  
  9. in parent  
  10. in child 12041  

 

这次只创建了5个进程, 但parent代码段执行了5次, 不符合我们的要求, 再改:

 

C代码   收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. #define N_PROCESS 5  
  5.   
  6. int main()  
  7. {  
  8.     pid_t pid[N_PROCESS];  
  9.     int i;   
  10.   
  11.     /* create child process */  
  12.     for (i = 0; i < N_PROCESS; i++) {  
  13.         if ((pid[i] = fork()) == 0) {  
  14.             printf("in child %d\n", getpid());  
  15.             exit(0);    /* 让子进程退出 */  
  16.         }   
  17.     }  
  18.   
  19.     printf("in parent\n");  
  20.   
  21.     return 0;  
  22. }  

 

运行结果如下:

 

C代码   收藏代码
  1. in child 12072  
  2. in parent  
  3. in child 12074  
  4. in child 12075  
  5. in child 12073  
  6. in child 12076  

 

嘎嘎, 这是我们期望的结果.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值