我正在使用以下代码部分为我的自定义C ++ shell执行输入重定向。 虽然类似于此的输出重定向效果很好,但输入重定向的子进程保持打开状态并且不会返回,就像它一直等待新输入一样。 什么是“询问”或“强制”这样的子进程在阅读输入后立即返回的最佳方法是什么?
int in_file = open(in, O_CREAT | O_RDONLY , S_IREAD | S_IWRITE);
pid_t pid = fork();
if (!pid) {
dup2(in_file, STDIN_FILENO);
if (execvp(argv[0], argv) < 0) {
cerr << "*** ERROR: exec failed: "<< argv[0] << endl;
exit(EXIT_FAILURE);
}
}
close(in_file);
out_file = open(out, O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU);
pid_t pid = fork();
if (!pid) {
dup2(out_file, STDOUT_FILENO);
if (execvp(argv[0], argv) < 0) {
cerr << "*** ERROR: exec failed: "<< argv[0] << endl;
exit(EXIT_FAILURE);
}
}
close(out_file);
我使用以下命令进行测试:
ps aux > out.txt
grep root < out.txt
第一个命令在成功写入out.txt后返回shell。第二个命令从out.txt中成功读取,但不返回或停止。
答案 0 :(得分:0)
首先,检查execvp()
的参数。如果此代码属于main(int argc, char* argv[])
,则argv[0]
是您自己的程序,而不是grep
。这意味着您的程序将永久地以递归方式重新执行。
然后,确保在使用:
打开in
时没有错误
if (in_file < 0) { perror(in); ... }
如果in_file
是无效的描述符,dup2()
将失败,grep
将从终端读取,因此,不会终止。顺便说一句,使用O_CREAT | O_RDONLY
看上去很狡猾。为什么要从以前不存在的文件中读取?
答案 1 :(得分:0)
孩子仍然打开in_file。你必须在exec:
之前关闭它dup2(in_file, STDIN_FILENO);
close(in_file);
(为简洁起见,省略了错误检查)。因为孩子仍然有一个打开的文件描述符,所以它永远不会将文件视为关闭,因此它会阻止读取等待某人写入更多数据。子进程没有意识到它是保持文件描述符打开的那个。另一种选择是为文件描述符设置'close-on-exec'标志,以便在exec上自动关闭。 (搜索FD_CLOEXEC)