Unix中的C:fork、waitpid和管道
我的问题是关于如何控制与管道相关的流程执行,特别是Unix中的C:fork、waitpid和管道,c,unix,pipe,fork,waitpid,C,Unix,Pipe,Fork,Waitpid,我的问题是关于如何控制与管道相关的流程执行,特别是wait/waitpid函数的实现 当我为以下命令创建管道时,我执行以下操作: 我创建管道,创建子管道 对于子级,我为stdin调用dup2,执行head-3命令,关闭子级中管道的输出端 对于父级,我为stdout调用dup2,执行ls命令,关闭父级中管道的输入端 我的问题:,我确实需要等待孩子完成执行,即执行head-3。但是如何/在何处实现waitpid函数,使其不会与close[]命令冲突 基于此,描述内容如下: 如果父级希望从子级接收
wait
/waitpid
函数的实现
当我为以下命令创建管道时,我执行以下操作:
- 我创建管道,创建子管道
- 对于子级,我为stdin调用dup2,执行
命令,关闭子级中管道的输出端head-3
- 对于父级,我为stdout调用dup2,执行
命令,关闭父级中管道的输入端ls
head-3
。但是如何/在何处实现waitpid
函数,使其不会与close[]
命令冲突
基于此,描述内容如下:
如果父级希望从子级接收数据,则应关闭fd1,子级应关闭fd0。如果父级希望向子级发送数据,则应关闭fd0,子级应关闭fd1。因为描述符在父级和子级之间共享,所以我们应该始终确保关闭我们不关心的管道末端。根据技术说明,如果管道的不必要端部未明确关闭,则EOF将永远不会返回
因此,在执行之前,子级必须等待父级完成管道
我也看到过一些例子,其中一个流程使用管道制作了两个叉子。这是不是为了避免僵尸进程,就像我在APUE ch.8的副本中所描述的那样
考虑以下代码实现:
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
int main()
{
int pid, status;
int fd[2];
char *com1[2];
char *com2[3];
com1[0] = "ls";
com1[1] = NULL;
com2[0] = "head";
com2[1] = "-3";
com2[2] = NULL;
pipe(fd);
if((pid = fork()) == -1)
{
printf("fork error");
exit(1);
}
if(pid == 0)
{
/* Child process closes up output side of pipe */
dup2(fd[0], 0);
close(fd[1]);
execvp(com2[0], com2);
}
else
{
/* if(waitpid(0, WIFEXITED(&status), 0) != pid)
{
printf("wait error");
}
is this even needed here? */
/* Parent process closes up input side of pipe */
dup2(fd[1], 1);
close(fd[0]);
execvp(com1[0], com1);
}
exit(0);
}
#包括
#包括
#包括
#包括
int main()
{
int-pid,状态;
int-fd[2];
char*com1[2];
char*com2[3];
com1[0]=“ls”;
com1[1]=NULL;
com2[0]=“头部”;
com2[1]=“-3”;
com2[2]=NULL;
管道(fd);
如果((pid=fork())=-1)
{
printf(“fork错误”);
出口(1);
}
如果(pid==0)
{
/*子进程关闭管道的输出端*/
dup2(fd[0],0);
关闭(fd[1]);
execvp(com2[0],com2);
}
其他的
{
/*if(waitpid(0,WIFEXITED(&status),0)!=pid)
{
printf(“等待错误”);
}
这里需要这个吗*/
/*父进程关闭管道的输入端*/
dup2(fd[1],1);
关闭(fd[0]);
execvp(com1[0],com1);
}
出口(0);
}
我必须承认,我已经在StackExchange上浏览了许多类似的问题。然而,几乎所有这些都有特定的内容。我要找的是对原理和功能组合的解释。谢谢你抽出时间 你不能既想等孩子又想执行。所以你需要有两个孩子。有两种常见的方法可以做到这一点,要么有一个创建两个直接子级的父进程,然后可以/必须等待这两个子进程;或者让一个子进程自己创建第二个进程,这样父进程只需等待一个进程终止 选项1(继承的管道) 选项2(管道仅对相关流程可见)
如果希望父进程继续执行,则需要创建两个子进程:一个用于
ls
命令,另一个用于head
命令。不,子级(在您的程序中)不必等待父级,如果当前没有要从管道中读取的内容,则所有非阻塞读取(默认)都将阻塞,直到有数据要读取或出现错误为止。@JoachimPileborg:“所有非阻塞读取都将阻塞”?Ehm。。。所有非阻塞读取都将阻塞我的意思是…:)“有一个自己创造第二个孩子”那么谁会等第二个呢?这和一个孩子的情况是一样的。显然,两个孩子和一个孩子的情况不同(主要的优点是父母现在可以等待……)。所有这些都应该包含在一个流程组中,更易于管理,但这是另一个故事……在第二个代码片段中,您只有一个waitpid。第二个孩子去哪里了?不需要,终止的孩子将被initd
继承,谁将等待它。所以你不在乎孩子是否成功终止。那么,首先为什么要运行它呢?
pipe(pi);
pid1 = fork();
if (pid1==0) { // child1
// make redirections
exec("head"...);
}
pid2 = fork();
if (pid2==0) { // child2
// make redirections
exec("ls"...);
}
// parent process
// close unuseful pipe
waitpid(pid1...);
waitpid(pid2...);
pid1 = fork();
if (pid1==0) { // child
pipe(pi);
pid2 = fork();
if (pid2==0) { // gran child
// make redirections
exec("ls"...);
}
// make redirections
exec("head"...);
}
// parent process
waitpid(pid1...);