06_父进程wait和waitpid_01

1waitwaitpid出现的原因
SIGCHLD
   当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止)
   子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程,它只保留最小的一些内核数据结构,以便父进程查询子进程的退出状态。
父进程查询子进程的退出状态可以用wait/waitpid函数
2waitwaitpid函数用法
Wait
   头文件<sys/types.h>和<sys/wait.h>
   函数功能:当我们用fork启动一个进程时,子进程就有了自己的生命,并将独立地运行。有时,我们需要知道某个子进程是否已经结束了,我们可以通过wait安排父进程在子进程结束之后。
   函数原型
   pid_t wait(int *status)
   函数参数
   status:该参数可以获得你等待子进程的信息
   返回值:
   成功等待子进程函数返回等待子进程的ID
   wait系统调用会使父进程暂停执行,直到它的一个子进程结束为止。
   返回的是子进程的PID,它通常是结束的子进程
   状态信息允许父进程判定子进程的退出状态,即从子进程的main函数返回的值或子进程中exit语句的退出码。
   如果status不是一个空指针,状态信息将被写入它指向的位置
Wait获取status后检测处理
宏定义 描述
WIFEXITED(status)   如果子进程正常结束,返回一个非零值
WEXITSTATUS(status) 如果WIFEXITED非零,返回子进程退出码
WIFSIGNALED(status) 子进程因为捕获信号而终止,返回非零值
WTERMSIG(status)    如果WIFSIGNALED非零,返回信号代码
WIFSTOPPED(status)  如果子进程被暂停,返回一个非零值
WSTOPSIG(status)    如果WIFSTOPPED非零,返回一个信号代码

Waitpid
函数功能:用来等待某个特定进程的结束
函数原型:
     pid_t waitpid(pid_t pid, int *status,int options)
 参数:
   status:如果不是空,会把状态信息写到它指向的位置
options:允许改变waitpid的行为,最有用的一个选项是WNOHANG,它的作用是防止waitpid把调用者的执行挂起
   返回值:如果成功返回等待子进程的ID,失败返回-1
对于waitpid的p I d参数的解释与其值有关:
   pid == -1 等待任一子进程。于是在这一功能方面waitpidwait等效。
   pid > 0 等待其进程I D与p I d相等的子进程。
   pid == 0 等待其组I D等于调用进程的组I D的任一子进程。换句话说是与调用者进程同在一个组的进程。
   pid < -1 等待其组I D等于p I d的绝对值的任一子进程。
3wait pk waitpid
Wait和waitpid区别和联系
   在一个子进程终止前, wait 使其调用者阻塞,而waitpid 有一选择项,可使调用者不阻塞。
   waitpid并不等待第一个终止的子进程—它有若干个选择项,可以控制它所等待的特定进程。
   实际上wait函数是waitpid函数的一个特例。
僵尸进程
   当一个子进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行或者父进程调用了wait才告终止。
进程表中代表子进程的数据项是不会立刻释放的,虽然不再活跃了,可子进程还停留在系统里,因为它的退出码还需要保存起来以备父进程中后续的wait调用使用。它将称为一个“僵进程”
如何避免僵尸进程
   调用wait或者waitpid函数查询子进程退出状态,此方法父进程会被挂起。
   如果不想让父进程挂起,可以在父进程中加入一条语句:signal(SIGCHLD,SIG_IGN);表示父进程忽略SIGCHLD信号,该信号是子进程退出的时候向父进程发送的。


