我有两个进程(“ls”进程和“grep”)。我用管子在他们两人之间交流。但grep进程无法从管道中读取。你能帮我弄清楚为什么吗?
这是我的密码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int pipe_fd[2];

int main()
{
    pid_t p1,p2;
    char *prog1_argv[4];
    char *prog2_argv[2];
    /* Build argument list */
    prog1_argv[0] = "ls";
    prog1_argv[1] = "-l";
    prog1_argv[2] = "/";
    prog1_argv[3] = NULL;
    prog2_argv[0] = "grep";
    prog2_argv[1] = "s";
    prog2_argv[1] = NULL;
    if (pipe(pipe_fd) < 0)
    {
        printf ("pipe failed");
    }
    p1 = fork();
    if(p1 == 0)
    {
        printf("in child\n");
        close(pipe_fd[0]);
        if(dup2(pipe_fd[1],1)<0)
        {
            printf("dup failed:%d\n",errno);
        }
        close(pipe_fd[1]);
        if(execvp (prog1_argv[0], prog1_argv)<0)
            printf("exec failed");
    }
    if(p1>0)
    {
        printf("im in parent\n");
        waitpid(p1,NULL,0);
        printf("parent: child exited. Now test the pipe\n");
        close(pipe_fd[1]);
        if(dup2(pipe_fd[0],0)<0)
        {
            printf("dup failed:%d\n",errno);
        }
        close(pipe_fd[0]);

        if(execvp (prog2_argv[0], prog2_argv)<0)
            printf("exec failed");

    }

}

最佳答案

基本上,您不应该在运行ls之前等待grep死亡。
ls命令可能生成的数据太多,无法全部存储在管道中,因此ls命令将阻塞,直到另一个进程从管道中读取数据,但另一个进程正在等待ls完成,然后再尝试从管道中读取任何数据。这是个僵局。
另外,通过这样的等待,您可以强制执行串行执行,这会丢掉多个内核的好处。
你应该做一些小的改进。报告错误的点有很多。应在标准错误流(stderr上报告错误,而不是在stdout上报告错误。您还应该确保程序在至少出现某些错误后不会继续。
您不必测试任何exec*()系统调用的返回值。如果函数返回,则失败。再一次,您应该确保进程在这之后退出。在这个程序中,孩子继续下去并不重要;在许多程序中,不退出会导致混乱(例如,同时读取标准输入的两个进程)。
不需要将pipe_fd作为全局变量。请确保您的所有邮件都以换行符结尾。您没有包含<sys/wait.h>所以您在waitpid()函数的作用域中没有原型——这通常是个坏主意。您应该将编译器设置为fussy,以便它要求在使用或定义每个函数之前,其作用域中都有一个原型。可以在定义中初始化参数列表:

char *prog1_argv[] = { "ls", "-l", "/", NULL };
char *prog2_argv[] = { "grep", "s", NULL };

这有一个至关重要的有益的副作用,即不使用空指针(如hisMatthias中的answer所述)。我还删除了数组的大小;第二个数组的维数是2,需要是3,但是当您像这样初始化时,编译器会进行计数。
正确地做了一件重要的事情,那就是确保管道文件描述符都已关闭。
这对我来说是正确的:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

int main(void)
{
    pid_t p1;
    int pipe_fd[2];
    char *prog1_argv[] = { "ls", "-l", "/", NULL };
    char *prog2_argv[] = { "grep", "s", 0 };
    if (pipe(pipe_fd) < 0)
    {
        fprintf(stderr, "pipe failed:%d\n", errno);
        exit(1);
    }
    p1 = fork();
    if (p1 == 0)
    {
        printf("In child\n");
        close(pipe_fd[0]);
        if (dup2(pipe_fd[1], 1) < 0)
        {
            fprintf(stderr, "dup failed:%d\n", errno);
            exit(1);
        }
        close(pipe_fd[1]);
        execvp(prog1_argv[0], prog1_argv);
        fprintf(stderr, "exec failed:%d\n", errno);
        exit(1);
    }
    if (p1 > 0)
    {
        printf("In parent\n");
        close(pipe_fd[1]);
        if (dup2(pipe_fd[0], 0) < 0)
        {
            fprintf(stderr, "dup failed:%d\n", errno);
            exit(1);
        }
        close(pipe_fd[0]);

        execvp(prog2_argv[0], prog2_argv);
        fprintf(stderr, "exec failed:%d\n", errno);
        exit(1);
    }
    fprintf(stderr, "Fork failed:%d\n", errno);
    return(1);
}

关于c - 无法写入2个进程的管道IPC,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19095173/

10-11 23:00
查看更多