Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 通过管道将子进程导入另一个子进程_C_Linux_Pipe_Fork_System Calls - Fatal编程技术网

C 通过管道将子进程导入另一个子进程

C 通过管道将子进程导入另一个子进程,c,linux,pipe,fork,system-calls,C,Linux,Pipe,Fork,System Calls,我正在尝试创建两个管道,第一个管道的输入是父进程的argv[1]中输入文件的内容,逐行输入到一个mapper进程中,该进程执行一些工作,最后输入到一个reducer进程中,该进程将其减少 当我在“bash”中运行我的mapper和reducer时: ./mapper < input.txt | reducer 问题是,如果在dup之后有多个fd,则在发送EOF时,必须关闭原始的dup 简而言之,对于dup,将增加FD引用计数 另一个问题是,我的进程树是线性的,而不是一个进程的两个子进程,

我正在尝试创建两个管道,第一个管道的输入是父进程的
argv[1]
中输入文件的内容,逐行输入到一个
mapper
进程中,该进程执行一些工作,最后输入到一个
reducer
进程中,该进程将其减少

当我在“bash”中运行我的
mapper
reducer
时:

./mapper < input.txt | reducer

问题是,如果在
dup
之后有多个
fd
,则在发送
EOF
时,必须关闭原始的
dup

简而言之,对于
dup
,将增加
FD
引用计数

另一个问题是,我的进程树是线性的,而不是一个进程的两个子进程,因此主进程在输出之前退出,导致bash在执行似乎完成之后有输出,使它看起来像是挂起的,而不是挂起的

解决方案是从父进程创建管道和分支,只需稍加重组


特别感谢帮助我的Russell Reed。

while(read=getline(&line,&n,in)!=-1)-->while(read=getline(&line,&n,in))!=-1)添加了括号没有改变任何东西除了terence调用的错误之外,还应该将变量“read”传递给write调用,而不是“n”n'是分配的空间量,通常大于实际读取量,导致重复写入某些相同的数据。这就是为什么你没有看到特伦斯的建议有任何变化。这两个更改为我修复了输出,但我还没有解决您的wait()问题。捕捉得好!不幸的是,它无法解决问题,在我调用exec后,孩子们似乎没有做任何事情……但是exec也不会抛出任何错误。我用/bin/cat替换了您的映射程序和减速器程序,以简化故障排除。我得到了正确的回显输入,但是第一个cat进程挂起,试图从管道读取更多数据(我运行strace查看系统调用)。
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>

void checkForkError(pid_t pid);
void mapperSetup(int mapperPipe[]);
void reducerSetup(int reducerPipe[]);

int main(int argc, char* argv[]) {
    if(argc < 2) {
        printf("please specify an input file\n");
        exit(1);
    }
    int mapperPipe[2]; //last index write end, first index read end

    if (pipe(mapperPipe) == -1) {
           perror("error piping");
           exit(EXIT_FAILURE);
    }

    pid_t firstChild = fork();

    checkForkError(firstChild);

    if(firstChild == 0) { //child
        mapperSetup(mapperPipe);
    }
    else {
        close(mapperPipe[0]);
        close(STDOUT_FILENO);
        dup(mapperPipe[1]);
        FILE* in = fopen(argv[1], "r");
        if(in == NULL) {
            perror("error opening file");
            exit(EXIT_FAILURE);
        }
        ssize_t read;
        size_t n;
        char* line = NULL;
        while(read = getline(&line, &n, in) != -1) {
            write(STDOUT_FILENO, line, n);
        }
        close(STDOUT_FILENO);
        free(line);
        wait(NULL);
    }
}

void inline checkForkError(pid_t pid) {
    if(pid < 0) {
        perror("error forking!!!");
    }
}

void mapperSetup(int mapperPipe[]) {
    int reducerPipe[2];

    if(pipe(reducerPipe) == -1) {
        perror("error piping");
        exit(EXIT_FAILURE);
    }

    pid_t secondChild = fork();

    checkForkError(secondChild);
    if(secondChild == 0) { //reducer process
        reducerSetup(reducerPipe);
    }
    else { //mapper process
        close(mapperPipe[1]); //close write end
        close(STDIN_FILENO); //close stdin
        dup(mapperPipe[0]); //dup pipe out to stdin

        close(reducerPipe[0]); //close read end
        close(STDOUT_FILENO); //close stdout
        dup(reducerPipe[1]); //dup output to reducer pipe

        if(execv("mapper", (char *[]){"mapper", NULL}) == -1) {
            perror("exec error");
            exit(EXIT_FAILURE);
        }
    }
}

void reducerSetup(int reducerPipe[]) {
    close(reducerPipe[1]); //close write end of second pipe
    close(STDIN_FILENO); //close stdin
    dup(reducerPipe[0]); //dup read end of pipe to stdin

    if(execv("reducer", (char *[]){"reducer", NULL}) != -1) {
        perror("exec error");
        exit(EXIT_FAILURE);
    }
}