1. 程式人生 > >linux系統程式設計-回收程序

linux系統程式設計-回收程序

孤兒程序和殭屍程序的概念

  • 孤兒程序:父程序先於子程序結束,則子程序成為孤兒程序,此時init程序變成子程序的父程序,稱為init程序領養孤兒程序。 在這裡插入圖片描述

  • 殭屍程序:程序終止,父程序尚未回收,子程序殘留資源(PCB)存放於核心中,變成殭屍(Zombie)程序 NOTE:殭屍程序不能使用kill命令清除,因為kill命令只是用來終止程序的,而殭屍程序已經終止。當父程序也死了,殭屍程序交給init程序解決了。 在這裡插入圖片描述

wait函式

  • pid_t wait(int *status); 成功:清理掉的子程序ID;失敗:-1 (無子程序) 一次呼叫只回收一個子程序,回收多個子程序:while(wait(NULL));
  • 當程序終止時,作業系統的隱式回收機制會: (1) 關閉所有檔案描述符 (2) 釋放使用者空間分配的記憶體 (3) 核心中PCB仍存在,其中儲存該程序的退出狀態。(正常終止→退出值;異常終止→終止訊號)
  • 父程序呼叫wait函式可以回收子程序終止資訊。該函式有三個功能: ① 阻塞等待子程序退出 ② 回收子程序殘留資源 ③ 獲取子程序結束狀態(退出原因)。
  • 可使用wait函式傳出引數status來儲存程序的退出狀態。藉助巨集函式來進一步判斷程序終止的具體原因。巨集函式可分為如下三組: (1)WIFEXITED(status) 為非0 → 程序正常結束    WEXITSTATUS(status) 如上巨集為真,使用此巨集 → 獲取程序退出狀態 (exit的引數)
           child_pid = wait(&status);
           if(wpid>0)//子程序的PID應該 >0
           {
                 if(WIFEXITED(status))
                 {
                      printf("exit value is %d \n",WEXITSTATUS(status)); //子程序退出時的值x:exit(x) or return(x)
                 }
           }

(2)WIFSIGNALED(status) 為非0 → 程序異常終止    WTERMSIG(status) 如上巨集為真,使用此巨集 → 取得使程序終止的那個訊號的編號。

         wpid = wait(&status);
         if(wpid>0)
         {
                   if(WIFSIGNALED(status))
                   printf("signal value is %d \n",WTERMSIG(status));
         }

         如果子程序執行了 100/0的算術運算,父程序輸出8,用kill -l 命令檢視,則異常訊號編號為8是SIGFPE,

(*3)WIFSTOPPED(status) 為非0 → 程序處於暫停狀態( 拓展 )     WSTOPSIG(status) 如上巨集為真,使用此巨集 → 取得使程序暫停的那個訊號的編號。    WIFCONTINUED(status) 為真 → 程序暫停後已經繼續執行

waitpid函式

  • 作用同wait,但可指定pid程序清理,可以不阻塞
  • pid_t waitpid(pid_t pid, int *status, in options); 成功:返回清理掉的子程序ID;失敗:-1( 無子程序) 引數 pid:> 0 回收指定ID的子程序       -1 回收任意子程序(相當於wait)       0 回收和當前呼叫waitpid一個組的所有子程序      < -1 回收指定程序組內的任意子程序 引數options:為WNOHANG,且子程序正在執行。返回0          :為0 ,且子程序正在執行。一直阻塞等待
例子1:父程序迴圈建立5個程序,只回收第3個程序
#include <stdio.h>
#include <stdlib.h>
 #include <unistd.h>
  
 int main(void)
{
         pid_t pid;
         int i=0,wpid;
        printf("------------------------\n");

       for(i=0;i<5;i++)
         {
         pid=fork();
                 if(pid<0)
                {
                         perror("fork error");
                 }
                 else if(pid == 0)
                {
                        break;
                 }
 
                 else
                 {
                         if(i==3)
                         wpid=pid;
                }
         }
         sleep(i);
         if(i<5)
         {
                 printf("i am %dth child,my pid is %d\n",i,getpid());
         }
         if(i==5)
         {
                 waitpid(wpid,NULL,0);
                 printf("i am father ,my pid is %d\n",getpid());
                 while(1);   //父程序停在這,
         }
 
         return 0;
 }

左邊:執行結果                        右邊:ps-aux 命令檢視的程序 在這裡插入圖片描述 例子2:父程序回收全部程序


         if(i==5)
         {
                 while(waitpid(-1,NULL,0)>0); //迴圈回收,當沒有子程序回收,返回-1,跳出
                 printf("i am father ,my pid is %d\n",getpid());
                 while(1);   //父程序停在這,
         } 

結果:只剩下父程序,子程序全部回收了,沒有殭屍程序了 在這裡插入圖片描述