2016-11-23 79 views
0

我正在嘗試從父進程的子進程exec()。在這個子進程中,我要求用戶輸入一條消息,以便它可以通過父進程打印出來,但我找不到方法來執行它...如何將標準輸入從孩子管到父母?

到目前爲止,我的代碼是:

parent.c

int main(int argc, char **argv) { 
    int fd[2]; 
    char line[80]; 

    pipe(fd); 

    pid_t pid = (pid_t)fork(); 

    if(pid > 0) { 
     waitpid(pid, NULL, 0); 
     close(fd[0]); 
     int size = read(fd[1], line, 79); 
     close(fd[1]); 
     line[size] = '\0'; 
     printf("[parent] Received \"%s\", size = %d\n", line, size); 
    } 
    else { 
     close(fd[1]); 
     close(stdin); 
     dup2(fd[0], stdin); 
     close(fd[0]); 
     exec("./child", 0, NULL); 
    } 

    return 0; 
} 

child.c

int main(int argc, char **argv) { 
    char line[80]; 

    printf("[child] Enter message: "); 
    gets(line, 80); 
    printf("[child] line = %s\n", line); 

    return 0; 
} 

當我啓動父進程,它會顯示[child] Enter message:,但是當我嘗試輸入內容時,即使按下回車鍵也不會顯示任何內容。

你知道我該如何使它工作?

謝謝你的幫助。

+2

在家長中,不要等到孩子讀完管道之前完成。它可能在這種情況下工作,因爲你可能沒有足夠的寫入來填充管道緩衝區,但是如果它被填充,那麼作者將會阻塞,並且你有一個死鎖。 –

+1

另外,你有什麼版本的'gets'函數需要緩衝區大小?你在使用'gets_s'的一些變體嗎? –

+0

您的父母計劃還存在其他一些問題。例如,它不應該乾淨地編譯。 –

回答

0

我找到了解決方法。我的實際目標是在父母和孩子之間傳遞信息。我的錯誤是在上stdin。通過這樣做,當程序提出問題時,我無法輸入任何內容。所以我傳遞了argv中的文件描述符的值,我的問題就解決了。

再次感謝您的幫助!

1

除了我評論中提到的問題,您遇到的問題是死鎖。你明白了,因爲父進程等待子進程退出。但是子進程正在等待從未到達的輸入。

這是因爲在子進程中你說輸入應該來自管道

此外,在父進程中,您嘗試從管道的寫入端讀取讀取

最後,只要子進程正在讀取用戶輸入,您的程序將永遠不會工作,因爲所有用戶輸入都將轉到父進程進程。

爲了使其工作,您需要重新考慮您的設計,並使處理從用戶讀取輸入,並寫入管道。並且子進程應該從管道讀取並打印到(非管道式)標準輸出。或者關閉父級中的(正常的,非管道式)標準輸入以及寫入管道的子級(作爲標準輸出)。

+0

謝謝你的回答。不幸的是,我不能重新考慮設計,因爲我被要求按照我的解釋去做。但也許我的做法不好,我不得不重新考慮這一點。我會及時通知你的! – Dayrona

0

你的代碼中有幾個問題:

  • 你混的整數(低電平)文件描述符,和(高電平)FILE *常量。
  • 您倒置stdin和stdout以及通過pipe
  • 你寫在stdout的消息所獲得的描述符的順序時,打算重定向它(應該使用標準錯誤)

這裏是一個固定的版本(我改變了你得到的與fgets,以及與EXECL你EXEC擁有一切編譯):

parent.c:

int main(int argc, char **argv) { 
    int fd[2]; 
    char line[80]; 

    pipe(fd); 

    pid_t pid = (pid_t)fork(); 

    if(pid > 0) { 
     waitpid(pid, NULL, 0); 
     close(fd[1]); 
     int size = read(fd[0], line, 79); 
     close(fd[0]); 
     line[size] = '\0'; 
     printf("[parent] Received \"%s\", size = %d\n", line, size); 
    } 
    else { 
     close(fd[0]); 
     close(1); 
     dup2(fd[1], 1); 
     close(fd[1]); 
     execl("./child", NULL); 
    } 

    return 0; 
} 

孩子。c

int main(int argc, char **argv) { 
    char line[80]; 

    fprintf(stderr, "[child] Enter message: "); 
    fgets(line, 80, stdin); 
    printf("[child] line = %s\n", line); 

    return 0; 
}