`
kenby
  • 浏览: 725447 次
  • 性别: 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

 

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

分享到:
评论

相关推荐

    fork创建多个子进程

    fork 创建多个子进程是指通过 fork 系统调用创建多个子进程,每个子进程可以执行不同的任务。下面我们将讨论三种常见的 fork 创建多个子进程的方法。 第一种方法:同时创建多个子进程 该方法通过在主进程中使用 ...

    fork后子进程从哪里开始执行

    `fork()` 是 Linux 和其他类 Unix 操作系统中的一个重要系统调用,用于创建一个与当前进程几乎完全一样的新进程,即子进程。子进程继承了父进程的大部分属性,如打开的文件描述符、环境变量等,但它是一个独立的进程...

    创建新进程:fork函数:fork函数干什么? fork函数与vfork函数的区别在哪里?为何在一个fork的子进程分支中使用_exit函数而不使用exit函数?

    它创建了一个完全相同的子进程副本,并返回一个进程标识符(PID)。fork 函数的返回值在父进程和子进程中不同:在父进程中,返回子进程的 PID;在子进程中,返回 0。 fork 函数的基本功能可以通过以下示例程序来...

    linux 进程 线程 fork 的深入思考

    2. 如果其中一个进程的输出结果是 “pid1:1001,pid2:1002”,请写出其他进程的输出结果(不考虑进程执行顺序)。 #### 解析 **预备知识** 为了更好地理解此题,首先需要了解一些关于 Linux 进程的基础知识: 1. ...

    fork函数和子函数进程

    2. **父子进程交互**:每个子进程都有机会成为下一个`fork()`函数的调用者,从而创建更多的子进程。这种递归创建方式使得程序输出结果更加复杂。 3. **程序结束**:所有子进程创建完成后,主进程和其他子进程都将...

    linux下用fork()函数实现多进程调用带来的一些思考

    \n")`,`stdout`的缓冲区会在遇到`\n`时被刷新,所以子进程不会继承这个已刷新的缓冲,从而只会在屏幕上看到一次"fork!"。 此外,当我们把程序的输出重定向到文件时,行为可能会有所不同。因为重定向通常会导致标准...

    fork()编程fork()编程fork()编程

    2. **返回值**:`fork()`调用后,执行流被分成两个分支,一个是父进程,另一个是子进程。两者都会继续执行`fork()`之后的语句,但各自的执行上下文不同。 三、父子进程通信 由于`fork()`后的两个进程共享某些资源...

    linux_fork函数

    当一个进程调用`fork()`函数时,系统会为新进程分配所需的资源,并将父进程的状态复制给子进程。这意味着除了少数几个特定值外,子进程与父进程具有相同的内存空间、环境变量和其他属性。这样的设计使得子进程可以...

    fork3()编程fork3()编程fork3()编程fork3()编程fork3()编程

    2. **守护进程**:通过`fork()`和`exec()`组合,父进程可以创建一个脱离控制终端的后台服务进程(守护进程)。 3. **进程通信**:多个进程之间可以通过管道、套接字或共享内存进行通信。 总结,虽然"fork3()"不是...

    Linux进程控制编程-fork子进程创建实例.pdf

    在Linux操作系统中,进程是程序执行的一个实例,而`fork()`函数是用于创建新进程的关键系统调用。本文将深入探讨`fork()`函数的工作原理、使用方法及其在Linux进程控制编程中的重要性。 `fork()`函数是C语言标准库...

    fork()系统调用参数返回值详解

    在解释这个问题之前,我们需要了解一个概念:在语句pid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的代码部分完全相同,将要执行的下一条语句都是if (pid&gt;0)...

    linux c fork全面剖析

    2. **返回值判断**:`fork()` 在父进程和子进程中都会返回一个值,但在父进程中返回的是子进程的进程标识符(PID),而在子进程中返回的是 0。通过这种方式,程序可以根据返回值的不同来区分父进程和子进程。 #### ...

    linux fork函数

    在Linux操作系统中,`fork()`函数是创建新进程的关键接口,它是C标准库中的一个系统调用。这个函数允许一个正在运行的进程(父进程)创建一个与它几乎完全相同的副本,即子进程。理解并熟练使用`fork()`是进行进程...

    c语言的fork函数笔记

    2. **返回值的区别**:`fork()`函数的返回值用于区分父进程和子进程: - 如果`fork()`返回值小于0,表明子进程创建失败。 - 如果`fork()`返回值等于0,表明这是子进程。 - 如果`fork()`返回值大于0,这个进程ID是...

    linux面试题看FORK()

    - 第二个`fork()`再次调用会产生另一个子进程`P2`,`P0`中的`fork()`返回`P2`的PID(例如1002)给`pid2`,之后`P0`完成执行并打印“pid1:1001, pid2:1002”。 - 对于`P2`而言,由于它是`P0`的子进程,因此`pid1`的...

    python编写守护进程实现当python进程被杀后重启进程的源代码

    本篇文章将深入探讨如何用Python编写一个守护进程,以及在进程被杀后自动重启的实现方法。 首先,让我们了解守护进程的基本概念。在Unix-like操作系统中,守护进程通常在用户登录会话之外运行,避免受到用户退出或...

    实验2 进程的创建与控制实验.docx

    2. 运行下面的程序,分析“printf(”fork 1,PID=%d\n“,getpid()); ”为什么会被执行两次。 3. 编译下面的程序 ftree.c,让可执行程序后台运行,用“pstree 进程 ID 号”查看进程树,用“ps”查看进程 ID 号,绘制...

    实验3的用户进程实现

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

Global site tag (gtag.js) - Google Analytics