6进程原语:wait()和waitpid()函数



1 wait/waitpid

僵尸进程:
子进程退出,父进程没有回收子进程资源(PCB),则子进程变成僵尸进程

孤儿进程:
父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为1号

进程init进程,称为init进程领养孤儿进程

2依赖的头文件

#include <sys/types.h>

#include <sys/wait.h>

3函数声明

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
回收指定进程组内的任意子进程

-1
回收任意子进程

0
回收和当前调用waitpid一个组的所有子进程

> 0
回收指定ID的子进程

3.说明:

一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还

保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止

则保存着导致该进程终止的信号是哪个。这个进程的父进程可以调用wait或waitpid获取这

些信息,然后彻底清除掉这个进程。我们知道一个进程的退出状态可以在Shell中用特殊变

量$?查看,因为Shell是它的父进程,当它终止时Shell调用wait或waitpid得到它的退出状

态同时彻底清除掉这个进程。

如果一个进程已经终止,但是它的父进程尚未调用wait或waitpid对它进行清理,这时

的进程状态称为僵尸(Zombie)进程。任何进程在刚终止时都是僵尸进程,正常情况下,僵

尸进程都立刻被父进程清理了,为了观察到僵尸进程,我们自己写一个不正常的程序,父进

程fork出子进程,子进程终止,而父进程既不终止也不调用wait清理子进程:

#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;

}

若调用成功则返回清理掉的子进程id,若调用出错则返回-1。父进程调用wait或

waitpid时可能会:

*
阻塞(如果它的所有子进程都还在运行)。

*
带子进程的终止信息立即返回(如果一个子进程已终止,正等待父进程读取其终止信

息)。

*
出错立即返回(如果它没有任何子进程)。

这两个函数的区别是:

*
如果父进程的所有子进程都还在运行,调用wait将使父进程阻塞,而调用waitpid时如果在options参数中指定WNOHANG可以使父进程不阻塞而立即返回0。

* wait等待第一个终止的子进程,而waitpid可以通过pid参数指定等待哪一个子进程。

可见,调用wait和waitpid不仅可以获得子进程的终止信息,还可以使父进程阻塞等待子进

程终止,起到进程间同步的作用。如果参数status不是空指针,则子进程的终止信息通过

这个参数传出,如果只是为了同步而不关心子进程的终止信息,可以将status参数指定为

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);

}

}

时间: 2024-08-10 19:17:05

6进程原语:wait()和waitpid()函数的相关文章

UNIX环境编程学习笔记(21)——进程管理之获取进程终止状态的 wait 和 waitpid 函数

lienhua342014-10-12 当一个进程正常或者异常终止时,内核就向其父进程发送 SIGCHLD信号.父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用的函数(信号处理程序).对于这种信号的系统默认动作是忽略它. 在文档“进程控制三部曲”中,我们讲的第三部曲是使用 wait 函数来获取终止子进程的终止状态.那么,有几个问题我们这里需要详细的学习一下. 1. 父进程一定能够获取到子进程的终止状态吗?如果子进程在父进程调用 wait 函数前就终止了,怎么办? 2. 如果父进程没有获

UNIX高级环境编程(9)进程控制(Process Control)- fork,vfork,僵尸进程,wait和waitpid

本章包含内容有: 创建新进程 程序执行(program execution) 进程终止(process termination) 进程的各种ID ? 1 进程标识符(Process Identifiers) 每个进程都有一个唯一的标识符,进程ID(process ID). 进程的ID是可重用的,如果一个进程被终止,那么它的进程ID会被系统回收,但是会延迟使用,防止该进程ID标识的新进程被误认为是以前的进程. 三个特殊ID的进程: Process ID 0:调度者进程,内核进程. Process

UNIX多进程 - 销毁僵尸进程 - wait()和waitpid()函数

#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *statusPtr, int options); 现在要知道调用wait或waitpid的进程可能会发生什么情况: 如果其所有子进程都在运行,则阻塞. 如果一个子进程已经终止,正在等待的父进程获取到终止状态,则取得该子进程的终止状态立即返回. 如果他没有任何子进程,则立即出错返回. 如

进程控制(七)---wait 和 waitpid 函数详解

进程的终止可以分为异常终止和正常终止. 当进程是正常终止的时候,子进程会通过 exit 函数向父进程传递终止状态: 当进程是异常终止的时候,内核(而不是进程)会传递给父进程一个信号编号值. 所以说无论子进程是正常终止还是异常终止,父进程都可以通过 wait 或者 waitpid 函数来获取到子进程的终止状态,通过参数 status. 无论子进程是正常终止还是异常终止 或者 子进程暂停了,内核都会向父进程发送一个 SIGCHLD 信号,但是父进程对于此信号的默认动作是忽略.当然我们也可以捕捉该信号

进程原语

linux C/C++:进程原语 1. 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础. 2. 进程环境 在libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时要用extern声明.用以下代码可以查看当前进程的所有环境变量的信息. #include <stdio.h> int main(void) { extern char **environ; int i; f

详解wait和waitpid函数

#include <sys/types.h> /* 提供类型pid_t的定义 */ #include <sys/wait.h> pid_t wait(int *status) 进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回:如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止. 参数status用来保存被收集进程退出时

linux 进程等待 wait 、 waitpid

waitpid() 与 wait() 功能相似,都是用户主进程等待子进程结束或中断. 可用于进程之间的同步 wait 函数原型 pid_t wait(int *status); 函数说明 wait() 会临时停止眼下进程的运行,直到有信号来到或子进程结束.假设在调用wait() 时子进程已经结束,则 wait() 会立即返回子进程结束状态值.子进程的结束状态值会由參数 status 返回,而子进程的进程识别码也会一块返回.假设不在意结束状态值,则參数ststus能够设为 NULL.子进程的结束状

waitpid 函数详解

关于Linux中waitpid函数的一些使用说明: #include<sys/types.h> #include<sys/wait.h> 定义函数 pid_t waitpid(pid_t pid,int * status,int options); waitpid函数有三个参数:pid和指向返回状态所在单元的指针和一个用来指定可选项的标识符.如果pid为-1 ,waitpid就等待任何一个子进程,如果pid>0 j就是等待pid指定的那个进程结束,参数pid还存在另外的两种可

进程控制(十二)---system函数

system函数是用来在进程中执行 shell 命令的.注意其实 exec 族函数其实也可以用来在进程中执行 shell 命令,但是这两个函数实现执行 shell 命令的原理是完全不同的. system函数相当于是 fork->exec->wait 这样的一个过程,也就是说system函数会调用fork函数来创建一个子进程,然后在子进程中去执行 shell命令,不影响父进程的执行. 而直接利用 exec 族函数来执行 shell命令是将 shell命令的代码段.数据段直接覆盖掉本进程原来的代码