子进程中重定向标准输出会影响父进程吗?

3
我正在准备周二的操作系统考试。为了准备,我正在尝试通过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;
    }
}

在等待之前,您需要在父进程中关闭文件描述符。 - William Pursell
1个回答

3
您的第一个问题是您没有包含使用的函数所需的所有必要头文件。`strerror`需要``,而`wait`需要``。
如果您使用gcc编译,请始终使用`gcc -Wall`并阅读警告。在这种情况下,它会抱怨`strerror`的隐式声明。
因为`strerror`没有被声明,编译器假设它返回一个`int`,这是错误的。如果您在64位Linux x86上运行程序,则`int`甚至不与由`strerror`返回的指针相同的大小。 当您然后将`strerror`的结果作为具有`%s`格式的参数传递给`fprintf`时,这将成为致命问题,因为指针已被错误地解释为int,然后转换回指针,最终得到虚假的值。 `fprintf`崩溃了,您永远看不到错误消息。
包含正确的标头,您将看到一个错误消息,这将引导您解决下一个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接