2014-01-29 62 views
0

我已經將此與以前的涉及管道的帖子進行了比較,我似乎無法找到問題。家長的一切似乎都應該關閉。當我輸入一個有效的命令(例如「ls | grep a」)時它工作正常,但如果它不是一個有效的命令(例如「ls | grup a)」,程序將停止響應用戶輸入(它會一直運行,但它不會執行)採取任何動作,當你輸入一個命令)基本shell程序的管道問題

主要功能:

int main() { 
int i; 
char **args; 

int pipeCheck = 0; 
int argCount = -1; 
int blank = 0; 

while(1) { 
    args = getln(); 

    if (args[0] != NULL){ 
     blank = 1; 
     if (strcmp(args[0],"exit")==0) exit(0); 
    } 
    for(i = 0; args[i] != NULL; i++) { 
    if (strcmp(args[i], "|")==0){ 
      pipeCheck = i; 
     } 
    } 
    if (pipeCheck != 0){ 
      args[pipeCheck] = NULL; 
      directPipe(args, pipeCheck, argCount, ampCheck); 
     } 
} 

} 這是我的程序管道的功能:

int directPipe(char ** args, int fileNumber, int argCount,int ampCheck){ 
    int fd[2]; 
    int child1,child2; 
    int status; 
    int i; 
    char * piped[10000]; 
    int count = 0; 

    for (i = (fileNumber+1); args[i] != NULL; i++){ 
     piped[count] = args[i]; 
     count++; 
    } 
    piped[count] = NULL; 

    printf("\nPipe attempted...\n"); 

    pipe(fd); 

    child1 = fork(); 
    if (child1==0){ 
     close(1); 
     dup(fd[1]); 
     close(fd[0]); 
     close(fd[1]); 

     execvp(args[0], args); 
     printf("Unknown command, please try again."); 
     exit(0); 
    } 

    child2 = fork(); 

    if (child2 ==0){ 

     close(0); 
     close(fd[1]); 
     dup(fd[0]); 
     close(fd[0]); 

     execvp(piped[0], piped); 
     printf("Unknown command, please try again."); 
     exit(0); 
    } 

    close(fd[1]); 
    close(fd[0]); 

    if (ampCheck == 0){ 
     while (wait(&status) != child1); 
     while (wait(&status) != child2); 
    } 
    else{ 
     printf("\nampCheck = %d",ampCheck); 
     sigset(child2, printer()); 
    } 

    return (0); 
} 
+0

「控制權不會回傳給父母」---請告訴您觀察到的情況。 –

+0

不清楚。什麼是函數參數。需要最少的main()來編譯完整的程序和指令來重現問題。 – grebneke

+0

增加了一個主要的和固定的解釋 –

回答

0

你的問題是對wait()環:

while (wait(&status) != child1); 
while (wait(&status) != child2); 

在你的場景中,第二個孩子在第一個孩子之前死亡,所以你在第一個環路中收集它的屍體,但是忽略它。然後第二個循環進入忙碌的等待狀態,因爲沒有孩子了。

至少,你需要做的:

int corpse; 

while ((corpse = wait(&status)) != -1 && corpse != child1 && corpse != child2) 
    ; 
while ((corpse = wait(&status)) != -1 && corpse != child1 && corpse != child2) 
    ; 

這種處理子女以任何順序死亡 - 但只有兩個孩子。對於更通用的管道(三個或更多進程),您必須更加努力 - 並使用單個循環。更一般的形式將是這樣的:

int corpse; 

while ((corpse = wait(&status)) != -1) 
{ 
    if (record_death_of_child(corpse, status) == -1) 
     break; 
} 

在您的進程創建的代碼記錄了創建進程的PID,以及record_death_of_child()代碼涉及PIDS並返回-1的該名單時,有沒有孩子更多等待當前管道(否則爲0)。或者你可以讓它使用其他啓發式來確定何時退出循環。請注意,如果您在後臺長時間運行作業,它們中的任何一個都可能死亡,並且會在循環中收集屍體。 「記錄死亡」功能也需要處理這樣的過程 - 例如,他們不能再進入前臺,並且您需要報告他們退出等。

您可能最終會使用waitpid(),同樣,因爲您可以安排在掛起時使用WNOHANG仍在運行的後臺進程不掛起。