【问题标题】:Multiple 1-to-1 pipes in CC中的多个1对1管道
【发布时间】:2019-03-03 03:28:37
【问题描述】:

C 中是否可以有多个并发的一对一管道? 我的示例用例如下:

  1. 父进程使用 fork() 创建 x 个子进程
  2. 父级创建 x 个管道,每个子级一个
  3. 每个子进程写入各自的管道,然后关闭它。
  4. 父级从管道读取然后关闭它们。

我目前的草稿尝试如下,但我对其功能有疑问:

// Create x pipes
int fd[2*x];
pipe(fd);

// In child i do (i from 0 to x-1 inclusive):
close(fd[2*i]);
write(fd[2*i +1], .....);
close(fd[2*i +1]);

// In parent do:
wait() // wait for children to finish
// while any pipe has content do:
// For each i from 0 to x-1 inclusive:
close(fd[2*i +1]);
read(fd[2*i], .....);
close(fd[2*i]);

如果有人能向我展示这个概念在工作中的简单示例,我将不胜感激。这里的最终目标是子级与父级之间的一种对话方式,其中父级将存储到单个数组中的多个值。

【问题讨论】:

  • 它更像int fd[x][2],然后你在循环中调用pipe,执行x次。
  • 没有什么是不可能的。主要问题是管道的永久问题——确保足够多的进程关闭足够多的管道。对于从孩子到父母的一条信息,这不如正在进行的双向对话那么重要。但是请注意,您需要在分叉孩子之前创建每个孩子的管道。此外,这意味着第二个孩子也将打开第一个孩子的管道——它需要关闭它(以及它自己管道的未使用的读取端)。对于其他孩子也是如此。请注意,您需要多次致电pipe()
  • @user3386109:fd[2*x]fd[x][2]的效果差别不大;两者都可以简单地工作,尽管用于访问描述符的符号略有不同。

标签: c pipe fork


【解决方案1】:

此代码或多或少可以满足您的需求。它使用我在 GitHub 上的 SOQ(堆栈溢出问题)存储库中提供的错误报告代码,作为 src/libsoq 子目录中的文件 stderr.cstderr.h

#include "stderr.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

enum { NUM_CHILDREN = 5 };
enum { MSG_BUFFSIZE = 64 };
static void be_childish(int kid, int *fd);

int main(int argc, char **argv)
{
    int fd[2 * NUM_CHILDREN];
    int pid[NUM_CHILDREN];

    err_setarg0(argv[0]);
    err_setlogopts(ERR_PID);

    if (argc != 1)
        err_usage("");

    for (int i = 0; i < NUM_CHILDREN; i++)
    {
         if (pipe(&fd[2 * i]) != 0)
             err_syserr("failed to create pipe for child %d: ", i);
    }

    for (int i = 0; i < NUM_CHILDREN; i++)
    {
        if ((pid[i] = fork()) < 0)
            err_syserr("failed to fork child %d: ", i);
        else if (pid[i] == 0)
            be_childish(i, fd);
        else
        {
            printf("Child %d has PID %d\n", i, pid[i]);
            fflush(stdout);
        }
    }

    char buffer[MSG_BUFFSIZE];
    for (int i = 0; i < NUM_CHILDREN; i++)
    {
        close(fd[2 * i + 1]);
        int pipe_in = fd[2 * i + 0];
        int nbytes = read(pipe_in, buffer, sizeof(buffer));
        if (nbytes < 0)
            err_syserr("failed to read from FD %2d: ", pipe_in);
        printf("Got %2d bytes [%.*s] from FD %2d, PID %d\n",
               nbytes, nbytes, buffer, pipe_in, pid[i]);
        close(pipe_in);
    }

    for (int i = 0; i < NUM_CHILDREN; i++)
    {
        int status;
        int corpse = wait(&status);
        if (corpse > 0)
            printf("Child with PID %d exited with status 0x%.4X\n", corpse, status);
        else
            err_syserr("Failed to wait for dead children: ");
    }

    return 0;
}

static void be_childish(int kid, int *fd)
{
    for (int i = 0; i < kid; i++)
    {
        close(fd[2 * i + 0]);
        close(fd[2 * i + 1]);
    }

    close(fd[2 * kid + 0]);
    int estat = kid + 32;

    char buffer[MSG_BUFFSIZE];
    int nbytes = snprintf(buffer, sizeof(buffer),
                          "Child %d (PID %d) exiting with status %d",
                          kid, (int)getpid(), estat);
    int pipe_out = fd[2 * kid + 1];
    if (write(pipe_out, buffer, nbytes) != nbytes)
        err_syserr("failed to write to parent: ");
    close(pipe_out);
    exit(estat);
}

示例运行:

Child 0 has PID 36957
Child 1 has PID 36958
Child 2 has PID 36959
Child 3 has PID 36960
Child 4 has PID 36961
Got 42 bytes [Child 0 (PID 36957) exiting with status 32] from FD  3, PID 36957
Got 42 bytes [Child 1 (PID 36958) exiting with status 33] from FD  5, PID 36958
Got 42 bytes [Child 2 (PID 36959) exiting with status 34] from FD  7, PID 36959
Got 42 bytes [Child 3 (PID 36960) exiting with status 35] from FD  9, PID 36960
Got 42 bytes [Child 4 (PID 36961) exiting with status 36] from FD 11, PID 36961
Child with PID 36960 exited with status 0x2300
Child with PID 36959 exited with status 0x2200
Child with PID 36958 exited with status 0x2100
Child with PID 36957 exited with status 0x2000
Child with PID 36961 exited with status 0x2400

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 2019-05-02
    • 2010-09-21
    相关资源
    最近更新 更多