一、前言
其實僵屍程序産生的主要原因就是作業系統要保留結束的子程序的狀态,尤其是其傳回值,以供主程序使用。要銷毀僵屍程序,釋放僵屍程序的資源。,我們需要父程序利用函數向作業系統索要該子程序的傳回值,當我們難道子程序的傳回值後,作業系統就會回收該程序的資源。當子程序結束時,它會把傳回值交給作業系統,而作業系統會把該值放到系統的一片記憶體中,我們要擷取該值,要做的就是利用函數讀取該記憶體塊中值。
二、wait函數
利用wait函數我們可以擷取上述子程序的傳回值。wait函數是阻塞函數,其原型如下:
#include <sys/wait.h>
pid_t wait(int *status);
wait函數可以等待任意子程序結束,其傳回值是該子程序的程序ID。其參數是讀取的上述子程序傳回值的位址。因為該位址儲存的資料不僅僅包含子程序的傳回值,還包含子程序是否是正常結束的布爾量,我們可以利用下面的宏擷取需要的資訊:
WIFEXITED(status),表示子程序是否正常結束。
WEXITSTATUS(status),表示子程序的傳回值。
示例代碼:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
int status;
pid_t pid=fork();
if(pid==0)
{
sleep(20);
return 3;
}
else
{
printf("目前子程序ID:%d\n",pid);
wait(&status);
if(WIFEXITED(status))
printf("子程序傳回值:%d\n",WEXITSTATUS(status));
}
return 0;
}
由于wait是阻塞函數,當執行到wait時,子程序正在sleep,而父程序會進行阻塞,直到子程序sleep完傳回3之後才會停止阻塞。
下面是執行結果:
[[email protected] fork]$ gcc wait.c
[[email protected] fork]$ ./a.out
目前子程序ID:9799
子程序傳回值:3
三、waitpid函數
waitpid函數也可以等待指定的程序傳回 并回收僵屍程序資源。但它不同于Wait,它是非阻塞函數,其原型定義如下:
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
pid表示要等待的子程序ID,如果寫-1表示等待任意子程序結束
status和wait的status含義一樣,表示指向子程序傳回值記憶體的指針。
options是常量WNOHANG,表示即使沒有結束的子程序也不會阻塞,而是傳回0并退出函數。
示例代碼:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
int status;
pid_t pid=fork();
if(pid==0)
{
sleep(20);
return 3;
}
else
{
printf("目前子程序ID:%d\n",pid);
while(waitpid(pid,&status,WNOHANG)==0)
{
printf("主程序sleep 4秒\n");
sleep(4);
}
if(WIFEXITED(status))
printf("子程序傳回值:%d\n",WEXITSTATUS(status));
}
return 0;
}
執行結果如下:
[[email protected] fork]$ gcc wait.c
[[email protected] fork]$ ./a.out
目前子程序ID:9893
主程序sleep 4秒
主程序sleep 4秒
主程序sleep 4秒
主程序sleep 4秒
主程序sleep 4秒
子程序傳回值:3
從上述結果中也可以看出可以看到waitpid并沒有阻塞,而是一直在執行while中的語句,直到子程序結束。
Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本項目:
git clone g[email protected]:HymanLiuTS/NetDevelopment.git
擷取本文源代碼:
git checkout NL12