如何 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 5

int 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 parent
in parent
in parent
in parent
in parent
in child 11799
in parent
in parent
in parent
in parent
in child 11799
in parent
in parent
in parent
in child 11807
in parent
in parent
in parent
in child 11803
in parent
in parent
in parent
in parent
in parent
in child 11805
in child 11799
in parent
in child 11804
in parent
in parent
in child 11799
in parent
in parent
in child 11806
in child 11808
in parent
in parent
in parent
in child 11803
in child 11809
in parent
in parent
in child 11802
in parent
in parent
in child 11799
in child 11801
in parent
in parent
in parent
in child 11799
in parent
in child 11804
in parent
in child 11811
in child 11799
in child 11801
in parent
in child 11815
in parent
in parent
in parent
in child 11802
in child 11812
in parent
in child 11799
in child 11801
in child 11813
in parent
in parent
in parent
in child 11800
in parent
in parent
in parent
in child 11799
in parent
in child 11804
in child 11810
in child 11817
in parent
in parent
in child 11802
in child 11812
in child 11819
in child 11799
in child 11801
in parent
in parent
in child 11816
in parent
in parent
in child 11802
in parent
in child 11814
in child 11799
in child 11801
in parent
in child 11815
in child 11818
in parent
in child 11800
in parent
in child 11822
in parent
in parent
in child 11800
in parent
in parent
in child 11824
in child 11799
in child 11801
in child 11813
in parent
in child 11823
in parent
in child 11800
in child 11820
in parent
in parent
in parent
in child 11800
in parent
in child 11822
in child 11825
in child 11799
in child 11801
in child 11813
in child 11821
in parent
in parent
in child 11800
in child 11820
in parent
in child 11828
in child 11799
in child 11801
in child 11813
in child 11821
in child 11826
in parent
in child 11800
in child 11820
in child 11827
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循环, 修改代码:

 

#include <stdio.h>
#include <stdlib.h>

#define N_PROCESS 5

int 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 parent
in child 12037
in parent
in parent
in child 12039
in child 12038
in parent
in child 12040
in parent
in child 12041

 

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

 

#include <stdio.h>
#include <stdlib.h>

#define N_PROCESS 5

int 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 12072
in parent
in child 12074
in child 12075
in child 12073
in child 12076

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值