我正在准备周二的操作系统考试。为了做好准备,我尝试通过 C 程序模拟命令行管道。
程序非常简单。我制作了一个管道,然后 fork 了一个子进程。
子进程将标准输出重定向到管道的写入端,关闭管道的文件描述符,然后执行命令(在本例中为 ls
)。
父进程等待子进程退出,将标准输入重定向到管道的读端,关闭管道的文件描述符,然后执行命令(grep 'school'
,在这种情况下)。
当我使用 ls | 通过命令行执行命令时grep 'school'
有一行内容是“school”打印到标准输出,这是有道理的,因为在我运行程序的目录中有一个目录命名为该目录。
当我运行我制作的程序时,我没有收到任何错误消息,但它也没有产生任何输出。
我唯一能想到的会阻止它工作的是在子进程中重定向标准输出会以某种方式影响父进程命令的输出,但我几乎肯定情况不应该如此.
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main() {
int fds[2];
int pipe_val, close_val, write_val, dup_val, status;
pid_t pid;
char *error;
pipe_val = pipe(fds);
if (pipe_val) {
fprintf(stderr, "Failed to prepare pipe.\n");
return -1;
}
pid = fork();
if (pid == -1) {
fprintf(stderr, "Failed to fork a child process.\n");
return -1;
} else if (pid == 0) {
dup_val = dup2(fds[1], STDOUT_FILENO);
if (dup_val) {
error = strerror(errno);
fprintf(stderr, "Failed to redirect standard output in child process because %s\n", error);
exit(1);
}
close_val = close(fds[0]);
if (close_val) {
fprintf(stderr, "Failed to close read-end of pipe in child process.\n");
exit(1);
}
close_val = close(fds[1]);
if (close_val) {
fprintf(stderr, "Failed to close write-end of pipe in child process.\n");
exit(1);
}
execl("/bin/ls", "ls", NULL);
fprintf(stderr, "Failed to execute command in child process.\n");
exit(1);
} else {
wait(&status);
dup_val = dup2(fds[0], STDIN_FILENO);
if (dup_val) {
error = strerror(errno);
fprintf(stderr, "Failed to redirect standard input in parent process because %s.\n", error);
return -1;
}
close_val = close(fds[0]);
if (close_val) {
fprintf(stderr, "Failed to close read-end of the pipe in the parent process.\n");
return -1;
}
close_val = close(fds[1]);
if (close_val) {
fprintf(stderr, "Failed to close write-end of the pipe in the parent process.\n");
return -1;
}
execl("/bin/grep", "grep", "school", NULL);
fprintf(stderr, "Failed to execute the command in the parent process.\n");
return -1;
}
}
最佳答案
您的第一个问题是您没有包含所用函数的所有必要 header 。 strerror
需要 <string.h>
和 wait
需要 <sys/wait.h>
.
如果您使用 gcc 进行编译,请始终使用 gcc -Wall
并阅读警告。在这种情况下,它会提示 strerror
的隐式声明。 .
因为 strerror
未声明,编译器假定它返回一个 int
,这是错误的。如果您在 64 位 Linux x86 上运行该程序,int
甚至与 strerror
返回的指针的大小 都不一样.当您随后传递 strerror
的结果时,这将成为一个致命问题。至 fprintf
用%s
格式,因为指针被错误解释为 int,然后又转换回指针,最后得到一个虚假值。 fprintf
段错误,您永远不会看到错误消息。
包含正确的 header ,您将看到一条错误消息,它将引导您解决下一个需要解决的问题。
关于c - 在子进程中重定向标准输出是否对父进程也是如此?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26962892/