c - 在子进程中重定向标准输出是否对父进程也是如此?

标签 c linux bash

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

相关文章:

C printf() 格式化 : Float doesn't seem to right justify.

无法使用 XOR C 加密器加密长字符串

将字符串复制到 char 数组中

linux - 如何自动为大列表添加增量数字?

java - 在 Linux 上部署 war

linux - shell语言的数据组

c - 使文件在所有节点上可用

linux - 在 ubuntu 10.10 中使用 Opengl-es 2.0 编程

linux - 如何删除 ~ 而不删除我的主目录?

Python 无法正确运行 shell 命令