如果在使用管道时子进程的数量大于处理器,进程会被阻塞吗?

Posted

技术标签:

【中文标题】如果在使用管道时子进程的数量大于处理器,进程会被阻塞吗?【英文标题】:Will processes be blocked, if the number of child processes greater than processors while using pipeline? 【发布时间】:2022-01-05 18:35:07 【问题描述】:

当子进程的数量很大时,我的程序停止运行。我不知道问题可能是什么,但我猜想子进程在运行时被阻塞了。

这是程序的主要工作流程:

void function(int process_num)

    int i;

    // initial variables for fork()
    int status = 0;
    pid_t child_pid[process_num], wpid;
    int *fds = malloc(sizeof(int) * process_num * 2);

    // initial pipes 
    for(i=0; i<process_num; i++)
        if(pipe(fds + i*2) <0)
            exit(0);
    

    // start child processes to write
    for(i=0; i<process_num; i++)
        child_pid[i] =fork();

        if(child_pid[i] == 0)
            close(fds[i*2]);
            // do something ...
            // write(fds[i*2+1], something);
            close(fds[i*2+1]);
            exit(0);
        else if(child_pid[i] == -1)
            printf("fork error\n");
            exit(0);
        
    

    // parent waits child processes and reads
    for(i=0; i<process_num; i++)

      pid_t cpid = waitpid(child_pid[i], &status, 0);
      if (WIFEXITED(status))
        close(fds[i*2+1]);
        // do something ...
        // read(fds[i*2], something);
       close(fds[i*2]);
      
    
    free(fds);
    while((wpid = wait(&status)) > 0);


我通过 htop 检查了进程的状态,有几个(例如,8 个,而 process_num 为 110)子进程的状态为 S

现在我的问题来了:如果子进程的数量大于处理器的数量,在使用管道为子进程和当前进程进行通信时,子进程是否会被阻塞(父进程等待所有子进程执行) ?非常感谢!

编辑:我在使用read()write()时打印了fds的Id,我发现读从4开始,写在5,我不知道为什么是案例,有人知道吗?

【问题讨论】:

不,处理器的数量不限制这个。您可以在单核机器上拥有(例如)100 个进程——没问题。更有可能的是,阻塞是由于您的代码中的错误造成的。具体来说,parent 进程应该在 进行任何等待之前关闭管道中间部分的 fd。我运行了您发布的程序,它在几分之一秒内完成,那么您发布的代码与您的实际程序有多接近? 你肯定有错误。当我将进程数设置为一个较小的数字(例如)10 但将缓冲区写入长度设置为 100,000 时,我被阻止了。 read 电话在哪里?在每个阶段i,您必须从fds[(i - 1) * 2] 读取并写入fds[i * 2 + 1]。第一阶段是特殊的(例如)从某个文件中读取。而且,最后一个阶段是特殊的(例如)写入标准输出。我会使用struct 来控制每个阶段。有关 [在自定义外壳中] 工作管道的示例,请参阅我的回答:***.com/questions/52823093/fd-leak-custom-shell/… @Craig Estey 嘿,非常感谢!我发现确实存在 read() 的错误。我的读取函数对其中一个数据长度为 0 的 fd 抛出错误。读取时fds[(i - 1) * 2] 是正确的,而不是fds[i*2]?但是当i =0 时会发生什么? 就像我说的,第一阶段(即i == 0)很特别。 i - 1no [有效] fds 条目。并且,最后阶段同样没有有效的输出值。你正在做的是相当于一个shell pipe:| cat | cat | cat | 而不是cat &lt; infile | cat | cat &gt; outfile @CraigEstey 哦,对不起,我不小心跳过了你提到的关于 i == 0 的部分。但我阅读了tldp.org/LDP/lpg/node11.html,并按照示例,i*2 用于阅读,i*2 + 1 写作 【参考方案1】:

处理器的数量在这里没有影响。操作系统是活的,能够运行任何有事可做的进程。 这是一个纯软件问题,所有进程都处于睡眠状态 (S) 等待某个永远不会发生的事件。

【讨论】:

以上是关于如果在使用管道时子进程的数量大于处理器,进程会被阻塞吗?的主要内容,如果未能解决你的问题,请参考以下文章

Unix环境高级编程(十五)高级I/O

多任务编程 -- 孤儿进程和僵尸进程

多任务编程 -- 孤儿进程和僵尸进程

在 C 中使用 execve 加载程序时子进程如何终止

Linux之僵尸进程

shell 命名管道,进程间通信, ncat作http server