天天看點

wait()函數

wait()函數:回收僵屍程序

父程序調用wait函數可以回收子程序終止資訊。該函數有三個功能:

1) 阻塞等待子程序退出

2) 回收子程序殘留資源

3) 擷取子程序結束狀态(退出原因)

/***
zoom_test.c
***/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void)
{
    pid_t pid, wpid;
    pid = fork();
    int status;
    
    if (pid == 0) {
            printf("---child, my parent= %d, going to sleep 10s\n", getppid());
            sleep(20);
            printf("-------------child die--------------\n");
            exit(77);
    } else if (pid > 0) {
        while (1) {
            printf("I am parent, pid = %d, myson = %d\n", getpid(), pid);

            wpid = wait(&status);
            if (wpid == -1) {
                perror("wait error");
                exit(1);
            }

            if (WIFEXITED(status)) {  //為真說明子程序正常結束
                printf("child exit with %d\n", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)) { //為真說明子程序被信号終止(異常)
                printf("child is killed by %d\n", WTERMSIG(status));
            }

            sleep(1);
        }
    } else {
        perror("fork");
        return 1;
    }

    return 0;
}      

pid_t wit(int *status); 成功:清理掉的子程序ID;失敗:-1(沒有子程序)

當程序終止時,作業系統的隐式回收進制會:

  1. 關閉所有的檔案描述符;
  2. 釋放使用者空間的記憶體;

核心的PCB仍存在。其中儲存該程序的退出狀态。(正常終止—>推出值;異常退出—>終止信号)

可使用wait函數傳出參數status來儲存程序的退出狀态。借助宏函數來進一步判斷程序終止的具體原因。宏函數可以分為以下三組:

  1. WIFEXITED(status) 為非0 à 程序正常結束

    WEXITSTATUS(status)如上宏為真,使用此宏à擷取程序的退出狀态(exit參數)

  2. WIFSIGNALED(status)為非0 à 程序異常終止

    WTERMSIG(status)如上宏為真,使用此宏 à 取得使程序終止的那個信号的編号

/***
wait1.c
***/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    pid_t pid, wpid;

    pid = fork();

    if(pid == -1){
        perror("fork error");
        exit(1);
    } else if(pid == 0){        //son
        printf("I'm process child, pid = %d\n", getpid());
        sleep(7);                //困了...
    } else {
lable:
        wpid = wait(NULL);        //死等!!!
        if(wpid == -1){
            perror("wait error");
            goto lable;
        }
        printf("I'm parent, I catched child process,"
                "pid = %d\n", wpid);
    }

    return 0;
}      
/***
wait2.c
***/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    pid_t pid, wpid;
    int status;

    pid = fork();

    if(pid == -1){
        perror("fork error");
        exit(1);
    } else if(pid == 0){        //son
        printf("I'm process child, pid = %d\n", getpid());
#if 1
        execl("./abnor", "abnor", NULL);
        perror("execl error");
        exit(1);
#endif
        sleep(1);                
        exit(10);
    } else {
        //wpid = wait(NULL);    //傳出參數
        wpid = wait(&status);    //傳出參數

        if(WIFEXITED(status)){    //正常退出
            printf("I'm parent, The child process "
                    "%d exit normally\n", wpid);
            printf("return value:%d\n", WEXITSTATUS(status));

        } else if (WIFSIGNALED(status)) {    //異常退出
            printf("The child process exit abnormally, "
                    "killed by signal %d\n", WTERMSIG(status));
                                        //擷取信号編号
        } else {
            printf("other...\n");
        }
    }

    return 0;
}      

wait(status):

                     傳回:成功:pid  失敗 -1

                     status:傳出參數

                     1: 阻塞等待子程序

                     2: 回收子程序資源

                     3:    擷取子程序結束狀态:1)WIFEXITED()真

                                                                      WEXITSTATUS()擷取子程序退出狀态