【问题标题】:Linux Fork Process terminationLinux Fork 进程终止
【发布时间】:2016-01-12 00:26:30
【问题描述】:
//Executing shell command ls -l | sort
int *pipeIN, *pipeOUT;

int runLS(){
    char* parmListLS[] = { "ls", "-l", NULL };
    int pid = fork();
    if(pid==0){
        close(*pipeIN);
        dup2(*pipeOUT, STDOUT_FILENO);
        execvp(parmListLS[0], parmListLS);
    }else return pid;
}

int runSORT(){
    char* parmListSORT[] = { "sort", NULL };
    int pid = fork();
    if(pid==0){
        close(*pipeOUT);
        dup2(*pipeIN, STDIN_FILENO);
        execvp(parmListSORT[0], parmListSORT);
    }else return pid;
}

int main(void){
    int pidLS, pidSort, pipeId[2];
    pipeIN = &pipeId[0], pipeOUT = &pipeId[1];
    pipe(pipeId); //open pipes

    pidLS = runLS();
    pidSort = runSORT();

    printf("PIDS: LS -> %d, Sort -> %d\n", pidLS, pidSort);
    printf("Terminated: %d\n", wait(NULL)); //return pid of 1st exited proc
    printf("Terminated: %d\n", wait(NULL)); //return pid of 2nd exited proc
    printf("Terminated Main Proccess!\n");
}

你好!我无法让一些简单的管道在 linux 上工作。 我正在尝试模拟 shell 命令 ls - l |种类。 如您所见,我正在初始化两个子进程, 一个用于 ls -l,另一个用于排序。 这些进程独立运行,我正在尝试重定向输出 ls - l,作为通过管道排序的输入。这个概念是主程序 应该等待他们两个都终止。但是,等待似乎有效 ls -l 很好,但它挂起 - 永远不会终止排序。所以整个程序 挂起。如果我从程序中删除两个等待代码行,则 ls - l -> sort pipe 工作得很好,当然 main 在它们之前终止。 我怀疑这是因为 sort 一直在等待输入, 即使在 ls -l 终止之后。我不明白如何终止 父进程影响两个子进程的终止。 有人可以向我解释实际发生的事情吗? 非常感谢。附言。为了清晰和减少代码,我忽略了大多数错误检查。

【问题讨论】:

    标签: c linux shell pipe fork


    【解决方案1】:

    sort 无法终止,因为父进程仍然打开了管道的写入端(和读取端),所以 sort 还没有达到管道上的 EOF,所以它还没有得到了所有的数据,所以它不能写任何输出。

    添加:

    close(pipeId[0]);
    close(pipeID[1]);
    

    在调用runLS()runSORT() 之后,一切正常。

    理想情况下,孩子们应该在复制后关闭管道的两端。如果您将管道文件描述符复制到标准文件流,您应该几乎总是关闭管道的 both 端。在这段代码中,您无需执行即可逃脱;情况并非总是如此。

    就个人而言,我认为这两个全局变量没有多大帮助。例如,标记为pipeIn 的管道是sort 的输入,但也是ls 的输出。

    【讨论】:

    • 感谢您的支持,您的方法确实有效。您能否多解释一下您的部分答案[理想情况下......是这种情况]?我怎么可能在上面的代码中关闭管道的末端?至于变量,实际上我几乎从来没有全局变量,只是为了清楚起见。
    • 在调用dup2(*pipeOUT, STDOUT_FILENO); 之后,您在ls 子节点中为管道的写入端打开了两个文件描述符;一个是*pipeOUT 中的值,另一个是STDOUT_FILENO。您真的不会再次使用*pipeOUT 描述符,因此您现在应该关闭它。与 sort 孩子中的 dup2() 类似。而且您还可以争辩说父级不会使用管道的任何一端,因此它也应该基于这些理由关闭这些文件描述符。令人惊讶的是,确保您有足够的近距离通话通常是让基于管道的程序正常工作的诀窍。
    • 关于如何关闭它:close(*pipeOUT)close(*pipeIN) 在儿童中。事实上,为了对称,你会做dup2(),然后在每个孩子中关闭两个。 dup2() 调用略有不同,但关闭相同。
    • 根据您的回答进行了更多研究后,我想我现在完全理解文件描述符、dup 和管道是如何工作的。所以非常感谢你,祝你有美好的一天:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2012-02-24
    • 2014-08-13
    • 2016-09-16
    相关资源
    最近更新 更多