在for循环中使用fork()创建子循环以运行execlp()

在for循环中使用fork()创建子循环以运行execlp(),c,linux,for-loop,exec,fork,C,Linux,For Loop,Exec,Fork,我正在编写一个运行Linux命令的C程序,如: $cat/etc/passwd | cut-f1-d:|排序 其思想是使用fork()创建子进程,以使用execlp()运行命令。我计划使用两个管道进行通信,并使用dup()引导输入输出 输出错误: ls-l | wc-c on命令返回1746 程序返回1761 代码(编辑以反映建议): #包括 #包括 #包括 #包括 #包括 int main() { inti,fd1[2],status,listpid[2]; pid_t儿童; 管道(fd1);

我正在编写一个运行Linux命令的C程序,如:

$cat/etc/passwd | cut-f1-d:|排序

其思想是使用fork()创建子进程,以使用execlp()运行命令。我计划使用两个管道进行通信,并使用dup()引导输入输出

输出错误:

ls-l | wc-c on命令返回1746 程序返回1761

代码(编辑以反映建议):

#包括
#包括
#包括
#包括
#包括
int main()
{
inti,fd1[2],status,listpid[2];
pid_t儿童;
管道(fd1);
对于(i=0;i<2;i++)
{
printf(“\n正在创建子项\n”);
if((child=fork())=-1)
{
佩罗尔(“福克”);
退出(退出失败);
}
else if(子项==0)
{
如果(i==0)
{
关闭(1);dup(fd1[1]);
关闭(fd1[0]);
关闭(fd1[1]);
printf(“\n运行ls-l\n”);
fflush(stdout);
execlp(“ls”、“ls”、“-l”、(char*)NULL);
退出(退出成功);
}
else如果(i==1)
{
关闭(0);dup(fd1[0]);
关闭(fd1[1]);
关闭(fd1[0]);
printf(“\n正在运行wc-c\n”);
fflush(stdout);
execlp(“wc”、“wc”、“-c”、(char*)NULL);
退出(退出成功);
}
}
其他的
{
listpid[i]=子对象;
}
}
关闭(fd1[0]);
关闭(fd1[1]);
对于(i=0;i<2;i++)
{
waitpid(listpid[i],&status,0);
如果(妻子退出(状态))
{
printf(“\n[%d]已终止(状态:%d)\n”、listpid[i],WEXITSTATUS(状态));
}
}
退出(退出成功);
}

首先,你不能在循环中等待PID——如果ls的输出足够大,它将填满管道,因此直到有人读到它才会结束:你必须在for循环之后等待两个孩子。
第二,只要管道的另一端打开,wc就会继续运行,即您也必须关闭父进程中的管道。

更新后,两个子进程的行为正常。但是,您仍然需要添加:

close(fd1[0]);
close(fd1[1]);
在启动子项的
for
循环和收集退出状态的
for
循环之间


由于管道的写入端仍处于打开状态,
wc
不会接收EOF,因此不会终止,因此进程将无限期等待。

请参阅使用
NULL
作为最后一个参数。传统做法是将
\n
放在
printf
的末尾,如果它是一个终端,这也避免了必须刷新
stdout
。像这样吗?if((child==0){}else{if(i==0){close(fd1[1]);}else if(i%2!=0){close(fd1[0]);}}@user1863673:通常,如果
dup()
dup2()
pipe()返回的一对描述符
,您需要关闭
管道()返回的两个描述符
。可能存在例外情况;它们非常少。仍然无法解决问题。非常感谢。这解决了挂起的问题。但是输出仍然错误。输出有什么问题吗?您是否记得标准输出是通过管道发送的,因此您的诊断打印被发送到
wc-c
,从而使字符膨胀字符数与在shell中运行
ls-l | wc-c
得到的字符数比较?存在
stderr
是有原因的;这样诊断信息就不会被发送到管道中造成混乱。如果将
printf(
更改为
fprintf(stderr,
全局,则来自程序的计数与shell从
ls-l | wc-c
获得的结果一致。
close(fd1[0]);
close(fd1[1]);