c - c 中的 pipe() 和 fork()

标签 c fork pipe

我需要创建两个子进程。一个子进程需要运行命令“ls -al”并将其输出重定向到下一个子进程的输入,后者又将对其输入数据运行命令“sort -r -n -k 5”。最后,父进程需要读取它(数据已经排序)并将其显示在终端中。终端中的最终结果(执行程序时)应该与我直接在 shell 中输入以下命令一样:“ls -al | sort -r -n -k 5”。为此,我需要使用以下方法:pipe()、fork()、execlp()。

我的程序可以编译,但我没有将所需的输出输出到终端。我不知道出了什么问题。这是代码:

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main()
{
    int fd[2];
    pid_t ls_pid, sort_pid;
    char buff[1000];

    /* create the pipe */
    if (pipe(fd) == -1) {
        fprintf(stderr, "Pipe failed");
        return 1;
    }

    /* create child 2 first */
    sort_pid = fork();
    if (sort_pid < 0) {                         // error creating Child 2 process
        fprintf(stderr, "\nChild 2 Fork failed");
        return 1;
    }
    else if(sort_pid > 0) {                     // parent process

        wait(NULL);                             // wait for children termination

        /* create child 1 */
        ls_pid = fork();
        if (ls_pid < 0) {                       // error creating Child 1 process
            fprintf(stderr, "\nChild 1 Fork failed");
            return 1;
        }
        else if (ls_pid == 0) {                 // child 1 process
            close(1);                           // close stdout
            dup2(fd[1], 1);                     // make stdout same as fd[1]
            close(fd[0]);                       // we don't need this end of pipe
            execlp("bin/ls", "ls", "-al", NULL);// executes ls command
        }

        wait(NULL);
        read(fd[0], buff, 1000);                // parent reads data 
        printf(buff);                           // parent prints data to terminal   
    }
    else if (sort_pid == 0) {                   // child 2 process
        close(0);                               // close stdin
        dup2(fd[0], 0);                         // make stdin same as fd[0]
        close(fd[1]);                           // we don't need this end of pipe
        execlp("bin/sort", "sort", "-r", "-n", "-k", "5", NULL); // executes sort operation
    }

    return 0;
}

最佳答案

您的父进程在创建 ls 进程之前等待s s 排序进程完成。

排序过程需要在完成之前读取其输入。它的输入来自 ls,直到 wait 之后才会启动。死锁。

您需要创建两个进程,然后为它们等待

此外,您的文件描述符操作不太正确。在这对调用中:

close(0);
dup2(fd[0], 0);

关闭是多余的,因为 dup2 将自动关闭现有的 fd 0(如果有的话)。您应该在 dup2 之后执行 close(fd[0]),这样您只有一个文件描述符绑定(bind)到管道的那一端。如果你想变得非常健壮,你应该已经测试 wither fd[0]==0,在这种情况下跳过 dup2 并关闭。

也将所有这些应用于其他 dup2。

然后是父进程保持管道打开的问题。我会说你应该在将它们传递给 child 之后关闭父管道的两端,但是你有那个奇怪的 read from fd[0] 在最后一个 wait 之后......我不确定为什么会在那里。如果 ls|sort 管道运行正确,之后管道将为空,因此不会有任何可读取的内容。在任何情况下,您肯定需要关闭父级中的 fd[1],否则排序过程将无法完成,因为在所有写入器关闭之前管道不会指示 EOF。

在奇怪的 read 之后是一个可能会崩溃的 printf,因为读取缓冲区不会被 '\0' 终止.

使用 execlp 的要点是它会为您执行 $PATH 查找,因此您不必指定 /bin/。我的第一次测试运行失败,因为我的排序在 /usr/bin/ 中。为什么在不需要时对路径进行硬编码?

关于c - c 中的 pipe() 和 fork(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16876130/

相关文章:

c - 如何在 C 中执行 grep 操作?

c - 使用 dup2 重定向时出现空白字符串

c - C语言中的fork函数

linux - 在 fork 之前或之后在磁盘文件上调用 mmap() 有什么区别?

c - x86 上的简单 PAPI 分析中意外出现大量 TLB 未命中

c++ - WxWidgets:简单的数学公式给出错误的结果?

c - 需要帮助创建和未知数量的命名管道来拆分和排序数据

g++ - 在 g++ 中管道文件内容进行编译

c - %g 浮点表示的最大字符串长度是多少?

c - 如何使用 scanf() 保存包含多个单词的字符串