2017-10-14 76 views
-1
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<unistd.h> 
#include<sys/wait.h> 
#define LG_LIGNE 256 
int main(void){ 

char ligne[LG_LIGNE]; 
while(1){//afficher un symbole d'invite(prompt) 
    fprintf(stderr, "-->"); 
    //lire une ligne de commandes 
    if(fgets(ligne,LG_LIGNE,stdin)==NULL) 
    break; 
    //supprimer le retour chariot final 
    ligne[strlen(ligne)-1]='\0'; 
    //lancer un processeur 
    if(fork()==0){ 
    //processus fils 
    //executer la commande 
    execlp(ligne, ligne, NULL); 
    //msg d'erreur si on echoue 
    perror(ligne); 
    exit(EXIT_FAILURE); 
    } 
    else{//process père 
    //attendre la fin de son fils 
    waitpid(-1,NULL,0); 
    //et reprendre la boucle 
    } 
} 
fprintf(stderr,"\n"); 
return EXIT_SUCCESS; 
} 

我明白每個返回值的含義,但我在這裏並不完全理解,從技術上來說,子/父進程中的含義是什麼,並且我看不到waitpid的用法,如果我不知道如何使用waitpid不使用它?所有的fork函數返回值有什麼區別?

+1

你可能會更清楚你在問什麼? –

回答

2

Fork()創建進程的內存和狀態的副本,併產生一個子進程中運行它。孩子和父母都在自己的進程中運行,並擁有自己的地址空間和虛擬內存副本。那麼如何判斷哪一個是父節點,哪個是子節點,因爲這兩個任務在fork()調用後具有相同的狀態和內存後恢復執行?

你可以知道哪些是家長和這是基於從fork()返回代碼孩子。如果返回值爲零,那麼你就是子進程,並且此進程通常會將返回代碼測試爲零,並分支以完成孩子的工作。

同時,父代也從相同的fork()調用中返回,但返回代碼設置爲其子代的進程標識(非零)。父母可以選擇保存此進程ID,但只有父母創建多個孩子並且希望通過他們的進程ID來跟蹤他們,這才真正有用。

父完成之前,通常會等待其子processses先完成。這是waitpid呼叫所做的。您可以傳入子進程的ID,在這種情況下waitpid調用不會返回,直到該子進程完成。將0123傳遞給waitpid會告訴它等到你的一個子任務完成。

waitpid的返回碼包含的子任務完成的進程ID。欲瞭解更多信息,這裏已經回答了這個問題https://stackoverflow.com/a/21249082/6693299

有關您的程序的完整說明,請閱讀H.S.的詳細說明。 ,回答同樣的問題在這裏https://stackoverflow.com/a/46741392/6693299

+0

感謝您的回答。 –

1

你的第一個問題 -

what being in the child/father process technically means

fork()通過複製調用進程創建一個子進程。 調用fork()的過程是父進程,新創建的進程是子進程。 所以fork()分爲二的過程,並返回0給子進程和子進程的PID給父進程,或-1,如果叉失敗。

的子進程,並在單獨的內存空間運行父進程。在fork()時,兩個內存空間都具有相同的內容。

有被稱爲概念上寫複製,其良好IT-有知識

寫入時複製是在頁表設置,使得父子進程開始優化共享所有相同的內存,並且只有在任何進程寫入的頁面都會在需要時被複制。

如果進程不修改任何內存並立即執行新進程,請完全替換地址空間。因此,在分支期間拷貝所有進程的內存是浪費的,而採用寫入時複製技術。

例如,在你的程序你立即調用execlpfork

if(fork()==0){ 
//processus fils 
//executer la commande 
execlp(ligne, ligne, NULL); 

你的第二個問題 -

I couldn't see the use of waitpid, what will happen if I didn't use it?

爲了解釋這一點,我已經修改了你的程序和添加聲明,以印刷父母和子女的過程pid's並將此聲明評論爲 -

節目
waitpid(-1,NULL,0); 

輸出是 -

parent process pid : 22325 -->ls child process pid : 22326 < here the output of ls command >

現在,如果我們看到ps命令與grep'ed父進程ID輸出 -

# ps -eaf | grep 22325 
root  22325 21555 0 10:39 pts/4 00:00:00 ./a.out 
root  22326 22325 0 10:39 pts/4 00:00:00 [ls] <defunct> 
root  22339 21644 0 10:39 pts/5 00:00:00 grep 22325 

這裏,在輸出第一列是UID,第二列是PID,第三列是PPID(父pid)。 您可以看到子進程(pid - 22326)被標記爲<不存在>

被禁處理(也被稱爲「殭屍」過程)是已完成執行的過程中,將有一個退出狀態報告給它的父進程。由於最後一點信息,進程將作爲殭屍進程保留在操作系統的進程表中,表明它不會被計劃用於進一步執行,但它不能被完全移除(並且其進程ID不能被重複使用),直到確定退出狀態不再需要。

這裏來使用waitpid() -

wait()waitpid()功能應獲得與主叫方的其中一個子進程狀態信息。

waitpid()暫停調用過程,直到系統獲得有關該孩子的狀態信息。如果調用waitpid()時系統已經有適當的孩子的狀態信息,則立即返回waitpid()。如果調用進程收到其操作是執行信號處理程序或結束進程的信號,則waitpid()也會結束。

有關waitpid()的其他詳細信息,如語法(狀態,選項)和返回值,您可以檢查其man頁面。

如果我取消在程序中waitpid()編譯並運行它,輸出 -

parent process id : 23069 
-->ls 
child process id : 23070 
<here the output of ls command> 

現在,如果我們看到ps命令與grep'ed父進程ID輸出 -

# ps -eaf | grep 23069 
root  23069 21555 0 10:51 pts/4 00:00:00 ./a.out 
root  23108 21644 0 10:51 pts/5 00:00:00 grep 23069 

沒有殭屍程序。運行ls命令的子進程已完成,父進程讀取其退出狀態。

希望這個答案你的兩個問題。

+0

感謝您的詳細解答。 –

相關問題