天天看點

Linux下回收子程序wait函數和waitpid函數的基本使用

1. 孤兒程序:父程序先于子程序結束,則子程序成為孤兒程序,子程序的父程序變為init程序 。

2. 僵屍程序:子程序終止了,父程序尚未回收子程序,子程序殘留資源(PCB)存放于核心中,子程序變成僵屍(Zombie)程序。 

問:那為什麼子程序要把PCB殘留在核心裡呢? 

答:因為子程序終止後,它會把終止信号等退出狀态(不管正常終止還是異常終止都對應一個信号)儲存在核心的PCB裡面,隻有這個子程序的父親節調用wait或者waitpid擷取這些退出狀态,然後才會徹底清除掉這個子程序。如果父程序不調用wait或者waitpid,那麼這個子程序就會成為僵屍程序。

問:什麼方法可以清除掉一個僵屍程序。(附:kill指令清除不了僵屍程序的,因為kill指令隻是用來終止程序的,而僵屍程序已經是終止的了) 

答:kill确實是直接清除不掉僵屍程序,但是我們可以kill掉僵屍程序的父程序,這樣僵屍程序的父程序就變為init程序,init程序自然會調用wait或者waitpid清除這個僵屍程序。 

3. wait函數

pid_t wait(int *status); //status傳出參數,存放子程序的退出狀态資訊

附:父程序一旦調用該函數,就會阻塞等待,直到子程序退出

傳回值:成功傳回子程序id,失敗傳回-1(無子程序) 。

status傳出參數儲存着子程序的退出狀态,下面對其說明如下:

if (WIFEXITED(status)) {  //IFEXITED非0,程序正常退出
                          printf("exited, status=%d\n", WEXITSTATUS(status));
                    } else if (WIFSIGNALED(status)) { //IFSIGNALED非0,程序被某個信号異常終止
                          printf("killed by signal %d\n", WTERMSIG(status));
                    } else if (WIFSTOPPED(status)) {    //IFSTOPPED非0,程序收到某個信号而暫停
                          printf("stopped by signal %d\n", WSTOPSIG(status));
                    } else if (WIFCONTINUED(status)) {  //IFCONTINUED非0,程序從暫停狀态變為繼續運作狀态
                          printf("continued\n");
                    }      

4. waitpid函數 

pid_t waitpid(pid_t pid, int *status, int options); 

功能:和wait一樣,但是這個函數清除指定的pid,可以不阻塞父程序

傳回值:成功傳回清除掉的程序pid,失敗傳回-1 (無子程序) 。當options指定為WNOHANG時,傳回0表示子程序正在運作。

下面對pid的不同取值情況的說明:

>0  表示回收指定ID的子程序

-1   表示回收任意子程序(相當于wait)

0    表示回收和目前調用waitpid一個組的所有子程序

<-1 表示回收指定程序組内的任意子程序,比如-6610表示回收程序組id為6610的任意子程序

附:一次wait或waitpid調用隻能清理掉一個子程序,清理多個子程序應該使用循環調用多次 。