日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux中wait()函数及waitpid()函数

發布時間:2023/11/30 linux 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux中wait()函数及waitpid()函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

編程過程中,有時需要讓一個進程等待另一個進程,最常見的是父進程等待自己的子進程,或者父進程回收自己的子進程資源包括僵尸進程。這里簡單介紹一下系統調用函數:wait()

函數原型是

#include <sys/types.h>

#include <wait.h>

int wait(int *status)

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

注:

  當父進程忘了用wait()函數等待已終止的子進程時,子進程就會進入一種無父進程的狀態,此時子進程就是僵尸進程.

  wait()要與fork()配套出現,如果在使用fork()之前調用wait(),wait()的返回值則為-1,正常情況下wait()的返回值為子進程的PID.

  如果先終止父進程,子進程將繼續正常進行,只是它將由init進程(PID 1)繼承,當子進程終止時,init進程捕獲這個狀態.

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

pid = wait(NULL);

如果成功,wait會返回被收集的子進程的進程ID,如果調用進程沒有子進程,調用就會失敗,此時wait返回-1,同時errno被置為ECHILD。

  如果參數status的值不是NULL,wait就會把子進程退出時的狀態取出并存入其中, 這是一個整數值(int),指出了子進程是正常退出還是被非正常結束的,以及正常結束時的返回值,或被哪一個信號結束的等信息。由于這些信息 被存放在一個整數的不同二進制位中,所以用常規的方法讀取會非常麻煩,人們就設計了一套專門的宏(macro)來完成這項工作,下面我們來學習一下其中最常用的兩個:

1,WIFEXITED(status) 這個宏用來指出子進程是否為正常退出的,如果是,它會返回一個非零值。

(請注意,雖然名字一樣,這里的參數status并不同于wait唯一的參數–指向整數的指針status,而是那個指針所指向的整數,切記不要搞混了。)

2, WEXITSTATUS(status) 當WIFEXITED返回非零值時,我們可以用這個宏來提取子進程的返回值,如果子進程調用exit(5)退出,WEXITSTATUS(status) 就會返回5;如果子進程調用exit(7),WEXITSTATUS(status)就會返回7。請注意,如果進程不是正常退出的,也就是說, WIFEXITED返回0,這個值就毫無意義。

#include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <wait.h> #include <errno.h> #include <stdlib.h> /***********************************************************功能說明:進程等待wait()方法的應用author: linux.sir@qq.com***********************************************************/ void waitprocess();int main(int argc, char * argv[]) {waitprocess();}void waitprocess() {int count = 0;pid_t pid = fork();int status = -1;if(pid<0){printf("fork error for %m\n",errno );}else if(pid>0){printf("this is parent ,pid = %d\n",getpid() );wait(&status);//父進程執行到此,馬上阻塞自己,直到有子進程結束。當發現有子進程結束時,就會回收它的資源。}else{printf("this is child , pid = %d , ppid = %d\n",getpid(),getppid() );int i;for (i = 0; i < 10; i++) {count++;sleep(1);printf("count = %d\n", count)? ;}exit(5);}printf("child exit status is %d\n", WEXITSTATUS(status));//status是按位存儲的狀態信息,需要調用相應的宏來還原一下printf("end of program from pid = %d\n",getpid() );}

運行結果如下:

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

?????#include <sys/types.h> /* 提供類型pid_t的定義 */

?????#include <sys/wait.h>

?????pid_t ?waitpid(pid_t pid,??int *status,??int options)

從本質上講,系統調用waitpid和wait的作用是完全相同的,但waitpid多出了兩個可由用戶控制的參數pid和options,從而為我們編程提供了另一種更靈活的方式。下面我們就來詳細介紹一下這兩個參數:

pid:

從參數的名字pid和類型pid_t中就可以看出,這里需要的是一個進程ID。但當pid取不同的值時,在這里有不同的意義。

??pid>0時,只等待進程ID等于pid的子進程,不管其它已經有多少子進程運行結束退出了,只要指定的子進程還沒有結束,waitpid就會一直等下去。
??pid=-1時,等待任何一個子進程退出,沒有任何限制,此時waitpid和wait的作用一模一樣。
??pid=0時,等待同一個進程組中的任何子進程,如果子進程已經加入了別的進程組,waitpid不會對它做任何理睬。
??pid<-1時,等待一個指定進程組中的任何子進程,這個進程組的ID等于pid的絕對值。

options:

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

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

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

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

如果使用了WNOHANG參數調用waitpid,即使沒有子進程退出,它也會立即返回,不會像wait那樣永遠等下去。

而WUNTRACED參數,由于涉及到一些跟蹤調試方面的知識,加之極少用到,這里就不多費筆墨了,有興趣的讀者可以自行查閱相關材料。

看到這里,聰明的讀者可能已經看出端倪了:wait不就是經過包裝的waitpid嗎?沒錯,察看<內核源碼目錄>/include/unistd.h文件349-352行就會發現以下程序段:

static inline pid_t wait(int * wait_stat)

{

????return waitpid(-1,wait_stat,0);

}

返回值和錯誤

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

??????????1、當正常返回的時候,waitpid返回收集到的子進程的進程ID;

??????????2、如果設置了選項WNOHANG,而調用中waitpid發現沒有已退出的子進程可收集,則返回0;

??????????3、如果調用中出錯,則返回-1,這時errno會被設置成相應的值以指示錯誤所在;

當pid所指示的子進程不存在,或此進程存在,但不是調用進程的子進程,waitpid就會出錯返回,這時errno被設置為ECHILD;
?

/* waitpid.c */#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>int main(){pid_t pc, pr;pc=fork();if(pc<0) /* 如果fork出錯 */{printf("Error occured on forking./n");}else if(pc==0) /* 如果是子進程 */{sleep(10); /* 睡眠10秒 */exit(0);}/* 如果是父進程 */do{pr=waitpid(pc, NULL, WNOHANG); /* 使用了WNOHANG參數,waitpid不會在這里等待 */if(pr==0) /* 如果沒有收集到子進程 */{printf("No child exited/n");sleep(1);}}while(pr == 0); /* 沒有收集到子進程,就回去繼續嘗試 */if(pr == pc){printf("successfully get child %d/n", pr);}elseprintf("some error occured/n");}

編譯并運行:

$ cc waitpid.c -o waitpid

$ ./waitpid

No child exited

No child exited

No child exited

No child exited

No child exited

No child exited

No child exited

No child exited

No child exited

No child exited

successfully get child 1526

父進程經過10次失敗的嘗試之后,終于收集到了退出的子進程。

因為這只是一個例子程序,不便寫得太復雜,所以我們就讓父進程和子進程分別睡眠了10秒鐘和1秒鐘,代表它們分別作了10秒鐘和1秒鐘的工作。父子進程都有工作要做,父進程利用工作的簡短間歇察看子進程的是否退出,如退出就收集它。

提示:可以嘗試在最后一個例子中把pr=waitpid(pc, NULL, WNOHANG);?改為pr=waitpid(pc, NULL, 0);或者pr=wait(NULL);看看運行結果有何變化?(修改后的結果使得父進程將自己阻塞,直到有子進程退出為止!)
?

原文鏈接:https://blog.csdn.net/wyhh_0101/article/details/83933308

總結

以上是生活随笔為你收集整理的Linux中wait()函数及waitpid()函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。