[英]C program cannot use pipe to execute the "more" command in "execlp" in order to view program's output
提前感谢您的帮助。
我正在尝试复制 shell 命令ls -1 /usr/include | more
的行为。 ls -1 /usr/include | more
使用 C 程序。 我写了这段代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
int page[2]; // page is the name of my pipe
pipe(page);
switch (fork()){
case -1:
exit(1);
break;
case 0:;
close(page[1]);
dup2(page[0], 0);
close(page[0]);
execlp("more", "more", NULL);
default:
close(page[0]);
dup2(page[1], 1);
close(page[1]);
execlp("ls", "ls", "-1", "/usr/include", NULL);
break;
}
}
但它只打印一页( more
会做)并导致一些奇怪的行为阻止我的终端(迫使我使用reset
将其设置回正常)。
我刚刚意识到父进程和子进程的角色被混淆了。 运行more
命令的应该是父级。 由于more
是一个交互式命令,终端将作为父级更好地响应它(我猜)。
所以为了解决我的问题,我交换了父母和孩子的角色。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
int page[2]; // page is the name of my pipe
pipe(page);
switch (fork()){
case -1:
exit(1);
break;
case 0:;
close(page[0]);
dup2(page[1], 1);
close(page[1]);
execlp("ls", "ls", "-1", "/usr/include", NULL);
break;
default:
close(page[1]);
dup2(page[0], 0);
close(page[0]);
execlp("more", "more", NULL);
}
}
为什么这可以解决问题? (我仍然不明白为什么它有效!)
您的原始代码在父进程和子进程以及启动程序的 shell 之间创建了一种竞争条件。 ls
进程在more
可以从管道中读取所有数据之前结束,并且由于在您的程序中父进程被ls
进程替换,当ls
进程结束时(将其所有输出写入管道缓冲区后),它退出,并且这样做会关闭管道并将控制权交还给外壳程序,外壳程序将立即准备好读取另一个命令。
所以,最初都more
与外壳可从同一TTY设备读取(它是从它的阅读STDERR
描述符,还是连接到您的TTY),然后一旦more
,最终得到了一些输入,它会尝试从管道再次读取(其STDIN
),它将获得文件结尾(管道已在写入端关闭,因为ls
退出),因此more
现在也将退出(不再打印任何输出)。 more
进程和 shell 之间也可能存在竞争,关于哪个(重新)设置 TTY 驱动程序模式以及何时。
程序的另一种实现是让原始父进程启动两个子进程,一个用于more
,一个用于ls
,然后等待两个进程终止,但这当然需要更多的系统资源。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.