gpt4 book ai didi

c - 将一个子进程管道化为另一个子进程

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:48:00 24 4
gpt4 key购买 nike

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

当我在 `bash 中像这样运行我的 mapperreducer 时:

./mapper < input.txt | reducer

它运行完美,但下面的程序什么都不输出并卡在 wait(NULL);

我的代码

#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);
}
}

最佳答案

问题是,当您在 dup 之后有多个 fd 时,您必须关闭原始的以及新的 dup完成发送 EOF

简而言之,FD 引用计数针对 dup 递增。

另一个问题是我的进程树是线性的,不是一个进程的两个子进程,所以主进程在输出之前就退出了,导致bash在执行完之后还有输出,让它看起来像是挂了它不是。

解决方案是通过稍作重构从父进程创建管道和分支。

特别感谢帮助我的 Russell Reed。

关于c - 将一个子进程管道化为另一个子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34817079/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com