`
kenby
  • 浏览: 717153 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

 

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

分享到:
评论

相关推荐

    实验3的用户进程实现

    本资源为我的博客《实验3正篇——用户进程》的附件,其中主要包含了实验3的代码实现,注意该代码可能有部分bug,但是在之后的实验中修复了,还包含了许多流程图或者逻辑图,与前篇的部分文件。希望能对感兴趣的人员...

    操作系统进程管理实验报告

    if(pid1 &gt; 0) { // 子进程创建成功,pid1为进程号 while((pid2 = fork( )) == -1); // 创建子进程2 if(pid2 &gt; 0) { wait_flag = 1; //sleep(1); // 父进程等待5秒 kill(pid1,SIGUSR1)...

    一个进程池的服务器程序

    2,父进程预fork n个子进程 3,各个子进程accept(listenfd),即所有子进程竞争accept请求。由于listenfd是在fork之前就有的,所以所有子进程都可以访问到,不需用到“进程间文件描述符传递”问题; 4,子进程每...

    进程通信.doc

    实际上,通常先创建一个管道,再通过fork函数创建一个子进程。图见附件。 子进程写入和父进程读的命名管道:图见附件 管道读写注意事项: 可以通过打开两个管道来创建一个双向的管道。但需要在子理程中正确地设置...

    管道机制实现进程间的通信

    操作系统课程作业(本人亲自...b) 子进程调用函数write()向父进程发送自己的进程ID和字符串” s sending a message to parent.\n”。 c) 父进程调用函数read()通过管道读出子进程发来的消息,将消息输出屏幕,然后终止

    操作系统课程设计进程控制

    在Windows下实现: 使用CreateProcess()来创建进程 使用WaitForSingleObject()在“mytime”命令和新创建的进程...使用fork()/execv()来创建进程运行程序 使用wait()等待新创建的进程结束 调用gettimeofday()来获取时间

    fork-helper:一个PHP助手来分叉进程并允许多线程

    $ fork -&gt; call ( function () { for ( $ i = 1 ; $ i &lt;= 3 ; $ i ++) { echo "Process A - " . $ i . "\n" ; sleep ( 1 ); } }); $ fork -&gt; call ( function () { for ( $ i = 1 ; $ i &lt; 3 ; $ i ++) { ...

    进程控制实验

    进程控制:#include "pctl.h" int main(int argc,char *argv[]){ int i; int pid1,pid2; int status1,status2; char *args1[]={"/bin/ls","-a",NULL}; char *args2[]={"/bin/ps","-a",NULL}; signal(SIGINT,...

    操作系统----进程管理及进程通信实验报告

    运行进程管理及进程通信(一)中给出的例子,查看自己运行的结果,并进行分析。  程序1 #include "stdio.h" main() { int i,j,k; if (i=fork()) { j=wait(); printf("Parent Process!\n"); printf("i=%d,j=%d,k=%...

    举例讲解C语言的fork()函数创建子进程的用法

    先来看这样一个例子,利用fork调用execlp()函数来在Linux下实现ps或ls命令: #include sys/types.h #include unistd.h #include stdio.h #include stdlib.h int main() { pid_t result; result=fork(); //报错...

    操作系统上机实验报告-进程的管道通信

    1) 父进程先接收子进程1发来的消息,然后再接收子进程2发来的消息。 2) 实现管道的互斥使用,当一个子进程正在对管道进行写操作时,另一子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用...

    操作系统实验 体验linux基本操作 子进程的创建

    一、实验目的: ... Stones(译者:陈健,宋健建),人民邮电出版社,2010)第11章“进程和信号”的内容,熟悉进程创建、进程协同工作等相关函数如fork()、system()、exec()、waitpid()、exit()等的使用方法。

    mongodb: mongod 启动报错[about to fork child process, waiting until server is ready for connections]

    mongodb 命令行mongod启动报错 about to fork child process, waiting until server is ready for connections. forked process: 3560 ERROR: child process ...已经有mongd进程在运行了 配置错误(如dbpath log等)

    从一道面试题谈linux下fork的运行机制

    1213printf("pid1:%d,pid2:%d\n",pid1,pid2);14} 要求如下:已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。1、请说出执行这个程序后,将一共运行几个进程。2、

    linux中进程问题

    sleep(2); } } void *procd(void *arg) //daughter线程 { while(1){ sem_wait(&applefull;); printf("%s\n",(char *)arg); sem_post(&empty;);sleep(5); } } main() { pthread_t father; //定义...

    UNIX 环境高级编程 part2

    进程控制 141&lt;br&gt;8.1 引言 141&lt;br&gt;8.2 进程标识 141&lt;br&gt;8.3 fork函数 142&lt;br&gt;8.4 vfork 函数 145&lt;br&gt;8.5 exit函数 147&lt;br&gt;8.6 wait和waitpid函数 148&lt;br&gt;8.7 wait3和wait4函数 152&lt;br&gt;8.8 竞态条件 153&lt;br&gt;8.9 exec...

    UNIX 环境高级编程 part3

    进程控制 141&lt;br&gt;8.1 引言 141&lt;br&gt;8.2 进程标识 141&lt;br&gt;8.3 fork函数 142&lt;br&gt;8.4 vfork 函数 145&lt;br&gt;8.5 exit函数 147&lt;br&gt;8.6 wait和waitpid函数 148&lt;br&gt;8.7 wait3和wait4函数 152&lt;br&gt;8.8 竞态条件 153&lt;br&gt;8.9 exec...

    UNIX环境高级编程 part1

    进程控制 141&lt;br&gt;8.1 引言 141&lt;br&gt;8.2 进程标识 141&lt;br&gt;8.3 fork函数 142&lt;br&gt;8.4 vfork 函数 145&lt;br&gt;8.5 exit函数 147&lt;br&gt;8.6 wait和waitpid函数 148&lt;br&gt;8.7 wait3和wait4函数 152&lt;br&gt;8.8 竞态条件 153&lt;br&gt;8.9 exec...

    UNIX 环境高级编程 part4

    进程控制 141&lt;br&gt;8.1 引言 141&lt;br&gt;8.2 进程标识 141&lt;br&gt;8.3 fork函数 142&lt;br&gt;8.4 vfork 函数 145&lt;br&gt;8.5 exit函数 147&lt;br&gt;8.6 wait和waitpid函数 148&lt;br&gt;8.7 wait3和wait4函数 152&lt;br&gt;8.8 竞态条件 153&lt;br&gt;8.9 exec...

    UNIX 环境高级编程 part5

    进程控制 141&lt;br&gt;8.1 引言 141&lt;br&gt;8.2 进程标识 141&lt;br&gt;8.3 fork函数 142&lt;br&gt;8.4 vfork 函数 145&lt;br&gt;8.5 exit函数 147&lt;br&gt;8.6 wait和waitpid函数 148&lt;br&gt;8.7 wait3和wait4函数 152&lt;br&gt;8.8 竞态条件 153&lt;br&gt;8.9 exec...

Global site tag (gtag.js) - Google Analytics