hzmct@U-64:/study$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    
Man 7 signal 查找有什么信号可以使应用程序暂停 
Standard signals
       Linux supports the standard signals listed below.  Several  signal  numbers  are
       architecture-dependent, as indicated in the "Value" column.  (Where three values
       are given, the first one is usually valid for alpha and sparc,  the  middle  one
       for  x86, arm, and most other architectures, and the last one for mips.  (Values
       for parisc are not shown; see the Linux kernel source for  signal  numbering  on
       that  architecture.)   A  - denotes that a signal is absent on the corresponding
       architecture.)

       First the signals described in the original POSIX.1-1990 standard.

       Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
       SIGINT        2       Term    Interrupt from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
       SIGSEGV      11       Core    Invalid memory reference
       SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                     readers
       SIGALRM      14       Term    Timer signal from alarm(2)
       SIGTERM      15       Term    Termination signal
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
       SIGCONT   19,18,25    Cont    Continue if stopped
       SIGSTOP   17,19,23    Stop    Stop process
       SIGTSTP   18,20,24    Stop    Stop typed at terminal
       SIGTTIN   21,21,26    Stop    Terminal input for background process
       SIGTTOU   22,22,27    Stop    Terminal output for background process

       The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

       Next the signals not in the POSIX.1-1990 standard but  described  in  SUSv2  and
       POSIX.1-2001.

       Signal       Value     Action   Comment
       ────────────────────────────────────────────────────────────────────
       SIGBUS      10,7,10     Core    Bus error (bad memory access)
       SIGPOLL                 Term    Pollable event (Sys V).
                                       Synonym for SIGIO
       SIGPROF     27,27,29    Term    Profiling timer expired
       SIGSYS      12,31,12    Core    Bad argument to routine (SVr4)
       SIGTRAP        5        Core    Trace/breakpoint trap
       SIGURG      16,23,21    Ign     Urgent condition on socket (4.2BSD)
       SIGVTALRM   26,26,28    Term    Virtual alarm clock (4.2BSD)
       SIGXCPU     24,24,30    Core    CPU time limit exceeded (4.2BSD)
       SIGXFSZ     25,25,31    Core    File size limit exceeded (4.2BSD)

#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>

/*
    wait()函数的使用
*/

void TestFunc(int loopnum)
{
    printf("loopnum:%d\n", loopnum);    
}

int main(void )
{   
    int procnum = 10;
    int loopnum = 100;
    int ret;
    int i = 0, j = 0;
    printf("please enter you procNum : \n");
    scanf("%d", &procnum);

    printf("please enter you loopnum :\n");
    scanf("%d", &loopnum);
    pid_t pid;
    for (i=0; i<procnum; i++)
    {
        pid = fork();
        if (pid == 0)
        {
            for (j=0; j<loopnum; j ++)
            {
                TestFunc(j);
            }
            sleep(2000);
            //exit(0);//使子进程退出,非常重要
            exit(10);
        }
    }
    //wait系统调用会使父进程暂停执行,直到它的一个子进程结束为止
    while(1){
        ret = wait(NULL);//让父进程阻塞的过程中有可能被别的信号中断 ,传NULL的妙用
        if(ret == -1){
            if(errno == EINTR){//EINTR错误(被中断的系统调用)。
                    perror("信号中断");
                    continue;
                }
            }
            break;
    }
    //wait(NULL);

    printf("hello...\n");
    return 0;
}
#include <sys/types.h>
#include <unistd.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
/*

    子进程退出状态的使用

    关闭或阻止core文件生成: $ulimit -c 0
    打开core文件生成: $ulimit -c unlimited
    检查core文件的选项是否打开: $ulimit -a

*/

void pr_exit(int status)
{
    if( WIFEXITED(status)){
            printf("子进程正常终止,退出码 exit status= %d\n",  WEXITSTATUS(status));
    }else if(   WIFSIGNALED(status)){
            printf("子进程异常终止,退出码 signal number= %d%s\n",  WTERMSIG(status),
            #ifdef WCOREDUMP
                WCOREDUMP(status) ? "(core file generated)" : "");
            #else
                "");
            #endif

        }else if(   WIFSTOPPED(status)){
            printf("子进程 stopped,退出码 signal number= %d\n",  WSTOPSIG(status));
        }
}

int main(void )
{   
    pid_t pid;
    int status;

    if((pid = fork()) < 0){
        perror("fork error");
    }else   if (pid == 0){
        exit(7);//子进程正常退出
    }
    if(wait(&status) != pid){//wait返回的是子进程的PID,它通常是结束的子进程
        perror("wait error");
    }
    pr_exit(status);
//----------------------------
    if((pid = fork()) < 0){
        perror("fork error");
    }else   if (pid == 0){
        abort();//子进程异常终止 SIGABRT 6
    }
    if(wait(&status) != pid){
        perror("wait error");
    }
    pr_exit(status);

//----------------------------
    if((pid = fork()) < 0){
        perror("fork error");
    }else   if (pid == 0){
        status /= 0;//子进程异常终止 SIGFPE 8
    }
    if(wait(&status) != pid){//wait返回的是子进程的PID,它通常是结束的子进程
        perror("wait error");
    }
    pr_exit(status);

    printf("hello...\n");
    exit(0);
}

猜你喜欢

转载自blog.csdn.net/WUZHU2017/article/details/81775550
今日推荐