我正在为星期二的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;
}
}
您的第一个问题是,您尚未包括所使用函数的所有必需标头。strerror
需要<string.h>
和wait
需要<sys/wait.h>
。
如果使用gcc进行编译,请务必使用gcc -Wall
并阅读警告。在这种情况下,它会抱怨的隐式声明strerror
。
由于strerror
未声明,因此编译器假定它返回int
,这是错误的。如果您在64位Linux x86上运行程序,int
则其大小甚至与所返回的指针的大小也不相同strerror
。当您随后使用格式将结果传递strerror
给to时,这将成为一个致命问题,因为指针已被误解为一个int值,然后又转换回指针,最后得到一个伪造的值。segfaults,您将永远不会看到错误消息。fprintf
%s
fprintf
包括正确的标题,您将看到一条错误消息,将导致您需要解决的下一个问题。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句