国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 操作系統(tǒng) > 正文

進(jìn)程控制之wait和waitpid函數(shù)

2024-06-28 13:28:36
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
進(jìn)程控制之wait和waitpid函數(shù)

當(dāng)一個(gè)進(jìn)程正常或異常終止時(shí),內(nèi)核就向其父進(jìn)程發(fā)送SIGCHLD信號(hào)。因?yàn)樽舆M(jìn)程終止是個(gè)異步事件(這可以在父進(jìn)程運(yùn)行的任何時(shí)候發(fā)生),所以這種信號(hào)也是內(nèi)核向父進(jìn)程發(fā)的異步通知。父進(jìn)程可以選擇忽略該信號(hào),或者提供一個(gè)該信號(hào)發(fā)生時(shí)即被調(diào)用執(zhí)行的函數(shù)(信號(hào)處理程序)。對(duì)于這種信號(hào)的系統(tǒng)默認(rèn)動(dòng)作是忽略它)。

調(diào)用wait或waitpid的進(jìn)程可能會(huì)發(fā)生的情況:

  • 如果其所有子進(jìn)程都還在運(yùn)行,則阻塞。
  • 如果一個(gè)子進(jìn)程已終止,正等待父進(jìn)程獲取其終止?fàn)顟B(tài),則取得該子進(jìn)程的終止?fàn)顟B(tài)立即返回。
  • 如果它沒(méi)有任何子進(jìn)程,則立即出錯(cuò)返回。

如果進(jìn)程由于接收到SIGCHLD信號(hào)而調(diào)用wait,則可期望wait會(huì)立即返回。但是如果在任意時(shí)刻調(diào)用wait,則進(jìn)程可能會(huì)阻塞。

#include <sys/wait.h>pid_t wait( int *statloc );返回值:若成功則返回已終止子進(jìn)程ID,若出錯(cuò)則返回-1pid_t waitpid( pid_t pid, int *statloc, int options );返回值:若成功則返回狀態(tài)改變的子進(jìn)程ID,若出錯(cuò)則返回-1,若指定了WNOHANG選項(xiàng)且pid指定的子進(jìn)程狀態(tài)沒(méi)有發(fā)生改變則返回0

這兩個(gè)函數(shù)的區(qū)別如下:

  • 在一個(gè)子進(jìn)程終止前,wait使其調(diào)用者阻塞,而waitpid有一個(gè)選項(xiàng),可使調(diào)用者不阻塞。
  • waitpid并不等待在其調(diào)用之后的第一個(gè)終止子進(jìn)程,它有若干個(gè)選項(xiàng),可以控制它所等待的進(jìn)程。

如果一個(gè)子進(jìn)程已經(jīng)終止,并且是一個(gè)僵死進(jìn)程,則wait立即返回并取得該子進(jìn)程的狀態(tài),否則wait使其調(diào)用者阻塞直到一個(gè)子進(jìn)程終止。如果調(diào)用者阻塞而且它有多個(gè)子進(jìn)程,則在其一個(gè)子進(jìn)程終止時(shí),wait就立即返回。因?yàn)閣ait返回終止子進(jìn)程的進(jìn)程ID,所以它總能了解是哪一個(gè)子進(jìn)程終止了。

這兩個(gè)函數(shù)的參數(shù)statloc是一個(gè)整型指針。如果statloc不是一個(gè)空指針,則終止進(jìn)程的終止?fàn)顟B(tài)就存放在它所指向的單元內(nèi)。如果不關(guān)心終止?fàn)顟B(tài),則可將該參數(shù)指定為空指針。

依據(jù)傳統(tǒng),這兩個(gè)函數(shù)返回的整型狀態(tài)字是由實(shí)現(xiàn)定義的。其中某些位表示退出狀態(tài)(正常返回),其他位則指示信號(hào)編號(hào)(異常返回),有一位指示是否產(chǎn)生了一個(gè)core文件等。POSIX.1規(guī)定狀態(tài)用定義在<sys/wait.h>中的各個(gè)宏來(lái)查看。有四個(gè)互斥的宏可用來(lái)取得進(jìn)程終止的原因,它們的名字都以WIF開(kāi)始。基于這四個(gè)宏中哪一個(gè)值為真,就可選用其他宏(表8-1說(shuō)明欄中下劃線標(biāo)注的宏)來(lái)取得終止?fàn)顟B(tài)、信號(hào)編號(hào)等。這四個(gè)互斥的宏示于表8-1中。

表8-1 檢查wait和waitpid所返回的終止?fàn)顟B(tài)的宏

