重定向子进程中的标准输出是否也为父进程执行此操作?

时间:2014-11-16 22:38:25

标签: c linux bash

我正在星期二学习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;
    }
}

1 个答案:

答案 0 :(得分:3)

您的第一个问题是您没有为您正在使用的功能添加所有必需的标题。 strerror需要<string.h>wait需要<sys/wait.h>

如果您正在使用gcc进行编译,请始终使用gcc -Wall并阅读警告。在这种情况下,它会抱怨隐含声明strerror

由于未声明strerror,编译器会假定它返回int,这是错误的。如果您在64位Linux x86上运行该程序,intstrerror返回的指针甚至不是 size 。当您将strerror的结果以fprintf格式传递给%s时,这会成为一个致命的问题,因为指针被误解为int然后转换回指针,结束假的价值。 fprintf段错误,您永远不会看到错误消息。

包含正确的标题,您会看到一条错误消息,指出您需要解决的下一个问题。