1)wait()和waitpid()函數(shù)說明
wait()函數(shù)用于使父進(jìn)程(也就是調(diào)用wait()的進(jìn)程)阻塞,直到一個子進(jìn)程結(jié)束或者該進(jìn)程接收到了一個指定的信號為止。如果該父進(jìn)程沒有子進(jìn)程或者它的子進(jìn)程已經(jīng)結(jié)束,則wait()就會立即返回。
waitpid()的作用和wait()一樣,但它并不一定要等待第一個終止的子進(jìn)程,它還有若干選項,如可提供一個非阻塞版本的wait()功能,也能支持作業(yè)控制。實際上,wait()函數(shù)只是waitpid()函數(shù)的一個特例,在Linux內(nèi)部實現(xiàn)wait()函數(shù)時直接調(diào)用的就是waitpid()函數(shù)。
2)wait()和waitpid()函數(shù)格式說明
表1列出了wait()函數(shù)的語法要點。
表1 wait()函數(shù)語法要點
所需頭文件 |
#include <sys/types.h> |
#include <sys/wait.h> |
函數(shù)原型 |
pid_t wait(int *status) |
函數(shù)傳入值 |
這里的status是一個整型指針,是該子進(jìn)程退出時的狀態(tài)。若status不為空,則通過它可以獲得子進(jìn)程的結(jié)束狀態(tài)。另外,子進(jìn)程的結(jié)束狀態(tài)可由Linux中一些特定的宏來測定 |
函數(shù)返回值 |
成功:已結(jié)束運行的子進(jìn)程的進(jìn)程號
失。-1
|
表2列出了waitpid()函數(shù)的語法要點。
表2 waitpid()函數(shù)語法要點
所需頭文件 |
#include <sys/types.h>
#include <sys/wait.h>
|
函數(shù)原型 |
pid_t waitpid(pid_t pid, int *status, int options) |
函數(shù)傳入值 |
pid |
pid > 0:只等待進(jìn)程ID等于pid的子進(jìn)程,不管是否已經(jīng)有其他子進(jìn)程運行結(jié)束退出,只要指定的子進(jìn)程還沒有結(jié)束,waitpid()就會一直等下去 |
pid = -1:等待任何一個子進(jìn)程退出,此時和wait()作用一樣 |
pid = 0:等待其組ID等于調(diào)用進(jìn)程的組ID的任一子進(jìn)程 |
pid < -1:等待其組ID等于pid的絕對值的任一子進(jìn)程 |
status |
同wait() |
options |
WNOHANG:若由pid指定的子進(jìn)程沒有結(jié)束,則waitpid()不阻塞而立即返回,此時返回值為0 |
WUNTRACED:為了實現(xiàn)某種操作,由pid指定的任一子進(jìn)程已被暫停,且其狀態(tài)自暫停以來還未報告過,則返回其狀態(tài) |
0:同wait(),阻塞父進(jìn)程,等待子進(jìn)程退出 |
函數(shù)返回值 |
正常:已經(jīng)結(jié)束運行的子進(jìn)程的進(jìn)程號 |
使用選項WNOHANG且沒有子進(jìn)程退出:0 |
調(diào)用出錯:-1 |
3)waitpid()使用實例
由于wait()函數(shù)的使用較為簡單,在此僅以waitpid()為例進(jìn)行講解。本例中首先使用fork()創(chuàng)建一個子進(jìn)程,然后讓其子進(jìn)程暫停5s(使用了sleep()函數(shù))。接下來對原有的父進(jìn)程使用waitpid()函數(shù),并使用參數(shù)WNOHANG使該父進(jìn)程不會阻塞。若有子進(jìn)程退出,則waitpid()返回子進(jìn)程號;若沒有子進(jìn)程退出,則waitpid()返回0,并且父進(jìn)程每隔1s循環(huán)判斷一次。該程序的流程圖如圖1所示。
 圖1 waitpid()函數(shù)程序流程圖
該程序源代碼如下:
/* waitpid.c */
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t pc, pr;
pc = fork();
if (pc < 0)
{
printf("Error fork\n");
}
else if (pc == 0) /* 子進(jìn)程 */
{
/* 子進(jìn)程暫停5s */
sleep(5);
/* 子進(jìn)程正常退出 */
exit(0);
}
else /* 父進(jìn)程 */
{
/* 循環(huán)測試子進(jìn)程是否退出 */
do
{
/* 調(diào)用waitpid(),且父進(jìn)程不阻塞 */
pr = waitpid(pc, NULL, WNOHANG);
/* 若子進(jìn)程還未退出,則父進(jìn)程暫停1s */
if (pr == 0)
{
printf("The child process has not exited\n");
sleep(1);
}
} while (pr == 0);
/* 若發(fā)現(xiàn)子進(jìn)程退出,打印出相應(yīng)情況 */
if (pr == pc)
{
printf("Get child exit code: %d\n",pr);
}
else
{
printf("Some error occured.\n");
}
}
}
將該程序交叉編譯,下載到目標(biāo)板后的運行結(jié)果如下:
$ ./waitpid
The child process has not exited
The child process has not exited
The child process has not exited
The child process has not exited
The child process has not exited
Get child exit code: 75
可見,該程序在經(jīng)過5次循環(huán)后,捕獲到了子進(jìn)程的退出信號,具體的子進(jìn)程號在不同的系統(tǒng)上會有所區(qū)別。
讀者還可以嘗試把“pr = waitpid(pc, NULL, WNOHANG);”改為“pr = waitpid(pc, NULL, 0);”或者“pr = wait(NULL);”,運行的結(jié)果為:
$ ./waitpid
Get child exit code: 76
可見,在上述兩種情況下,父進(jìn)程在調(diào)用waitpid()或wait()之后就將自己阻塞,直到有子進(jìn)程退出為止。
本文選自華清遠(yuǎn)見嵌入式培訓(xùn)教材《從實踐中學(xué)嵌入式Linux應(yīng)用程序開發(fā)》
熱點鏈接:
1、exit()和_exit()函數(shù)
2、Linux下多進(jìn)程編程之exec函數(shù)語法及使用實例
3、Linux下多進(jìn)程編程之fork()函數(shù)語法
4、Linux下多進(jìn)程編程之fork()函數(shù)說明
5、Linux下多任務(wù)系統(tǒng)之線程介紹
更多新聞>> |