6进程原语:wait()和waitpid()函数
1 wait/waitpid
僵尸進(jìn)程: 子進(jìn)程退出,父進(jìn)程沒(méi)有回收子進(jìn)程資源(PCB),則子進(jìn)程變成僵尸進(jìn)程
孤兒進(jìn)程: 父進(jìn)程先于子進(jìn)程結(jié)束,則子進(jìn)程成為孤兒進(jìn)程,子進(jìn)程的父進(jìn)程成為1號(hào)
進(jìn)程init進(jìn)程,稱(chēng)為init進(jìn)程領(lǐng)養(yǎng)孤兒進(jìn)程
2依賴(lài)的頭文件
#include <sys/types.h>
#include <sys/wait.h>
3函數(shù)聲明
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, intoptions);
?
The value of pid can be:
??????< -1?? meaning wait for anychild process whose? process? group?ID? is
????????????? equal to the absolute value ofpid.
?
??????-1???? meaning wait for any childprocess.
?
??????0????? meaning? wait?for? any? child process whose process group ID is
????????????? equal to that of the callingprocess.
?
??????> 0??? meaning wait for thechild whose process? ID? is?equal? to? the
????????????? value of pid.
< -1 回收指定進(jìn)程組內(nèi)的任意子進(jìn)程
-1 回收任意子進(jìn)程
0 回收和當(dāng)前調(diào)用waitpid一個(gè)組的所有子進(jìn)程
> 0 回收指定ID的子進(jìn)程
3.說(shuō)明:
一個(gè)進(jìn)程在終止時(shí)會(huì)關(guān)閉所有文件描述符,釋放在用戶空間分配的內(nèi)存,但它的PCB還
保留著,內(nèi)核在其中保存了一些信息:如果是正常終止則保存著退出狀態(tài),如果是異常終止
則保存著導(dǎo)致該進(jìn)程終止的信號(hào)是哪個(gè)。這個(gè)進(jìn)程的父進(jìn)程可以調(diào)用wait或waitpid獲取這
些信息,然后徹底清除掉這個(gè)進(jìn)程。我們知道一個(gè)進(jìn)程的退出狀態(tài)可以在Shell中用特殊變
量$?查看,因?yàn)?/span>Shell是它的父進(jìn)程,當(dāng)它終止時(shí)Shell調(diào)用wait或waitpid得到它的退出狀
態(tài)同時(shí)徹底清除掉這個(gè)進(jìn)程。
如果一個(gè)進(jìn)程已經(jīng)終止,但是它的父進(jìn)程尚未調(diào)用wait或waitpid對(duì)它進(jìn)行清理,這時(shí)
的進(jìn)程狀態(tài)稱(chēng)為僵尸(Zombie)進(jìn)程。任何進(jìn)程在剛終止時(shí)都是僵尸進(jìn)程,正常情況下,僵
尸進(jìn)程都立刻被父進(jìn)程清理了,為了觀察到僵尸進(jìn)程,我們自己寫(xiě)一個(gè)不正常的程序,父進(jìn)
程fork出子進(jìn)程,子進(jìn)程終止,而父進(jìn)程既不終止也不調(diào)用wait清理子進(jìn)程:
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
pid_t pid=fork();
if(pid<0) {
perror("fork");
exit(1);
}
if(pid>0) { /* parent */
while(1);
}
/* child */
return 0;
}
若調(diào)用成功則返回清理掉的子進(jìn)程id,若調(diào)用出錯(cuò)則返回-1。父進(jìn)程調(diào)用wait或
waitpid時(shí)可能會(huì):
* 阻塞(如果它的所有子進(jìn)程都還在運(yùn)行)。
* 帶子進(jìn)程的終止信息立即返回(如果一個(gè)子進(jìn)程已終止,正等待父進(jìn)程讀取其終止信
息)。
* 出錯(cuò)立即返回(如果它沒(méi)有任何子進(jìn)程)。
這兩個(gè)函數(shù)的區(qū)別是:
* 如果父進(jìn)程的所有子進(jìn)程都還在運(yùn)行,調(diào)用wait將使父進(jìn)程阻塞,而調(diào)用waitpid時(shí)如果在options參數(shù)中指定WNOHANG可以使父進(jìn)程不阻塞而立即返回0。
* wait等待第一個(gè)終止的子進(jìn)程,而waitpid可以通過(guò)pid參數(shù)指定等待哪一個(gè)子進(jìn)程。
可見(jiàn),調(diào)用wait和waitpid不僅可以獲得子進(jìn)程的終止信息,還可以使父進(jìn)程阻塞等待子進(jìn)
程終止,起到進(jìn)程間同步的作用。如果參數(shù)status不是空指針,則子進(jìn)程的終止信息通過(guò)
這個(gè)參數(shù)傳出,如果只是為了同步而不關(guān)心子進(jìn)程的終止信息,可以將status參數(shù)指定為
NULL。
例waitpid
The?value? of? options?is an OR of zero or more of the following con‐
??????stants:
??????WNOHANG???? return immediately ifno child has exited.
??????WUNTRACED?? also return if a childhas? stopped? (but?not? traced? via
?????????????????? ptrace(2)).?? Status for traced children which havestopped
?????????????????? is provided even if thisoption is not specified.
??????WCONTINUED (since Linux 2.6.10)
?????????????????? also return if a stoppedchild has been resumed by delivery
?????????????????? of SIGCONT.
??????(For Linux-only options, see below.)
If status is not NULL, wait() and waitpid()store status information in
??????the int to which it points.? Thisinteger can? be? inspected?with? the
??????following? macros? (which take the integer itself as anargument, not a
??????pointer to it, as is done in wait() and waitpid()!):
?
??????WIFEXITED(status)
????????????? returns true if the childterminated normally, that is, by call‐
????????????? ing exit(3) or _exit(2), or byreturning from main().
?
??????WEXITSTATUS(status)
????????????? returns? the?exit? status? of? thechild.? This consists of the
????????????? least significant 8 bits of thestatus argument that? the? child
????????????? specified? in?a? call to exit(3) or _exit(2) oras the argument
????????????? for a return statement inmain().? This macro should be employed
????????????? only if WIFEXITED returned true.
?
??????WIFSIGNALED(status)
????????????? returns true if the child processwas terminated by a signal.
?
??????WTERMSIG(status)
????????????? returns? the?number of the signal that caused the child process
????????????? to terminate.? This macro should be employed only ifWIFSIGNALED
????????????? returned true.
WCOREDUMP(status)
???? ?????????returns? true?if? the? child?produced a core dump.? This macro
????????????? should be employed only? if?WIFSIGNALED? returned? true.??This
????????????? macro? is? notspecified in POSIX.1-2001 and is not available on
????????????? some UNIX implementations (e.g.,AIX,? SunOS).?? Only?use? this
????????????? enclosed in #ifdef WCOREDUMP ...#endif.
?
??????WIFSTOPPED(status)
????????????? returns? true?if the child process was stopped by delivery of a
????????????? signal; this is possible only ifthe call was? done? using?WUN‐
????????????? TRACED or when the child is beingtraced (see ptrace(2)).
?
??????WSTOPSIG(status)
????????????? returns the number of the signalwhich caused the child to stop.
????????????? This macro should be employedonly if WIFSTOPPED returned true.
?
??????WIFCONTINUED(status)
????????????? (since Linux 2.6.10) returns? true?if? the? child?process? was
????????????? resumed by delivery of SIGCONT.
?
#include <sys/wait.h>
??????#include <stdlib.h>
??????#include <unistd.h>
??????#include <stdio.h>
?
??????int
??????main(int argc, char *argv[])
??????{
??????????pid_t cpid, w;
??????????int status;
?
??????????cpid = fork();
??????????if (cpid == -1) {
?????????????? perror("fork");
?????????????? exit(EXIT_FAILURE);
??????????}
?
??????????if (cpid == 0) {??????????? /*Code executed by child */
?????????????? printf("Child PID is%ld\n", (long) getpid());
?????????????? if (argc == 1)
?????????????????? pause();??????????????????? /* Wait for signals */
?????????????? _exit(atoi(argv[1]));
} else {??????????????????? /*Code executed by parent */
?????????????? do {
?????????????????? w = waitpid(cpid,&status, WUNTRACED | WCONTINUED);
?????????????????? if (w == -1) {
?????????????????????? perror("waitpid");
?????????????????????? exit(EXIT_FAILURE);
?????????????????? }
?
?????????????????? if (WIFEXITED(status)) {
?????????????????????? printf("exited,status=%d\n", WEXITSTATUS(status));
?????????????????? } else if(WIFSIGNALED(status)) {
???? ??????????????????printf("killed by signal%d\n", WTERMSIG(status));
?????????????????? } else if(WIFSTOPPED(status)) {
?????????????????????? printf("stopped bysignal %d\n", WSTOPSIG(status));
?????????????????? } else if(WIFCONTINUED(status)) {
??????????????????????printf("continued\n");
?????????????????? }
?????????????? } while (!WIFEXITED(status)&& !WIFSIGNALED(status));
?????????????? exit(EXIT_SUCCESS);
??????????}
??????}
總結(jié)
以上是生活随笔為你收集整理的6进程原语:wait()和waitpid()函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 3进程状态getrlimit()函数和s
- 下一篇: 光大信用卡白金卡年费