gpt4 book ai didi

c - 无法写入 2 个进程的管道 IPC

转载 作者:太空宇宙 更新时间:2023-11-04 08:52:33 25 4
gpt4 key购买 nike

我有 2 个进程(一个“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*() 的返回值系统调用。如果函数返回,则失败。同样,您应该确保进程在此之后退出。在这个程序中, child 是否继续并不重要;在许多程序中,不退出会导致困惑(例如,两个进程试图同时读取标准输入)。

不需要 pipe_fd成为一个全局变量。请确保您的所有消息都以换行符结尾。你没有包括 <sys/wait.h>所以你在没有原型(prototype)的情况下工作 waitpid()功能——这通常是个坏主意。您应该将编译器设置为 fussy,以便它要求每个函数在使用或定义之前在范围内都有一个原型(prototype)。您可以在定义中初始化参数列表:

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

这具有不切换的关键有益副作用 prog_argv2[1]使用 NULL 指针(如 Matthias 在他的 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com