C++管道问题
C++ piping issue
我正在尝试分叉我的 C++ 程序并将父级输出定向到子级输入,我正在使用 pipe() 和 fork()。在程序的目录中有一个名为 input.txt 的文件。不幸的是,我得到的唯一输出是 "wc: stdin: read: Bad file descriptor"。有人知道为什么吗?如果是这样,我做错了什么?谢谢
#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;
}
你把管道倒过来了,你已经把管道的写入端连接到了wc
的标准输入端。在 wc
检测到文件结束条件并正常终止之前,您需要关闭两个进程中管道的写入端。
您还错误地将原始标准输出还原为父级的标准输入。
此外 wc
默认情况下不会将标准输入解释为列表文件名,因此不会读取 input.txt
.
您的程序中有几个问题需要修正:
- 使用
STDIN_FILENO
和 STDOUT_FILENO
而不是 0 和 1。这个值在不同的平台上可能会改变,你也犯了一个错误,如果你使用名称而不是值,例如dup2(stdOut,0);
复制了 stdin
,您需要在此处复制 stdout
。
- 您应该关闭子进程和父进程的管道写端。
- 通过使
wc
从 stdin
读取,然后您将 "input.txt" 字符串传递给它 - 它会 return 该字符串的统计信息,而不是文件的统计信息。您可以通过打开该文件的文件描述符或使用 exec*
和 cat
. 来修复它
None 调用 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);
我正在尝试分叉我的 C++ 程序并将父级输出定向到子级输入,我正在使用 pipe() 和 fork()。在程序的目录中有一个名为 input.txt 的文件。不幸的是,我得到的唯一输出是 "wc: stdin: read: Bad file descriptor"。有人知道为什么吗?如果是这样,我做错了什么?谢谢
#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;
}
你把管道倒过来了,你已经把管道的写入端连接到了wc
的标准输入端。在 wc
检测到文件结束条件并正常终止之前,您需要关闭两个进程中管道的写入端。
您还错误地将原始标准输出还原为父级的标准输入。
此外 wc
默认情况下不会将标准输入解释为列表文件名,因此不会读取 input.txt
.
您的程序中有几个问题需要修正:
- 使用
STDIN_FILENO
和STDOUT_FILENO
而不是 0 和 1。这个值在不同的平台上可能会改变,你也犯了一个错误,如果你使用名称而不是值,例如dup2(stdOut,0);
复制了stdin
,您需要在此处复制stdout
。 - 您应该关闭子进程和父进程的管道写端。
- 通过使
wc
从stdin
读取,然后您将 "input.txt" 字符串传递给它 - 它会 return 该字符串的统计信息,而不是文件的统计信息。您可以通过打开该文件的文件描述符或使用exec*
和cat
. 来修复它
None 调用
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);