天天看點

作業系統 - 程式不會按照特定的順序回收子程序

eg1:

// waitpid1.c
// 2015-08-26    Lucifer Zhang
// Using the waitpid function to reap zombie children in no
// particular order.
#include "csapp.h"
#define N 2

int main() 
{
    int status, i;
    pid_t pid;

    /* Parent creates N children */
    for (i = 0; i < N; i++)                       //line:ecf:waitpid1:for
	if ((pid = Fork()) == 0)  /* child */     //line:ecf:waitpid1:fork
	    exit(100+i);                          //line:ecf:waitpid1:exit

    /* Parent reaps N children in no particular order */
    while ((pid = waitpid(-1, &status, 0)) > 0) { //line:ecf:waitpid1:waitpid
	if (WIFEXITED(status))                    //line:ecf:waitpid1:wifexited
	    printf("child %d terminated normally with exit status=%d\n",
		   pid, WEXITSTATUS(status));     //line:ecf:waitpid1:wexitstatus
	else
	    printf("child %d terminated abnormally\n", pid);
    }

    /* The only normal termination is if there are no more children */
    if (errno != ECHILD)                          //line:ecf:waitpid1:errno
	unix_error("waitpid error");

    exit(0);
}
           

        第15行,父程序建立N個子程序,在第16行,每個子程序以一個唯一的退出狀态退出。在第19行,父程序用waitpid作為while循環的測試條件,等待它所有的子程序終止,因為第一個參數是-1,是以對waitpid的調用會阻塞,知道任意一個子程序終止。在每個子程序終止時,對waitpid的調用會傳回,傳回值為該子程序的非零PID。第20行檢查子程序的退出狀态。如果子程序是正常終止的,在此是以調用exit函數終止的,那麼父程序就提取出退出狀态,把它輸出到stdout上。

        當回收了所有的子程序之後,再調用waitpid就傳回-1,并且設定errno為ECHILD。第28行檢查waitpid函數是正常終止的,否則就輸出一個錯誤消息。

        測試:

作業系統 - 程式不會按照特定的順序回收子程式

        注意,程式不會按照特定的順序回收子程序。子程序回收的順序是這台特定的計算機的屬性。在另一個系統上,甚至在同一個系統上再次執行一次,兩個子程序都可能以相反的順序被回收。上面的測試結果也說明了這一點。這是非确定性的(nondeterministic)行為的一個示例,這種非确定性行為使得對并發進行推理非常困難。

    下面這個例子做了簡單的改變,消除了不确定性,按照父程序建立子程序的相同順序來回收這些子程序。

eg2:

// waitpid1.c
// 2015-08-26    Lucifer Zhang
// Using waitpid to reap zombie children in the order they were created.

#include "csapp.h"
#define N 2

int main() 
{
    int status, i;
    pid_t pid;

    /* Parent creates N children */
    for (i = 0; i < N; i++)                       //line:ecf:waitpid1:for
	if ((pid = Fork()) == 0)  /* child */     //line:ecf:waitpid1:fork
	    exit(100+i);                          //line:ecf:waitpid1:exit

    /* Parent reaps N children in no particular order */
    while ((pid = waitpid(-1, &status, 0)) > 0) { //line:ecf:waitpid1:waitpid
	if (WIFEXITED(status))                    //line:ecf:waitpid1:wifexited
	    printf("child %d terminated normally with exit status=%d\n",
		   pid, WEXITSTATUS(status));     //line:ecf:waitpid1:wexitstatus
	else
	    printf("child %d terminated abnormally\n", pid);
    }

    /* The only normal termination is if there are no more children */
    if (errno != ECHILD)                          //line:ecf:waitpid1:errno
	unix_error("waitpid error");

    exit(0);
}
           

繼續閱讀