你一直问我的心在不在:进程控制之exit和waitpid(wait)函数 - 缘起宇轩阁 - CSDN博客

来源:百度文库 编辑:偶看新闻 时间:2024/05/10 16:59:38
1. exit函数我们知道,进程有五种正常终止:1). 从main函数执行return语句,如同调用exit一样。2). 调用exit。此函数有ISO C定义,其操作包括调用各中终止处理程序,然后关闭所有标准I/O流等。因为ISO C并不处理文件描述符,多进程以及作业控制,所以这一定义对UNIX系统是不完整的。3). 调用_exit或_Exit。ISO C定义_Exit,其目的是为进程提高一种无需运行终止处理程序或信号处理程序而终止的方法。在UNIX系统中,_exit或_Exit是同义的,并不冲洗标准I/O流。_exit由exit调用。4). 进程的最后一个线程在启动例程中执行返回语句。但是,该线程的返回值不会用作进程的返回值。而该进程以终止状态0返回。5). 最后一个线程调用pthead_exit,而该进程以终止状态0返回。三种异常终止1). 调用abort2). 接到一个信号并终止3). 最后一个线程对取消请求做出响应。不管进程如何终止,最后都会执行内核同一段代码。这段代码为相应进程关闭所有打开描述符,释放它使用的存储器等。在任意一种情况下,终止进程的父进程都能用wait或waitpid函数取得其终止状态。在最后调用_exit时,内核将退出状态转换为终止状态(termination status)。如果父进程在子进程前终止,将如何?对于父进程已经终止的所有进程,它们的父进程都改变为init进程。我们称这些进程由init领养。在一个进程终止时,内核逐个坚持所有活动进程,以判断它是否是正要终止进程的子进程,如果是,则将该进程的父进程ID改为1。只要init的子进程终止,init会调用一个wait函数获得其终止状态。如果子进程在父进程之前终止,将如何?内核为每个终止子进程保存了一定量的信息,所以当终止进程的父进程调用wait或waitpid函数时,可以得到这些信息。在UINX术语中,一个已经终止、但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍占有的资源)的进程被称为僵死进程(zombie)。ps命令将僵死进程的状态打印为Z。2. wait和waitpid函数当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。父进程可以忽略该信号,或调用信号处理函数。调用wait或waitpid的进程,会发生以下情况:1). 如果其所有子进程都在运行,则该进程阻塞2). 如果一个子进程已经终止,正等待父进程获取其终止状态,则取得该进程的终止状态立即返回3). 如果它没有任何子进程,则立即出错返回。#include #pid_t wait (int * statloc);#pid_t waitpid (pid_t pid, int * statloc, int optins);2.1. wait和waitpid函数区别区别如下1). 在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞。2). waitpid并不等待在其调用之后的第一个终止子进程,它有若干个选项,可以控制它所等到的进程。3). 对于wait,其唯一的出错是调用进程没有子进程;对于waitpid,入股指定的进程或进程组不存在,或者参数pid指定的进程不是调用进程的子进程都可能出错。4). Waitpid提供了wait没有的三个功能:一是waitpid可等待一个特定的进程;二是waitpid提供了一个waitpid的非阻塞版本;三是waitpid支持作业控制。   依据传统,这两个函数返回的整型状态字是由实现定义的。其中某些位表示退出状态(正常返回),其它位表示信号编号(异常返回)。下表有四个互斥的宏。WIFEXITED(status)
 若为正常终止子进程返回的状态,则为真。对于这种情况可以执行WEXITSTATUS(status),取子进程传送给exit、_exit或_Exit参数的低8位。
 
WIFSIGNALED(status)
 若为异常终止子进程返回的状态,则为真(接到一个不捕捉的信号)。对于这种情况可以执行WTERMSIG(status),取得子进程终止的信号编号。
 
WIFSTOPPED(status)
 若为当前暂停子进程返回的状态,则为真。对于这种情况可以执行WSTOPSIG(status),取得子进程暂停的信号编号。
 
WIFCONTINUED(status)
 若在作业控制暂停后已经继续的子进程返回的状态,则为真。仅用于waitpid。
 
对于waitpid函数中的pid参数的作用见下表:pid == -1
 等待任一子进程。
 
pid > 0
 等待其进程ID与pid相等的子进程
 
pid == 0
 等待其组ID等于调用进程组ID的任一的子进程
 
pid < -1
 等待其组ID等于pid绝对值的任一的子进程
 
对于waitpid函数中的options参数的作用见下表:WCONTINUED
 若实现支持作业控制,那么由pid指定的任一子进程在暂停后已经继续,但是状态没报告,则返回其状态
 
WNOHANG
 若由pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时返回值为0
 
WUNTRACED
 若实现支持作业控制,那么由pid指定的任一子进程已经处于暂停状态并没报告过,则返回其状态
 
2.2. fork两次可以避免僵死进程实例如下:
view plaincopy to clipboardprint?
#include  
#include  
#include  
#include  
#include  
#include  
#include   
 
int main ()  
{  
    pid_t pid;  
      
    if((pid_t = fork()) < 0)  
    {  
        printf("fork error\n");  
    }  
    else if (pid == 0)  
    {  
        // 父进程A的子进程B  
        if((pid_t = fork()) < 0)  
        {  
            printf("fork error\n");  
        }  
        else if (pid > 0)  
        {  
            // 父进程A的子进程B退出  
            exit(0);  
        }  
 
        // 子进程B的子进程C继续  
        sleep(2);  
        printf("second child, parent pid = %d\n", getpid());  
        // 子进程B的子进程C退出  
        exit(0);  
    }  
 
    // 父进程A阻塞  
    if(waitpid(pid, NULL, 0) != pid)  
    {  
        printf("waitpid error\n");  
    }  
 
    //  
    exit(0);  
}   本文来自CSDN博客,转载请标明出处:file:///D:/我的文档/Linux/Process/进程控制之exit和waitpid(wait)函数%20-%20缘起宇轩阁%20-%20CSDN博客.mht