我正在星期二学习OS考试。为了准备,我试图通过C程序模拟命令行管道。
程序非常简单。我制作一个管道,然后分叉一个子进程。
子进程将标准输出重定向到管道的写端,关闭管道的文件描述符,然后执行命令(在这种情况下为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;
}
}
答案 0 :(得分:3)
您的第一个问题是您没有为您正在使用的功能添加所有必需的标题。 strerror
需要<string.h>
,wait
需要<sys/wait.h>
。
如果您正在使用gcc进行编译,请始终使用gcc -Wall
并阅读警告。在这种情况下,它会抱怨隐含声明strerror
。
由于未声明strerror
,编译器会假定它返回int
,这是错误的。如果您在64位Linux x86上运行该程序,int
与strerror
返回的指针甚至不是 size 。当您将strerror
的结果以fprintf
格式传递给%s
时,这会成为一个致命的问题,因为指针被误解为int然后转换回指针,结束假的价值。 fprintf
段错误,您永远不会看到错误消息。
包含正确的标题,您会看到一条错误消息,指出您需要解决的下一个问题。