【问题标题】:Program still wants to take input even if the all pipes are closed即使所有管道都关闭,程序仍然希望接受输入
【发布时间】:2016-03-25 03:20:51
【问题描述】:

我正在尝试实现这种情况:

fork and pipe scenario

两个并行进程通过管道连接到tr /a-z/ /A-Z/,最后tr /a-z/ /A-Z/ 进程连接到标准输出。

我编写了这个程序来尝试实现我的目标:

#include<stdio.h>
#include<unistd.h>
#include<wait.h>

int main()
{
    int dummy;
    int fd[2];
    int i;
    char* lsargs[]  = {"/bin/ls", "-l", NULL};
    char* lsargs2[] = {"cat", "/etc/group", NULL};
    char* lsargs3[] = {"tr", "/a-z/", "/A-Z/", NULL};
    char** am[] = {lsargs, lsargs2, lsargs3};

    pipe(fd);

    for ( i = 0 ; i < 3 ; i++ )
    {
        pid_t pid = fork();

        if ( pid == 0 )
        {
            if ( i != 2 ) // ls -l & cat
            {
                // 0 -> stdin, 1 -> pipe write end
                close(fd[0]);
                dup2(fd[1], 1);
                close(fd[1]);
                execvp(am[i][0], am[i]);
            }
            else //TR AZ AZ
            {
                // 0 -> pipe read end 1 -> stdout
                close(fd[1]);
                dup2(fd[0],0);
                close(fd[0]);
                execvp(am[i][0], am[i]);
            }
            break;
        }
        else{
            wait(&dummy);
        }
    }

    return 0;
}

我得到了正确的输出,但我的程序没有终止,它仍然想要输入。你能帮我理解原因吗?

【问题讨论】:

  • 你在 fork 第一个进程后等待。你的循环太聪明了,我建议你展开循环
  • @AnttiHaapala 你有什么建议?我知道使用循环是没有意义的,我将它用于特殊目的。
  • 不要使用for 编写代码以使其重复;然后您可以识别可以重复的部分以及原因。现在你的父母将wait 让第一个孩子退出之前下一个孩子甚至被分叉,执行也没有让它的管道运行。

标签: c linux pipe fork system-calls


【解决方案1】:

顶级进程没有关闭管道。由于父进程实际上只是一个协调器并且实际上并不使用管道,因此一旦完成最后一次fork 调用,它就需要关闭两端。一种方法是将关闭代码添加到else 案例中。例如:

else {

    /* ADDED CODE - close the pipes after last fork */
    if (i == 2) {
        close(fd[0]);
        close(fd[1]);
    }

    wait(&dummy);
}

【讨论】:

  • 代码以我想要的方式工作,但 Antti Haapala 在主帖中的评论让我想知道:我是否适当地使用 wait(&dummy)?如果没有,我该如何正确使用它。
  • @ArdaGüney 这取决于你想要的行为是什么。如果您希望ls 和cat 输出一个接一个地排序,那么您当前的等待行为是正确的。如果您至少在第一个fork 之后不等待,那么ls 和cat 输出可能会交错出现,因为它们都将尝试同时写入pipe,因此不确定是什么输出排序将是。
  • 我不知道如何不让僵尸落后,同时让 ls 和 cat 同时运行。向 wait(&dummy) 添加 if (i != 0) 语句不起作用。
  • 要做到这一点,只需从当前的for 循环中取出wait 调用,然后在仅调用wait 3 次的现有循环之后添加另一个for 循环。
  • 当您这样做时,无法保证订购。所以你不能确定它是有序的还是交错的。它取决于时间。例如,假设您有一个包含许多文件的目录。如果ls 进程首先被调度,那么它可能会在cat 进程执行之前再次暂停。在这种情况下,输出将被交错。
猜你喜欢
  • 1970-01-01
  • 2021-01-25
  • 1970-01-01
  • 2015-09-28
  • 2018-12-13
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多