我试图分叉我的c ++程序并将父输出指向childs输入,我使用的是pipe()和fork()。在程序的目录中有一个名为input.txt的文件。不幸的是,我得到的唯一输出是" wc:stdin:读取:错误的文件描述符"。有人知道为什么吗?如果是这样,我做错了什么?谢谢
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
int main(int argc, char *argv[]){
int pipes[2],pid,stdIn,stdOut;
stdIn = dup(0);
stdOut = dup(1);
pipe(pipes);
pid = fork();
if(pid == 0){
dup2(pipes[1],0);
close(pipes[1]);
execlp("wc","wc",NULL);
}
else{
dup2(pipes[0],1);
close(pipes[0]);
std::cout<<"input.txt"<<std::endl;
dup2(stdOut,0);
std::cout<<"parent done\n";
wait(NULL);
}
std::cout<<"after"<<std::endl;
return 0;
}
答案 0 :(得分:1)
您的计划中有几件事需要修复:
STDIN_FILENO
和STDOUT_FILENO
而不是0和1.这些值可能会在不同的平台上发生变化而且您也犯了一个错误,如果您使用名称而不是值,则可能会出错例如dup2(stdOut,0);
重复stdin
,您需要在此处复制stdout
。wc
读取stdin
,然后将“input.txt”字符串传递给它 - 它将返回该字符串的统计信息,而不是文件。你可以修复它,打开该文件的文件描述符,或者使用exec*
cat
。您的所有调用都没有pipe()
或execlp()
等函数检查失败。你应该这样做:
if (pipe(pipes) == -1) {
perror("pipe");
exit(1);
}
您不需要stdIn
变量。
你会在下面找到固定的代码(它没有实现我在(5)中描述的内容):
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int pipes[2], pid, stdOut;
stdOut = dup(STDOUT_FILENO);
pipe(pipes);
pid = fork();
if (pid == 0) {
dup2(pipes[0], STDIN_FILENO);
/* You need to close write end of the pipe here */
close(pipes[1]);
execlp("wc", "wc", NULL);
} else {
std::cout << "Parent setup" << std::endl;
dup2(pipes[1], STDOUT_FILENO);
/* You need to close write end of the pipe here as well */
close(pipes[1]);
/* This will only send the string "input.txt" through the pipe, to the
* wc command */
std::cout << "input.txt" << std::endl;
dup2(stdOut, STDOUT_FILENO);
std::cout << "Parent done" << std::endl;
wait(NULL);
}
std::cout << "Program finished" << std::endl;
return 0;
}
编辑:正如对其他答案的评论中所建议的那样,您可以简单地使用xargs wc
将stdint作为文件参数读取:
execlp("xargs", "xargs","wc",NULL);
答案 1 :(得分:0)
管道向后,您已将管道的写入端连接到wc
的标准输入。在wc
检测到文件结束条件并正常终止之前,您需要在两个进程中关闭管道的写入端。
您还错误地将原始标准输出还原为父级的标准输入。
此外,wc
默认情况下不会将标准输入解释为列表文件名,因此不会读取input.txt
。