1. 程式人生 > >等待子程序結束wait()和waitpid()

等待子程序結束wait()和waitpid()

父子程序有時需要簡單的程序間同步,如父程序等待子程序的結束。

linux提供了以下兩個等待函式:wait()waitpid().

需要包含標頭檔案:

#include <sys/types.h>

#include <sys/wait.h>

1)  pid_t wait(int *status);

功能:等待任一子程序終止,如果子程序終止了,此函式會回收子程序的資源

呼叫wait函式的程序會被掛起(阻塞),直到它的一個子程序退出或收到一個不能被忽視的訊號時才被喚醒。

若呼叫程序沒有子程序或它的子程序已經結束,該函式立即返回。

引數:函式返回時,引數status中包含子程序退出時的狀態資訊。

子程序的退出資訊在一個int中包含了多個欄位,用巨集定義可以取出其中的每個欄位。

返回值:如果執行成功則返回子程序的程序號。出錯返回-1,失敗原因存在errno中。

取出子程序的退出資訊:

>> WIFEXITED(status)

如果子程序是正常終止的,取出的欄位值非零。

>>WEXITSTATUS(status)

返回子程序的退出狀態,退出狀態儲存在status變數的8~16位。

在用此巨集前應先用巨集WIFEXITED判斷子程序是否正常退出,正常退出才可以使用此巨集。

fork3.c程式碼展示:

#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(){
    pid_t pid;
    pid = fork();
    if(pid < 0){
        printf("fork error.\n");
        return -1;
    }else if(pid == 0){
        int i = 0;
        for(i = 0;i < 3;i++){
            printf("this is child process.\n");
            sleep(1);
        }
        _exit(1);
    }else{
        int status = 0;
        wait(&status); //wait the end of child process
        if(WIFEXITED(status)){
            printf("child process return %d\n",WEXITSTATUS(status));
        }
        printf("this is father process.\n");
    }
    return 0;
}
編譯和執行結果如下:


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

功能:等待指定子程序終止,如果子程序終止了,此函式會回收子程序的資源。

返回值:如果執行成功則返回子程序ID。出錯返回-1,失敗原因存於errno中。

---- 從本質上講,系統呼叫waitpid和wait的作用是完全相同的,但waitpid多出了兩個可由使用者控制的引數pid和options,從而為我們程式設計提供了另一種更靈活的方式。

pid:當引數pid取不同的值時,有不同的意義:

1> pid>0時,只等待程序ID等於pid的子程序,不管其它已經有多少子程序執行結束退出了,只要指定的子程序還沒有結束,waitpid就會一直等下去。

2> pid=-1時,等待任何一個子程序退出,沒有任何限制,此時waitpid和wait的作用一模一樣。

3> pid=0時,等待和該程序在同一個程序組中的任何子程序,如果某個子程序已經加入了別的程序組,waitpid不會對它做任何理睬。

4> pid<-1時,等待一個指定程序組中的任何子程序,這個程序組的ID等於pid的絕對值。

options:目前在Linux中只支援WNOHANG和WUNTRACED兩個選項,可以用”|“運算子把它們連線起來使用,如:

         ret = waitpid(-1,NULL,WNOHANG|WUNTRACED);

WNOHANG,表示即使沒有子程序退出,它也會立即返回,不會像wait那樣永遠等下去。

WUNTRACED,與跟蹤除錯有關,極少用到。

waitpid的返回值比wait稍微複雜一些,一共有3種情況:

>> 正常返回的時候,waitpid返回收集到的子程序的程序ID;

>> 如果設定了選項WNOHANG,而呼叫中waitpid發現沒有已退出的子程序可收集,則返回0;

>> 呼叫中出錯,則返回-1,這時errno會被設定成相應的值以指示錯誤所在。例如:當pid所指示的子程序不存在,或此程序存在,但不是呼叫程序的子程序,waitpid就會出錯返回,這時errno被設定為ECHILD。