我正在尝试使用 dup2()
、fork()
和 pipe()
创建递归管道函数。但是,当我的数组类似于 {"ls", "grep shell"}
(其中 shell 是我的 shell 的名称)时,它会无限循环显示 ls 的结果并说“写入错误:错误的文件描述符”。我确定我没有以某种方式正确终止我的递归,我怀疑问题在于尝试复制 fd[1]
或 fd[0]
,但是在调试了几个小时之后,我仍然无法弄清楚。感谢您的帮助!
void recursive_piping(char *recursive_pipe_args[MAX_ARGS]) {
int i = 0;
int fd[2];
char *first_arg[2] = {"", NULL};
char *rest_of_args[81];
// if its of size 1, base case
if (recursive_pipe_args[1] == NULL) {
if (execvp(recursive_pipe_args[0], recursive_pipe_args) == -1) {
printf("\nExecute didn't work");
fflush(stdout);
}
return;
}
// recursive case, split args into the first on and the rest of them
first_arg[0] = recursive_pipe_args[0];
for (i = 0; i < (num_pipes); i++) {
rest_of_args[i] = malloc(81);
strcpy(rest_of_args[i], recursive_pipe_args[i+1]);
}
if (pipe(fd) < 0) {
printf("\npipe Failure");
}
// parent section, reads file descriptor fd[0]
if (fork()) {
close(fd[0]);
dup2(fd[1], 0);
recursive_piping(rest_of_args);
// return;
}
close(fd[1]);
dup2(fd[0], 1);
execvp(first_arg[0], first_arg);
}
最佳答案
我用这些变化准备了你的函数的变体:
- 它添加了对
recursive_pipe_args
的第一个元素是否为NULL
的检查,在这种情况下它会发出诊断而不执行任何操作。 - 它计算
recursive_pipe_args
数组中初始非 NULL 元素的数量,并动态分配具有该容量的rest_of_args
(从而允许空间用于少一个参数加上NULL
标记)。 - 根据前者的实际元素个数,将
recursive_pipe_args
的尾部复制到rest_of_args
中,从而确保复制NULL
哨兵。 - 它识别并处理
fork()
中的错误。 - 它纠正了复制,以便每个管道 (
fd[1]
) 的写入端被复制到标准输出(文件描述符1
),读取端被复制到标准输入(分别为fd[0]
和0
),并且在每个进程中,该进程中未使用的管道末端被关闭。 - 它将错误消息写入标准错误流而不是标准输出,尽可能依赖于
perror()
。
生成的程序按我的预期工作:它将指定的命令管道的结果发送到它的标准输出。但是请注意,您的设计本质上仅限于不带任何参数的命令,这严重限制了它的实用性。我的测试用例是 { "ls", "wc"}
。
实现这些更改的代码留作练习。
关于c - 使用 Execvp、fork 和 pipe 的递归管道函数中的错误文件描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51987191/