wait函數和waitpid的使用和總結


wait和waitpid出現的原因
SIGCHLD
--當子進程退出的時候,內核會向父進程發送SIGCHLD信號,子進程的退出是個異步事件(子進程可以在父進程運行的任何時刻終止)
--子進程退出時,內核將子進程置為僵屍狀態,這個進程成為僵屍進程,它只保留最小的一些內核數據結構,以便父進程查詢子進程的退出狀態
--父進程查詢子進程的退出狀態可以用wait/waitpid函數

wait獲取staus后檢測處理
宏定義  描述
WIFEXITED(status) 如果進程子進程正常結束,返回一個非零值
    WEXITSTATUS(status) 如果WIFEXITED非零,返回子進程退出碼
WIFSIGNALED(status) 子進程因為捕獲信號而終止,返回非零值
    WTERMSIG(status) 如果WIFSIGNALED非零,返回信號代碼
WIFSTOPPED(status) 如果進程被暫停,返回一個非零值
    WSTOPSIG(status) 如果WIFSTOPPED非零,返回信號代碼

wait系統調用在Linux函數庫中的原型是: 

#include <sys/types.h>    
#include <sys/wait.h>
pid_t wait(int *status) 

 進程一旦調用了wait,就立即阻塞自己,由wait自動分析是否當前進程的某個子進程已經 退出,如果讓它找到了這樣一個已經變成僵屍的子進程,wait就會收集這個子進程的信息,並把它徹底銷毀后返回;如果沒有找到這樣一個子進程,wait就 會一直阻塞在這里,直到有一個出現為止。

參數status用來保存被收集進程退出時的一些狀態,它是一個指向int類型的指針。但如果我們對這個子進程是如何死掉的毫不在意,只想把這個僵屍進程消滅掉,(事實上絕大多數情況下,我們都會這樣想),我們就可以設定這個參數為NULL,就象下面這樣

pid = wait(NULL); 

waitpid系統調用在Linux函數庫中的原型是:

函數功能:用來等待某個特定進程的結束
status如果不為空,會把狀態信息寫到它指向的位置
    options允許改變waitpid的行為,最有用的一個選項是WNOHANG,它的作用是防止waitpid把調用者的執行掛起
返回值:成功返回等待子進程的pid,失敗返回-1
#include <sys/types.h>   
#include <sys/wait.h>  
pid_t waitpid(pid_t pid,int *status,int options) 
  • pid>0時,只等待進程ID等於pid的子進程,不管其它已經有多少子進程運行結束退出了,只要指定的子進程還沒有結束,waitpid就會一直等下去。
  • pid=-1時,等待任何一個子進程退出,沒有任何限制,此時waitpid和wait的作用一模一樣。
  • pid=0時,等待同一個進程組中的任何子進程,如果子進程已經加入了別的進程組,waitpid不會對它做任何理睬。
  • pid<-1時,等待一個指定進程組中的任何子進程,這個進程組的ID等於pid的絕對值。

options提供了一些額外的選項來控制waitpid,目前在Linux中只支持WNOHANG和WUNTRACED兩個選項,這是兩個常數,可以用"|"運算符把它們連接起來使用,比如:

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

如果我們不想使用它們,也可以把options設為0,如:

ret=waitpid(-1,NULL,0); 

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

int main(int arg,char *args[])
{
    pid_t pid=fork();
    if(pid==-1)
    {
        printf("fork() failed ! error message:%s\n",strerror(errno));
        return -1;
    }
    if(pid>0)
    {
        int status=0;
        printf("父進程\n");
        wait(&status);
        if(WIFEXITED(status))//WIFEXITED宏的釋義: wait if exit ed
        {
            printf("子進程返回信息碼:%d\n",WEXITSTATUS(status));
        }else if(WIFSIGNALED(status))
        {
            printf("子進程信號中斷返回信息碼:%d\n",WTERMSIG(status));
        }else if(WIFSTOPPED(status))
        {
            printf("子進程暫停返回信息碼:%d\n",WSTOPSIG(status));
        }else
        {
            printf("其他退出信息!\n");
        }
    }else if(pid==0)
    {
        printf("i am child !\n");
        abort();
        //exit(100);
    }
    printf("game is over!\n");
    return 0;
}
wait()函數成功返回等待子進程的pid,失敗返回-1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int arg, char *args[])
{
    pid_t pid = 0;
    int i = 0, ret = 0;
    for (i = 0; i < 10; i++)
    {
        pid = fork();
        if (pid == -1)
        {
            printf("fork() failed ! error message:%s\n", strerror(errno));
            return -1;
        }
        if (pid == 0)
        {
            printf("child haved run!\n");
            exit(0);
        }
    }
    while (1)
    {
        //wait()函數的返回值是子進程的pid
        ret = wait(NULL);
        printf("子進程pid=%d\n", ret);
        if (ret == -1)
        {
            //父進程wait()函數阻塞過程中,有可能被別的信號中斷,需要做異常處理
            if (errno == EINTR)
            {
                continue;
            }
            break;
        }
    }
    printf("game is over!\n");
    return 0;
}

  

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM