使用单个管道创建多个子进程

时间:2013-05-20 04:15:11

标签: unix process pipe

我需要创建三个子进程,每个进程从命令行参数中读取一个字符串,并将该字符串写入单个管道。然后父母将从管道中读取字符串并在屏幕上显示所有这三个字符串。我尝试用两个进程来测试,它打印两个字符串,而不是两个。

#include <stdio.h>
#include <unistd.h>

int main (int argc, char *argv[]) {

    char *character1 = argv[1];
    char *character2 = argv[2]; 

    char inbuf[100]; //creating an array with a max size of 100

    int p[2]; // Pipe descriptor array
    pid_t pid1; // defining pid1 of type pid_t
    pid_t pid2; // defining pid2 of type pid_t

    if (pipe(p) == -1) {
        fprintf(stderr, "Pipe Failed"); // pipe fail
    }

    pid1 = fork(); // fork

    if (pid1 < 0) {
        fprintf(stderr, "Fork Failed"); // fork fail
    }

    else if (pid1 == 0){ // if child process 1
        close(p[0]); // close the read end
        write(p[1], character1, sizeof(&inbuf[0])); // write character 1 to the pipe
    }

    else { // if parent, create a second child process, child process 2
        pid2 = fork();  

        if (pid2 < 0) {
        fprintf(stderr, "Fork Failed"); // fork fail
        }

        if (pid2 = 0) { // if child process 2
            close(p[0]); // close the read end
            write(p[1], character2, sizeof(&inbuf[0])); // write character 2 to the pipe
        }

        else { // if parent process
            close(p[1]); // close the write end

            read(p[0], inbuf, sizeof(&inbuf[0])); // Read the pipe that both children write to 
            printf("%s\n", inbuf); // print 

            read(p[0], inbuf, sizeof(&inbuf[0])); // Read the pipe that both children write to 
            printf("%s\n", inbuf); // print 
        }
    } 
}

1 个答案:

答案 0 :(得分:3)

在没有更多数据要读取之前,您的代码不会继续循环。它只进行一次读取。它也不会检查read()返回的值,但它应该。

我已将fork()write()(以及错误检查)代码抽象为函数。这似乎有效:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void child(int fd, const char *string)
{
    pid_t pid = fork();
    int len = strlen(string);
    if (pid < 0)
    {
        fprintf(stderr, "%.5d: failed to fork (%d: %s)\n",
                (int)getpid(), errno, strerror(errno));
        exit(1);
    }
    else if (pid > 0)
        return;
    else if (write(fd, string, len) != len)
    {
        fprintf(stderr, "%.5d: failed to write on pipe %d (%d: %s)\n",
                (int)getpid(), fd, errno, strerror(errno));
        exit(1);
    }
    else
        exit(0);
}

int main (int argc, char *argv[])
{
    char inbuf[100]; //creating an array with a max size of 100
    int p[2]; // Pipe descriptor array

    if (argc != 4)
    {
        fprintf(stderr, "Usage: %s str1 str2 str3\n", argv[0]);
        return 1;
    }

    if (pipe(p) == -1)
    {
        fprintf(stderr, "Pipe Failed"); // pipe fail
        return 1;
    }

    for (int i = 0; i < 3; i++)
        child(p[1], argv[i+1]);

    int nbytes;
    close(p[1]); // close the write end
    while ((nbytes = read(p[0], inbuf, sizeof(inbuf))) > 0)
        printf("%.*s\n", nbytes, inbuf); // print 

    return 0;
}

我每次都使用命令行多次运行命令:

./p3 'message 1' 'the second message' 'a third message for the third process'

一次运行,输出为:

the second messagemessage 1
a third message for the third process

另一方面,我得到了:

the second messagemessage 1a third message for the third process

另一方面,我得到了:

message 1
the second messagea third message for the third process

(这是在配备Intel Core i7的MacBook Pro上,运行Mac OS X 10.8.3,并使用GCC 4.7.1。)