2015-10-14 76 views
2
//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,另一个用于排序。 这些proccess独立运行,我试图重定向ls -l的输出 ,作为通过管道排序的输入。这个概念是主程序 应该等待它们两个终止。然而,等待似乎对ls -l正常工作 ,但它挂起 - 从不终止排序。所以整个程序 挂起。如果我从程序中删除两个等待代码行,ls - l - > sort 管道完美工作,当然主要在它们之前终止。 我怀疑这是由于排序不断等待输入,即使在ls -l终止之后也是如此, 。我不明白父母如何终止 影响两个子进程的终止。 是否有人请向我解释发生了什么事情? 非常感谢。 PS。为了清晰和少代码,我忽略了大多数错误检查。Linux Fork进程终止

回答

5

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

地址:

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

来电来runLS()runSORT()后,事情正常工作。

理想情况下,儿童在复制后应关闭管道的两端。如果将管道文件描述符复制到标准文件流中,则应几乎总是关闭两个两端的管道。在这段代码中,你不用做就可以逃脱;这并不总是如此。

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

+0

感谢您的支持,事实上您的方法可行。 你能否解释一点你的答案部分[理想情况是这样]?我怎么能在上面的代码中关闭管道的末端? 至于变量,无论如何,我确实几乎从来没有全局变量,它只是为了清晰。 –

+0

调用'dup2(* pipeOUT,STDOUT_FILENO);'后,您有两个文件描述符在管道的写入端在'ls'子目录中打开;一个是'* pipeOUT'中的值,另一个是'STDOUT_FILENO'。你真的不会再使用'* pipeOUT'描述符,所以你现在应该关闭它。类似于'sort'孩子中的'dup2()'。你也可以争辩说,父母不打算使用管道的任何一端,所以它也应该关闭这些文件描述符。令人惊讶的是,确保你有足够的关闭电话是获得基于管道的程序工作的诀窍。 –

+0

至于如何关闭它:在子节点中关闭(* pipeOUT)'和关闭(* pipeIN)'。实际上,为了对称,你需要做'dup2()',然后两个孩子关闭。 'dup2()'调用稍有不同,但关闭是相同的。 –