我正在嘗試使用管道將1個命令exec'd的stdout鏈接到另一個命令的stdin。例如模仿(cmd1 | cmd2)c在某些情況下導致程序掛起的管道
下面是我的代碼嚴重剝離版本。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argC, char *argv[])
{
//Run first command
int fds[2];
if (pipe (fds) < 0) { //Create pipe
fprintf (stderr, "Pipe Failed\n");
}
int pid;
if ((pid = fork()) == -1) {
fprintf (stderr, "Fork 1 Failed\n");
exit (1);
}
if (pid == 0) { //First child proccess
close (fds[0]); //Close input end of pipe
dup2 (fds[1], STDOUT_FILENO); //Set stdout to output pipe
close (fds[1]); //Close output end of pipe
fprintf (stderr, "Exec 1 executing now\n");
execlp ("./addone", "./addone", NULL); //execute first command - Doesnt cause hang
//execlp("ls", "ls", NULL);//Causes hang
fprintf (stderr, "Exec 1 failed\n");
} else { //First parent segment
int returnStatus;
waitpid (pid, &returnStatus, 0); //Wait for child 1 to finish
fprintf (stderr, "Back to parent 1\n");
}
//Run second command
if ((pid = fork()) == -1) {
fprintf (stderr, "Fork 2 failed\n");
}
if (pid == 0) { //second child proccess
dup2 (fds[0], STDIN_FILENO); //Set stdin to input pipe
close (fds[0]); //Close input end of pipe
close (fds[1]); //Close output end of pipe
fprintf (stderr, "Exec 2 executing now\n");
execlp ("./addone", "./addone", NULL); //execute first command - Doesnt cause hang
//execlp("wc", "wc", NULL);//Causes hang
fprintf (stderr, "Exec 2 failed\n");
} else { //second parent segment
int returnStatus;
waitpid (pid, &returnStatus, 0); //Wait for child 2 to finish
fprintf (stderr, "Back to parent 2\n");
//Done with pipes
close (fds[0]);
close (fds[1]);
}
return 0;
}
在程序中,我嘗試製作一個管道,並將第一個可執行文件標準輸出路由到秒標準輸入。嘗試使用ls |運行程序時作爲我的執行官,我的程序掛在第二任執行官上。但是,當我使用一個簡單的程序「./addone」作爲我的執行程序時,整個執行過程都會正常結束。
其中「addone」是一個小程序:
#include<stdio.h>
int main(){
int value = 0;
scanf("%d", &value);
value++;
printf("%d\n", value);
}
它有人認爲我的問題可能是有被輸入管道保持打開,但我不能工作了,其中會發生,它不沒有解釋爲什麼我的程序在使用我的簡單測試程序時運行得很好。
任何意見,什麼會導致這個掛起將不勝感激。
您需要關閉父進程中的管道末端。因爲'pipe'在'fork'之前被調用,所以它在父進程和子進程中都被打開。這對你的簡單程序來說不是問題,因爲它不會象'wc'那樣循環等待'EOF'。如果管道仍然被任何進程保持打開狀態,「EOF」永遠不會到來。 – kaylum
不要我已經用close(fds [0])來做到這一點;關閉(FDS [1]); 或者我應該將這些移到父級的等待聲明之前嗎? – Killedan9
你確定你沒有去掉你的程序中重要的東西嗎?在你發佈的例子中,我希望它會掛在第一個waitpid,只要被執行的程序向stdout寫入任何東西 - 子節點中的printf將被阻塞,因爲從管道的另一端沒有讀數,而父母會反過來阻止等待孩子。建議:1)立即關閉父母和小孩的未使用的管子末端(即在第一次分岔後關閉父母的fds [1]等等。2)在開始第二個等待之前不要等待第一個孩子,等待兩端而不是 – davlet