繁体   English   中英

Pipe 命令与 fork 和 dup2

[英]Pipe commands with fork and dup2

我为 pipe 两个命令编写了以下代码:

#include <stdlib.h>
#include <unistd.h>

char    *program_1[3] = {"/bin/cat", "/dev/random", NULL};
char    *program_2[2] = {"/bin/ls", NULL};
char    *program_3[2] = {"/usr/bin/sort", NULL};

int main(void)
{
    int fd[2];
    int pid;

    pipe(fd);
    if ((pid = fork()) == 0) //Child process
    {
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        execve(program_3[0], program_3, NULL);
    }
    else if (pid > 0) //Parent process
    {
        dup2(fd[0], STDIN_FILENO);
        close(fd[1]);
        execve(program_2[0], program_2, NULL);
    }
    return (EXIT_SUCCESS);
}

每对 program_x / program_y 其中 x,= y 工作正常。 除了这个,当我将 pipe 排序为 ls 时,ls 会在标准输出上很好地打印其 output,但随后:排序抛出此错误: sort: Input/output error

当我输入sort | ls sort | ls进入 bash,它将 ls 结果打印为我的程序,然后等待输入。

我做错了吗?

编辑:我正在尝试重新实现 shell 的行为

问题是当ls完成时,父进程将退出,这将关闭 pipe 的读端,这将导致错误传播到 pipe 的写端,通过sort检测并写入错误信息。

在 shell 中不会发生这种情况是因为 shell 处理管道的方式与您的简单示例程序不同,并且它使 pipe 的右侧保持打开并运行(可能在后台),直到您通过EOFCtrl-D )到sort程序。

您的程序并不完全等同于 shell 通常所做的。

您正在用ls替换父级; 而 shell 将创建谁子进程并连接它们并等待它们完成。

它更像是:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

char    *program_2[2] = {"/bin/ls", NULL};
char    *program_3[2] = {"/usr/bin/sort", NULL};

int main(void)
{
    int fd[2];
    pid_t pid;
    pid_t pid2;

    pipe(fd);
    if ((pid = fork()) == 0) //Child process
    {
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        execve(program_3[0], program_3, NULL);
    }
    else if (pid > 0) //Parent process
    {
        if ( (pid2 = fork()) == 0) {
            dup2(fd[0], STDIN_FILENO);
            close(fd[1]);
            execve(program_2[0], program_2, NULL);
        }
    }

    waitpid(pid, 0, 0);
    waitpid(pid2, 0, 0);
    return (EXIT_SUCCESS);
}

我终于找到了解决方案,我们接近:

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

char    *cat[3] = {"/bin/cat", "/dev/random", NULL};
char    *ls[2] = {"/bin/ls", NULL};
char    *sort[2] = {"/usr/bin/sort", NULL};

int main(void)
{
    int fd[2];
    pid_t pid;
    pid_t pid2;

    pipe(fd);
    if ((pid = fork()) == 0)
    {
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        execve(cat[0], cat, NULL);
    }
    else if (pid > 0)
    {
        if ( (pid2 = fork()) == 0)
        {
            dup2(fd[0], STDIN_FILENO);
            close(fd[1]);
            execve(ls[0], ls, NULL);
        }
        waitpid(pid2, 0, 0);
        close(fd[0]);
    }
    waitpid(pid, 0, 0);
    return (EXIT_SUCCESS);
}

一旦最后一个进程结束,我们需要关闭 pipe 的读取端,这样,如果第一个进程尝试在 pipe 上写入,则会抛出错误并退出进程,否则如果它只从标准输入读取sort ,它将继续阅读,因为标准输入仍处于打开状态

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM