使用管道在父进程和子进程之间进行通信的问题

Posted

技术标签:

【中文标题】使用管道在父进程和子进程之间进行通信的问题【英文标题】:An issue with communication between parent-process and child-process using pipe 【发布时间】:2014-11-28 11:39:25 【问题描述】:

我正在编写一个 C 程序,给定一个可执行文件 a.out 和输入文件 in_1.txtin_2.txt ... in_n.txt,将在所有 n 输入文件上运行 a.out,并将生成参数列表中每个输入文件的对应输出。 我在我的程序中遇到了一些奇怪的行为(称为tester.out),几个小时后,我能够确定我的问题,但不知道如何解决它。

我会先贴出代码,然后再解释问题...

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<limits.h>
#include<string.h>

#define PERM S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP  // 660

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

    if (argc<3) 
        printf("Arguments required; an executable file and at least one input file.\n");
        return 1;
    

    int channel[2];
    if (pipe(channel)<0) 
        perror("pipe");
        return 1;
    

    int i;
    for (i=2; i<argc; ++i) 

        pid_t p=fork();
        if (p<0) 
            perror("fork");
            return 1;
        

        if (p)  // parent

            // closing read end
            close(channel[0]); // *** The problem lies here! ***

            int indicator;

            if ((indicator=write(channel[1], argv[i], strlen(argv[i])+1))<0) 
                perror("write");
                return 1;
            

            printf("Parent wrote %d bytes\n", indicator);

            int status;
            wait(&status);

            if (WIFEXITED(status)) 
                printf("Your program terminated normally with exit code %d\n", WEXITSTATUS(status));
                printf("See output file: %s_output\n", argv[i]);
            
            else if (WIFSIGNALED(status)) 
                printf("Your program terminated by a signal! signal code: %d\n", WTERMSIG(status));
            

        
        else  // child

            // closing write end
            close(channel[1]);

            char input_file[PATH_MAX]=0;
            char output_file[PATH_MAX+10]=0;

            int indicator;

            // read input_file from pipe
            if ((indicator=read(channel[0], input_file, PATH_MAX))<1) 
                perror("child process: read");
                return 1;
            

            printf("child read %d bytes\n", indicator);

            sprintf(output_file, "%s_output", input_file);
            printf("Got %s and output is %s\n", input_file, output_file);

            sleep(5); /* later, I will call execl() here to run argv[1] on input_file */
            return 1;
        



    



    return 0;

这在我运行时按预期工作:

$ ./tester.out a.out input1.txt

但是当我使用多个输入文件运行它时失败:

$ ./tester.out a.out input1.txt input2.txt

正如代码中突出显示的注释所暗示的那样,问题在于调用close(channel[0]) 的行,因为在第一次 迭代中关闭父级中的channel[0],意味着在第二次迭代,子进程将其channel[0]关闭(由其父进程 - 在第一次迭代中)。

对如何解决这种情况有什么建议吗?

【问题讨论】:

这一行: if (argc 否,if (argc 【参考方案1】:

您应该为每个子进程创建一个新管道,并在完成后关闭管道的两端。您需要在父子节点中关闭两端。

【讨论】:

所以对 pipe() 的调用应该在 fork() 之前的 for 循环内?【参考方案2】:

一个简单的解决方法是:

从循环之前移动到循环内部,就在调用 fork() 的行之前。然后定义choice[2] 变量并调用pipe()。

【讨论】:

以上是关于使用管道在父进程和子进程之间进行通信的问题的主要内容,如果未能解决你的问题,请参考以下文章

swoole父进程和子进程之间通信的例子

swoole父进程和子进程之间通信的例子

进程间通信——命名管道

通过 c 中的半双工管道在父进程和 2 个子进程之间进行通信的问题

进程间通信 IPC(Inter-Process Communication)

如何在父进程和子进程之间发送带有 pipe() 的矩阵?