子进程的终止处理

2014-08-05 06:38:49   最后更新: 2014-08-05 06:38:49   访问数量:849




当一个进程正常或异常终止时,内核就向父进程发送SIGCHLD信号,因为子进程终止是个异步事件,可以在父进程运行的任何时候发生,所以这种信号也是内核向父进程发的异步通知,父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数(即信号处理程序),对于这种信号,系统的默认动作是忽略他。

pid_t wait (int * status);

定义于 sys/wait.h头文件中,若成功则返回进程ID,若出错返回-1。

如果参数status不为空,则进程终止状态被保存于其中。

依据传统,返回的整形状态字是由实现定义的,其中有些位表示退出状态(正常返回),其他位表示信号编号(异常返回),有一位表示是否产生了一个core文件等。

终止状态是定义在 sys/wait.h中的各个宏,有四可互斥的宏可以用来取得进程终止的原因。

  • WIFEXITED          正常返回时为真,可以执行宏函数WEXITSTATUS获取子进程传送给exit、_exit或_Exit的参数的低8位
  • WIFSIGNALED        异常返回时为真,可以执行宏函数WTERMSIG取得子进程终止的信号编号,另外,对于一些实现,定义有宏WCOREDUMP宏,若以经昌盛终止进程的core文件,则为真
  • WIFSTOPPED         若为当前暂停子进程的返回的状态,则为真,可执行WSTOPSIG取得使子进程暂停的信号编号
  • WIFCONTINUED       若在作业控制暂停后已经继续的子进程返回了状态,则为真,仅用于waitpid
/* * file: wait.c * author: 龙泉居士 * date: 2012-09-13 10:35 */ #include "../apue.2e/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)); } int main () { pid_t pid; int status; if ((pid = fork())<0) err_sys ("fork error"); else if (pid == 0) exit (7); if (wait(&status) != pid) err_sys ("wait error"); pr_exit (status); if ((pid = fork())<0) err_sys ("fork error"); else if (pid == 0) abort(); if (wait(&status) != pid) err_sys ("wait error"); pr_exit (status); if ((pid = fork())<0) err_sys ("fork error"); else if (pid == 0) status /= 0; if (wait(&status) != pid) err_sys ("wait error"); pr_exit (status); exit (0); }

 

运行结果如下:

normaltermination, exit status = 7

abnormaltermination, signal number = 6

abnormaltermination, signal number = 8

 

但是,6和8究竟指的是什么,并没有一种可移植的方法去说明,我们需要去查看signal.h头文件才能知道对应的宏的含义

 

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

 

定义于 sys/wait.h头文件中,若成功则返回进程ID,0,若出错返回-1。

 

waitpid提供了wait更多的功能,基本用法于返回值与wait相同

 

1、pid参数

对于有多个子进程的父进程,只要有一个子进程终止,父进程中的wait函数就会返回,如果要等待特定的子进程,那就要不断的调用wait函数等待,POSIX定义了waitpid提供了等待特定子进程的功能及其他功能:waitpid的pid参数的作用:

  • pid== -1    等待任一子进程,wait的功能与此相同
  • pid> 0      等待进程ID为pid的子进程
  • pid== 0     等待组ID等于调用进程组ID的任一子进程
  • pid< -1     等待组ID等于-pid的任一子进程

waitpid函数返回终止子进程的进程ID,并将该子进程的终止状态存放在由status指针指向的空间中,如果指定的进程或进程组不存在,或者pid指定的进程不是调用进程的子进程,则调用失败返回-1。

 

2、options参数

当options参数为0时,与wait功能相同,不提供额外功能,如果为下列常量按位或则提供更多功能:

  • WCONTINUED      若实现支持作业控制,那么由pid指定的任一子进程在暂停后已经继续,但状态尚未报告,则返回状态
  • WNOHANG         若由pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时返回0
  • WUNTRACED       若实现支持作业控制,而pid指定的任一子进程已经暂停,且其状态尚未报告,则返回其状态

 

3、与wait的区别

waitpid提供了三个wait所没有的功能

  1. waitpid可以等待一个特定的进程,而wait则返回任一终止子进程的状态
  2. waitpid可以使父进程不进入阻塞状态
  3. waitpid支持作业控制

 

waitid 函数类似于 waitpid,但是提供了更多的灵活性

int waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options);

 

定义于 <sys/wait.h> 头文件中,调用成功返回0,否则返回-1

 

1、idtype 常量

  • P_PID       等待一个特定的进程:id参数包含要等待子进程的进程ID
  • P_PGID      等待一个特定进程组中的任一子进程:id参数包含要等待子进程的进程组ID
  • P_ALL       等待任一子进程,忽略id参数

 

3、infop 参数

infop 参数是指向 siginfo 结构的指针,该结构包含了有关引起子进程状态改变的生成信号的详细信息

需要注意的是,UNIX 系统中只有 solaris 支持该函数

 

2、options 常量

  • WCONTINUED     等待一个进程,他以前曾被暂停,此后又已继续,但其状态尚未报告
  • WEXITED        等待已退出的进程
  • WNOHANG        如果没有可用的子进程退出状态,立即返回而不是阻塞
  • WNOWAIT        不破坏子进程退出状态,该子进程退出状态可由后续的 wait、waitid 或 waitpid 调用取得
  • WSTOPPED       等待一个进程,他已经被暂停,但是其状态尚未报告

 

大多数 UNIX 系统实现提供了另外两个函数 wait3 和 wait4,他们的功能比 POSIX.1 函数 wait、waitpid、waitid 多一个,因为他们有一个附加参数 rusage,该参数要求内核返回由终止进程及其所有子进程使用的资源汇总

pid_t wait3 (int *statloc, int options, struct rusage *rusage); pid_t wait4 (pid_t pid, int *statloc, int options, struct rusage *rusage);

 

调用成功返回进程ID,否则返回-1

 

资源统计信息包含用户 CPU 时间总量、系统 CPU 时间总量、页面出错次数、接收到信号的次数等,因此需要引用 <sys/types.h>、<sys/wait.h>、<sys/time.h>、<resource.h> 等头文件

 






读书笔记      技术帖      linux      unix      龙潭书斋      apue      unix环境高级编程      进程     


京ICP备15018585号