說(shuō)明

         WIFEXITED(status)     若為正常終止子進(jìn)程返回的狀態(tài),則為真。對(duì)于這種情況可執(zhí)行WEXITSTATUS(status),取子進(jìn)程傳送給exit、_exit或_Exit參數(shù)的低8位
         WIFSIGNALED(status)    若為異常終止子進(jìn)程返回的狀態(tài),則為真(接到一個(gè)不捕捉的信號(hào))。對(duì)于這種情況,可執(zhí)行WTERMSIG(status),取使子進(jìn)程終止的信號(hào)編號(hào)。另外,有些實(shí)現(xiàn)定義宏WCOREDUMP(status),若已產(chǎn)生終止進(jìn)程的core文件,則它返回真
        WIFSTOPPED(status)    若為當(dāng)前暫停子進(jìn)程的返回狀態(tài),則為真。對(duì)于這種情況,可執(zhí)行WSTOPSIG(status),取使子進(jìn)程暫停的信號(hào)編號(hào)
        WIFCONTINUED(status)    若在作業(yè)控制暫停后已經(jīng)繼續(xù)的子進(jìn)程返回了狀態(tài),則為真。(POSIX.1的XSI擴(kuò)展;僅用于waitpid。)

 

程序清單8-3 打印exit狀態(tài)的說(shuō)明

[root@localhost apue]# cat PRog8-3.c#include "apue.h"#include <sys/wait.h>void pr_exit(int status){        if(WIFEXITED(status))                printf("normal termination, exit status = %d/n",                        WEXITSTATUS(status));        else if(WIFSIGNALED(status))                printf("abnormal termination, signal number = %d%s/n",                        WTERMSIG(status),#ifdef  WCOREDUMP                WCOREDUMP(status) ? " (core file generated)" : "");#else                "");#endif        else if(WIFSTOPPED(status))                printf("child stopped, signal number = %d/n",                        WSTOPSIG(status));}

程序清單8-4 演示不同的exit值(調(diào)用prog8-3中的pr_exit函數(shù))

[root@localhost apue]# cat prog8-4.c#include "apue.h"#include <sys/wait.h>intmain(void){        pid_t   pid;        int     status;        if ((pid = fork()) < 0)                err_sys("fork error");        else if (pid == 0)                exit(7);                /* child */        if (wait(&status) != pid)       /* wait for child */                err_sys("wait error");        pr_exit(status);                /* and print its status */        if ((pid = fork()) < 0)                err_sys("fork error");        else if (pid == 0)              /* child */                abort();        if (wait(&status) != pid)       /* wait for child */                err_sys("wait error");        pr_exit(status);                /* and print its status */        if ((pid = fork()) < 0)                err_sys("fork error");        else if (pid == 0)              /* child */                status /= 0;            /* divide by 0 generates SIGPE */        if (wait(&status) != pid)       /* wait for child */                err_sys("wait error");        pr_exit(status);                /* and print its status */        exit(0);}

運(yùn)行該程序可得:

[root@localhost apue]# ./prog8-4normal termination, exit status = 7abnormal termination, signal number = 6abnormal termination, signal number = 8

不幸的是,沒(méi)有一種可移植的方法將WTERMSIG得到的信號(hào)編號(hào)映射為說(shuō)明性的名字。我們必須查看<signal.h>頭文件才能知道SIGABRT的值是6,SIGFPE的值是8.

正如前面所述,如果一個(gè)進(jìn)程有幾個(gè)子進(jìn)程,那么只要有一個(gè)子進(jìn)程終止,wait就返回。如果要等待一個(gè)指定的進(jìn)程終止(如果知道要等待進(jìn)程的ID),那么該如何做呢?POSIX.1定義了waitpid函數(shù)以提供這種功能(以及其他一些功能)。

對(duì)于waitpid函數(shù)中pid參數(shù)的作用解釋如下:

pid == –1   等待任一子進(jìn)程。就這一方面而言,waitpid與wait等效。
pid > 0   等待其進(jìn)程ID與pid相等的子進(jìn)程。
pid == 0   等待其組ID等于調(diào)用進(jìn)程組ID的任一子進(jìn)程。
pid < –1   等待其組ID等于pid絕對(duì)值的任一子進(jìn)程。

waitpid函數(shù)返回終止子進(jìn)程的進(jìn)程ID,并將該子進(jìn)程的終止?fàn)顟B(tài)存放在由status指向的存儲(chǔ)單元中。對(duì)于wait,其唯一的出錯(cuò)是調(diào)用進(jìn)程沒(méi)有子進(jìn)程(函數(shù)調(diào)用被一個(gè)信號(hào)中斷時(shí),也可能返回另一種出錯(cuò))。但是對(duì)于waitpid,如果指定的進(jìn)程或進(jìn)程組不存在,或者參數(shù)pid指定的進(jìn)程不是調(diào)用進(jìn)程的子進(jìn)程則都將出錯(cuò)。

