微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

管道重定向问题,丢失数据

如何解决管道重定向问题,丢失数据

我想用一个小的 c 程序重现这个 shell 行为:

< file cmd1 | cmd2

因此它需要三个参数并且可以这样执行,例如:

./a.out foo /bin/cat /usr/bin/wc

这是我的代码,没有错误检查:

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

static void exe_cmd(char *cmd,char **env)
{
    int     pid;
    char    *av[] = {cmd,NULL};

    pid = fork();
    if (pid == 0)
    {
        execve(av[0],av,env);
        exit(0);
    }
    waitpid(pid,NULL,0);
}

static void left_pipe_side(int fd[2],char *cmd,char *path,char **env)
{
    int file;

    file = open(path,O_RDONLY);
    dup2(fd[1],STDOUT_FILENO); // Can be commented out to see the first command output
    dup2(file,STDIN_FILENO);
    close(fd[0]);
    close(fd[1]);
    close(file);
    exe_cmd(cmd,env);
}

static void right_pipe_side(int fd[2],char **env)
{
    dup2(fd[0],STDIN_FILENO);
    close(fd[1]);
    close(fd[0]);
    exe_cmd(cmd,env);
}

int main(int ac,char **av,char **env)
{
    int fd[2];
    pid_t   pid;

    pid = fork();
    pipe(fd);
    if (pid == 0)
    {
        left_pipe_side(fd,av[2],av[1],env);
        exit(0);
    }
    right_pipe_side(fd,av[3],env);
    waitpid(pid,0);
    return (0);
}

我的问题是作为第二个命令的 wc输出将始终为 0 0 0,就好像输入是空的(但给定的文件包含文本)。 如果我注释掉我在左管道侧将 fd[1] 复制到 stdout 的行,第一个命令将正确输出,所以我不明白为什么重定向使这些数据“消失”

解决方法

您在 pipe 之后打开 fork,因此每个进程都有自己的无关 pipe。之前打开它,以便它在进程之间共享。

pipe(fd);
pid = fork();
,

在您的代码中,您在 pipe 之后打开 fork,这意味着每个进程都有自己的 pipe 而这不是管道的工作方式

您必须在 pipes 之前打开 fork,它使进程与您的管道链接。

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

static void exe_cmd(char *cmd,char **env)
{
    int     pid;
    char    *av[] = {cmd,NULL};

    pid = fork();
    if (pid == 0)
    {
        execve(av[0],av,env);
        exit(0);
    }
    waitpid(pid,NULL,0);
}

static void left_pipe_side(int fd[2],char *cmd,char *path,char **env)
{
    int file;

    file = open(path,O_RDONLY);
    dup2(fd[1],STDOUT_FILENO); // Can be commented out to see the first command output
    dup2(file,STDIN_FILENO);
    close(fd[0]);
    close(fd[1]);
    close(file);
    exe_cmd(cmd,env);
}

static void right_pipe_side(int fd[2],char **env)
{
    dup2(fd[0],STDIN_FILENO);
    close(fd[1]);
    close(fd[0]);
    exe_cmd(cmd,env);
}

int main(int ac,char **av,char **env)
{
    int fd[2];
    pid_t   pid;
    /************************ the error part **********************/
    // pid = fork();
    // pipe(fd);
    pipe(fd);
    pid = fork();
    /**************************************************************/

    if (pid == 0)
    {
        left_pipe_side(fd,av[2],av[1],env);
        exit(0);
    }
    right_pipe_side(fd,av[3],env);
    waitpid(pid,0);
    return (0);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。