C多处理/管道

时间:2015-02-03 00:07:12

标签: c pipe multiprocessing

我正在学习fork()如何在C中工作。 这个想法是产生3个子进程,每个进程都向父进程发送一些信息。

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

int main()
{
    int fd[2];
    int pid[3] = {0,0,0};
    int status = 0;


for (int i = 0; i < 3; i++)
{
    pipe(fd);

    pid[i] = fork();
    if (pid[i] < 0)
    {
        return -1;
    }
    if (pid[i] == 0)
    {
        close(fd[0]);
        char *arr = malloc(sizeof(char));
        sprintf(arr, "%i", i);
        write(fd[1], arr, 1);
        exit(0);
    }


}

for(int j=0; j < 3; j++)
{
    close(fd[1]);
    if (pid[j] > 0)
    {
        sleep(0);
        pid[j] = wait(&status);
        char *out = malloc(20 *sizeof(char));
        read(fd[0], out, 6);
        printf("%s\n", out);
        free(out);
        printf("I am the parent\n");

    }
}


}

预定的输出是:

1
I am the parent
2
I am the parent
3
I am the parent

实际输出是:     2     我是父母     2     我是父母     2     我是父母

为什么会这样?

2 个答案:

答案 0 :(得分:1)

您正在致电

pipe(fd);

在第一个for循环中多次。考虑在循环之前移动它,因为它每次调用它时都会返回一对新的文件描述符进行读/写。

此外,close(fd[1])只应从父进程调用一次。

答案 1 :(得分:0)

几点:

  1. 您在第一个pipe(fd)循环中呼叫for三次,而当您创建三个管道时,您只需保存一个引用其中之一。因此,在您的第二个for循环中,您将从每次创建的第三个管道中读取数据。您应该有一个数组来存储对所有三个管道的引用。

  2. 您应该检查可能失败的系统调用的所有的返回。由于上面的第1点,close(fd[1])如果你做了这个,就会失败两次,而且它会提醒你事情已经发生了。检查系统调用的返回不仅是为了防止出现不太可能发生的错误,而且还可以帮助您进行调试,因为它们失败的最可能原因是你做错了,就像这里的情况一样。

    < / LI>
  3. 完全没有必要使用malloc(),这里 - 常规的char数组很好。此外,当您需要至少两个(即单个数字和终止空字符)时,malloc(sizeof(char));一个字符分配空间。此外,您应始终检查malloc()的退货,因为它可能会失败。此外,根据定义,sizeof(char)始终为1,因此它总是多余的。

  4. 要获得所需的输出,您应该将1添加到i,否则i将是0,然后是1,然后2,但您的示例输出显示您想要1,然后23

  5. waitpid()优于wait(),因为您希望等待特定流程。同样,使用此功能时,sleep()来电也是多余的。

  6. 虽然在您退出之前没有必要close()您的管道,但这样做有时会有所帮助,因为如果您和& #39;做错了什么。

  7. 您的if (pid[j] > 0)检查是不必要的,因为如果fork()失败或0失败,您已经终止,因此您已经知道它将会是当你到达这里时,大于0

  8. 如果您不打算使用它,则不需要status变量来检索流程的退出状态 - 您只需将NULL传递给wait()即可waitpid()j

  9. 小点,但您不需要为第二个for循环使用不同的变量名称(即i),因为for的范围在您的第一个i循环中仅限于该循环。如果您要使用return EXIT_FAILURE作为循环计数器的通用名称,您可以随时随地使用它。

  10. return -1优于255,无论如何,当您检索退出状态时,该值将转换为fork()

  11. 实际上它不太可能是一个问题,但是pid_t会返回int类型,而不是类型pid,所以它更好使#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd[3][2]; pid_t pid[3]; for ( int i = 0; i < 3; ++i ) { if ( pipe(fd[i]) == -1 ) { perror("pipe() failed"); return EXIT_FAILURE; } if ( (pid[i] = fork()) == -1 ) { perror("fork() failed"); return EXIT_FAILURE; } else if ( pid[i] == 0 ) { if ( close(fd[i][0]) == -1 ) { perror("close() failed"); return EXIT_FAILURE; } char arr[100]; sprintf(arr, "%d", i + 1); if ( write(fd[i][1], arr, 1) == -1 ) { perror("write() failed"); return EXIT_FAILURE; } if ( close(fd[i][1]) == -1 ) { perror("close() failed"); return EXIT_FAILURE; } return EXIT_SUCCESS; } else { if ( close(fd[i][1]) == -1 ) { perror("close() failed"); return EXIT_FAILURE; } } } for ( int i = 0; i < 3; ++i ) { if ( waitpid(pid[i], NULL, 0) == -1 ) { perror("waitpid() failed"); return EXIT_FAILURE; } char out[100] = {0}; if ( read(fd[i][0], out, 99) == -1 ) { perror("read() failed"); return EXIT_FAILURE; } printf("%s\nI am the parent\n", out); if ( close(fd[i][0]) == -1 ) { perror("close() failed"); return EXIT_FAILURE; } } return EXIT_SUCCESS; } 成为该类型的数组。

  12. 这里有一些修改过的代码:

    paul@horus:~/src/sandbox$ ./pipe
    1
    I am the parent
    2
    I am the parent
    3
    I am the parent
    paul@horus:~/src/sandbox$ 
    

    输出:

    {{1}}