我分叉并设置了这样的命令:
pid_t pid;
pid = fork();
if (pid == 0)
{ // I am the child
freopen("/input_pipe","r",stdin);
freopen("/output_pip","w",stdout);
execl("/bin/sh", "sh", "-c", command, (char *)NULL); // using execv is probably faster
// Should never get here
perror("execl");
exit(1);
}
Run Code Online (Sandbox Code Playgroud)
/input_pipe 在进程分叉之前已经创建并填充了数据。
这在几乎所有情况下都非常有效。该命令read()从其标准输入读取(使用)并获取由另一个进程写入管道的数据。
但有时该命令无法从其 stdin 流中读取,并在尝试这样做时收到“错误的文件描述符”错误。
什么可能导致此错误?
编辑:我已将 freopen 部分更改为:
pipe_in = open(pipename_in, O_RDONLY);
pipe_out = open(pipename_out, O_WRONLY);
dup2(pipe_in, 0);
dup2(pipe_out, 1);
Run Code Online (Sandbox Code Playgroud)
我将对此进行几天的测试,因为错误很少出现。
一个可能的问题来源是“stdin”和“stdout”不一定分别对应于文件描述符 0 和 1。在运行时库的许多实现中,freopen可能会更改属于 FILE* 的文件描述符。文件描述符属于内核,而文件属于运行时库,它们不一定是对齐的。
请看这里:
http://man7.org/linux/man-pages/man3/stdout.3.html
“将 freopen(3) 应用于这些流之一可以更改与流关联的文件描述符编号”
execl 之后,子进程只期望文件描述符 0 和 1 是标准输入和输出,但可能会发生 freopen 关闭 fd 0 并将另一个 fd 连接到 (FILE*)stdin。我建议您使用“open”、“close”、“dup”等系统调用并直接处理文件描述符 0 和 1(或者更好的是标准宏 STDIN_FILENO 和 STDOUT_FILENO)。