如何动态创建Unix管道?

时间:2014-04-16 02:23:16

标签: c unix pipe

我有一个使用fork()创建子进程的程序,我希望让子进程使用Unix管道与父进程通信。

问题是似乎没有创建多个管道,或者我的阵列可能存在问题。当我在父程序中使用prinf()时,它会从每个管道读取相同的数据,即使每个子项发送不同的数据。

这是我的代码:

// Variables
int pipes_count = 0;
int *pipes[MAXCLIENTS];
int new_pipefd[2];
int pipe_bytes;
char pipe_buffer[MAXDATASIZE];

while(1) {
    // Pipe creation 
    pipe(new_pipefd);
    pipes[pipes_count] = new_pipefd;
    pipes_count++;

    if (fork()) {
        // unrelated code for parent here
        close(new_pipefd[1]); // close the parent's write-end of the pipe
        break;
    } else {
        // unrelated code for child here
        close(new_pipefd[0]); // close the child's read-end of the pipe
        break;
    }

    if (some condition) { break; } // The parent will stop creating pipes
}

while(condition that guarantees this is the child) {
    write(new_pipefd[1], buffer, strlen(recv_buffer));
    close(new_pipefd[1]);
    return 0; // the child process ends
}

// This is a loop where the parent reads what the children sent
for (int i = 0; i < pipes_count; i++) {
    pipe_bytes = read(pipes[i][0], pipe_buffer, sizeof pipe_buffer);
    if (pipe_bytes == 0) {
        close(pipes[i][0]); 
    } else {
        printf("Testing: %s\n", pipe_buffer);
    }
}

1 个答案:

答案 0 :(得分:2)

正如我在评论中指出的那样,问题出在作业pipes[pipes_count] = new_pipefd;上:

int pipes_count = 0;
int *pipes[MAXCLIENTS];
int new_pipefd[2];
int pipe_bytes;
char pipe_buffer[MAXDATASIZE];

while(1) {
    // Pipe creation 
    pipe(new_pipefd);
    pipes[pipes_count] = new_pipefd;
    pipes_count++;

问题是变量new_pipefd是一个数组,所以你要将同一个数组的地址复制到pipes的每个元素中,这意味着父变量只有访问最后创建的管道。

我认为你应该使用更像代码的代码:

int pipes_count = 0;
int pipes[MAXCLIENTS];  // Changed type!
int new_pipefd[2];
char pipe_buffer[MAXDATASIZE];

while (1)
{
    // Pipe creation 
    pipe(new_pipefd);
    pipes[pipes_count++] = new_pipefd[0];  // Just the read end of the pipe

    if (fork())
    {
        // unrelated code for parent here
        close(new_pipefd[1]); // close the parent's write-end of the pipe
        // break;             // This break is not wanted
    }
    else
    {
        // unrelated code for child here
        close(new_pipefd[0]); // close the child's read-end of the pipe
        break;
    }

    if (some condition)
        break;        // The parent will stop creating pipes
}

while (condition that guarantees this is the child)
{
    write(new_pipefd[1], buffer, strlen(recv_buffer));
    close(new_pipefd[1]);
    return 0; // the child process ends
}

// This is a loop where the parent reads what the children sent
for (int i = 0; i < pipes_count; i++) {
    int pipe_bytes = read(pipes[i], pipe_buffer, sizeof(pipe_buffer));
    if (pipe_bytes != 0)
        printf("Testing: %.*s\n", pipe_bytes, pipe_buffer); // Safe!
    close(pipes[i]); 
}

如果是我的代码,我有一个函数(我传统上称之为be_childish())来调用&#39;如果它是一个孩子&#39;循环中的代码块。该函数永远不会返回,并且会传递它所需的任何资源(new_pipefd肯定,也可能是其他信息)。我经常有一个函数be_parental()来做父母的活动。我发现这可以清除大部分代码,迫使活动清晰分离。