繁体   English   中英

C程序不能使用管道执行“execlp”中的“more”命令来查看程序的输出

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM