【问题标题】:Two pipe in C and ls | sort | grep r [duplicate]C 和 ls 中的两个管道 |排序 | grep r [重复]
【发布时间】:2023-02-02 22:34:30
【问题描述】:

我需要创建一个程序,在 shell 中使用两个管道和三个进程执行此命令:ls |排序 |格雷普河我所做的代码是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>

#define WRITE 1
#define READ 0

int main(int argc, char** argv)
{

    int fd1[2],fd2[2];
    pid_t pid1,pid2;
    
    if( (pid1 = fork()) < 0)
    {
        perror("fork");
        exit(-1);
    }
    
    if( pipe(fd1) < 0)
    {
        perror("pipe 1");
        exit(-1);
    }
    
    if( pipe(fd2) < 0)
    {
        perror("pipe 2");
        exit(-1);
    }
    
    if( pid1 == 0 )
        pid2 = fork();
        
    if(pid1>0)
    {
        close(fd2[READ]);
        close(fd2[WRITE]);
        close(fd1[READ]);
        dup2(fd1[WRITE],STDOUT_FILENO);
        close(fd1[WRITE]);
        execlp("ls","ls",NULL);
        perror("ls");
        exit(-1);
    }
    
    if(pid2>0)
    {
        close(fd1[WRITE]);
        dup2(fd1[READ],STDIN_FILENO);
        close(fd1[READ]);
        close(fd2[READ]);
        dup2(fd2[WRITE],STDOUT_FILENO);
        close(fd2[WRITE]);
        execlp("sort","sort",NULL);
        perror("sort");
        exit(-1);
    }
    if(pid2==0)
    {
        close(fd1[READ]);
        close(fd1[WRITE]);
        close(fd2[WRITE]);
        dup2(fd2[READ],STDIN_FILENO);
        close(fd2[READ]);
        execlp("grep","grep","r",NULL);
        perror("grep");
        exit(-1);
    }

}

可能我对这两个管道的通信有误,因为我今天才知道它们是如何工作的。很抱歉,如果我弄错了一些关于管道的重要事情。我希望有人可以帮助我解决这个问题并解释我的错误。谢谢。

【问题讨论】:

  • 你是什​​么意思“在壳中”?您正在做管道工作而不是使用外壳。如果你真的想运行一个 shell 命令,查看 system 这将使你的程序变得微不足道

标签: c shell grep pipe ls


【解决方案1】:

您在第一个叉子之后(但在第二个叉子之前)创建了管道。

这意味着您调用了 pipe 4 次,在第一个 fork 之后存在的每个进程中调用了 2 次。

所以 fd1fd2 有一组主进程的值(pid1&gt;0 的一组值,也就是执行 ls 的一组值),另一组用于子进程和孙进程(第二个 fork 在之后完成)管道的创建,所以这里没有问题:执行sortgrep的两个进程确实共享相同的文件描述符)。

所以对于 sort | grep 部分,没问题。 sort 的输出是fd2[1],而grep 的输入是fd2[0],如你所愿,fd2 是同一个pipe 调用的结果,在第二次分叉之前执行,因此共享在这两个过程之间。

但是对于 ls | sort 部分,你所做的就像你做了类似的事情

    if(fork()){
        int fd[2];
        pipe(fd);
        close(fd[0]);
        dup2(fd[1], 1);
        printf("Hello
");
        exit(0);
    }else{
        int fd[2];
        pipe(fd);
        close(fd[1]);
        dup2(fd[0], 0);
        char s[100];
        scanf("%s", s);
        printf("Should be hello=%s
", s);
        exit(0);
    }

不会按预期工作。这两个进程的fd 之间没有任何关系。

所以你需要创建管道叉子。

至少,您打算在将由此分支创建的进程之间共享的管道。

我想我知道你为什么要做这件奇怪的事。由于 3 进程管道链的另一个警告:我们经常看到人们在分叉两次之前创建所有管道,使他们的代码工作时遇到问题。另一个原因:他们通常忘记他们的管道存在于 3 个进程中,他们需要关闭所有他们不使用的管道。即使在与fd1无关的进程中,fd1的两端也必须关闭。

编辑: 你做的另一件奇怪的事情是,即使在你想要使用它的过程中(就在 dup2 之后),也关闭了 fd1[WRITE]。你不能那样做。这不像在 dup2 之后你可以关闭原始管道,因为你会有一个副本,或类似的东西。它是同一文件的描述符副本。如果您关闭该文件,它也会为副本关闭。

【讨论】:

    猜你喜欢
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多