options參數(shù)使我們能進(jìn)一步控制waitpid的操作。此參數(shù)可以是0,或者是表8-2中常量按位“或”運(yùn)算的結(jié)果。

表8-2 waitpid的options常量

常量

說(shuō)明

          WCONTINUED   若實(shí)現(xiàn)支持作業(yè)控制,那么由pid指定的任一子進(jìn)程在暫停后已經(jīng)繼續(xù),但其狀態(tài)尚未報(bào)告,則返回其狀態(tài)
          WNOHANG   若由pid指定的子進(jìn)程并不是立即可用的,則waitpid不阻塞,此時(shí)其返回值為0
          WUNTRACED   若某實(shí)現(xiàn)支持作業(yè)控制,而由pid指定的任一子進(jìn)程已處于暫停狀態(tài),并且其狀態(tài)自暫停以來(lái)還未報(bào)告過(guò),則返回其狀態(tài)。WIFSTOPPED宏確定返回值是否對(duì)應(yīng)于一個(gè)暫停子進(jìn)程

 

waitpid函數(shù)提供了wait函數(shù)沒(méi)有提供的三個(gè)功能:

(1)waitpid可等待一個(gè)特定的進(jìn)程,而wait則返回任一終止子進(jìn)程的狀態(tài)。

(2)waitpid提供了一個(gè)wait的非阻塞版本。有時(shí)用戶希望取得一個(gè)子進(jìn)程的狀態(tài),但不想阻塞。

(3)waitpid支持作業(yè)控制(利用WUNTRACED和WCONTINUED選項(xiàng))。

如果一個(gè)進(jìn)程fork一個(gè)子進(jìn)程,但不要等待子進(jìn)程終止,也不希望子進(jìn)程處于僵死狀態(tài)直到父進(jìn)程終止,實(shí)現(xiàn)這一要求的技巧是調(diào)用fork兩次

程序清單8-5 調(diào)用fork兩次以避免僵死進(jìn)程

[root@localhost apue]# cat prog8-5.c#include "apue.h"#include <sys/wait.h>intmain(void){        pid_t pid;        if ((pid = fork()) < 0)        {                err_sys("fork error");        }        else if (pid == 0)              /* first child */        {                if ((pid = fork()) < 0)                        err_sys("fork error");                else if (pid > 0)                        exit(0);        /* parent from second fork == first child */                /*                * We're the second child; our parent become init as soon                * as our real parent calls exit() in the statement above.                * Here's where we'd continue executing, knowing that when                 * we're done, init will reap our status.                */                sleep(2);                printf("second child, parent pid = %d/n", getppid());                exit(0);        }        if (waitpid(pid, NULL, 0) != pid)       /* wait for first child */                err_sys("waitpid error");        /*        * We're the parent ( the original process ); we continue executing,        * knowing that we're not the parent of the second child.         */        exit(0);}

第二個(gè)子進(jìn)程調(diào)用sleep以保證在打印父進(jìn)程ID時(shí)第一個(gè)子進(jìn)程已終止。在fork之后,父、子進(jìn)程都可繼續(xù)執(zhí)行,并且我們無(wú)法預(yù)知哪一個(gè)會(huì)先執(zhí)行。在fork之后,如果不使第二個(gè)子進(jìn)程休眠,那么它可能比其父進(jìn)程先執(zhí)行,于是它打印的父進(jìn)程ID將是創(chuàng)建它的父進(jìn)程,而不是init進(jìn)程(進(jìn)程ID 1)。

執(zhí)行結(jié)果:

[root@localhost apue]# ./prog8-5[root@localhost apue]# second child, parent pid = 1

注意,當(dāng)原先的進(jìn)程(也就是exec本程序的進(jìn)程)終止時(shí),shell打印其提示符,這在第二個(gè)子進(jìn)程打印其父進(jìn)程ID之前。

本篇博文內(nèi)容摘自《UNIX環(huán)境高級(jí)編程》(第二版),僅作個(gè)人學(xué)習(xí)記錄所用。關(guān)于本書可參考:http://www.apuebook.com/


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 山西省| 湖州市| 武功县| 芷江| 定安县| 陕西省| 阜康市| 泸西县| 陇南市| 宁化县| 岐山县| 西和县| 嘉兴市| 汝州市| 英吉沙县| 历史| 沽源县| 铁岭县| 乐安县| 汨罗市| 米易县| 勃利县| 恩平市| 凤城市| 华阴市| 霸州市| 宜黄县| 通江县| 青浦区| 繁昌县| 揭东县| 贡山| 太仆寺旗| 凭祥市| 九龙城区| 夹江县| 怀安县| 昌乐县| 沿河| 祁阳县| 麻阳|