wait获取子进程退出状态 WIFEXITED和WIFSIGNALED用法

本文介绍如何使用wait函数及宏函数组合来检测子进程的状态,包括正常退出、被信号终止等情况,并提供了一个具体的C语言示例程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以使用wait函数传出参数status来保存进程的退出状态


常用宏函数分为日如下几组:
1、 WIFEXITED(status) 若此值为非0 表明进程正常结束。
若上宏为真,此时可通过WEXITSTATUS(status)获取进程退出状态(exit时参数)
示例:

        if(WIFEXITED(status)){
            printf("退出值为 %d\n", WEXITSTATUS(status));
        }

2、 WIFSIGNALED(status)为非0 表明进程异常终止。
若上宏为真,此时可通过WTERMSIG(status)获取使得进程退出的信号编号
用法示例:

    if(WIFSIGNALED(status)){
        printf("使得进程终止的信号编号: %d\n",WTERMSIG(status));   
    }

3、 WIFSTOPPED(status)为非0 表明进程处于暂停状态
若上宏为真,此时可通过WSTOPSIG(status)获取使得进程暂停的信号编号
4、 WIFCONTINUED(status) 非0表示暂停后已经继续运行。


WIFEXITED和WIFSIGNALED用法完整程序:

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

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

    pid = fork();
    if(pid == 0){               //子进程
        printf("child --- my parent is %d\n", getppid());
        sleep(30);              //子进程睡眠30秒
        printf("child is die\n");
     }else if(pid>0){           //父进程
        wpid = wait(&status);   //等待回收子进程
        if(wpid == -1){
            perror("wait error:");
            exit(1);
        }
        //正常退出判断
        if(WIFEXITED(status)){
            printf("child exit with %d\n", WEXITSTATUS(status));
        }

        //因为某种信号中断获取状态
        if(WIFSIGNALED(status)){
            printf("child killed by %d\n", WTERMSIG(status));
        }

        while(1)
        {
            printf("parent pid = %d, sonpid = %d\n", getpid(), pid);
            sleep(1);
        }
        } else {
            perror("for error");
            exit(1);
        }

    return 0;
}

测试程序
编译程序:

yu@ubuntu:~/cplusplus/wait进程控制$ gcc getstatus.c -o getstatus.out

1、首先测试WIFEXITED正常退出情况,执行:

yu@ubuntu:~/cplusplus/wait进程控制$ ./getstatus.out 
child --- my parent is 6408
child is die
child exit with 0
parent pid = 6408, sonpid = 6409
parent pid = 6408, sonpid = 6409
parent pid = 6408, sonpid = 6409
parent pid = 6408, sonpid = 6409
....

2、测试WIFSIGNALED信号终止,执行(sleep(300)便于测试):

yu@ubuntu:~/cplusplus/wait进程控制$ ./getstatus.out 
child --- my parent is 6418

此时另开一终端,查看进程,kill命令终止子进程:

yu@ubuntu:~/cplusplus/Process$ ps aux | grep getstatus.out
yu         6437  0.0  0.0   4224   784 pts/18   S+   21:58   0:00 ./getstatus.out
yu         6438  0.0  0.0   4356    84 pts/18   S+   21:58   0:00 ./getstatus.out
yu         6442  0.0  0.0  21292   976 pts/4    S+   21:58   0:00 grep --color=auto getstatus.out

yu@ubuntu:~/cplusplus/Process$ kill 6438

此时子进程异常终止,getstatus.out 程序输出信息:

yu@ubuntu:~/cplusplus/wait进程控制$ ./getstatus.out 
child --- my parent is 6437
child killed by 15
parent pid = 6437, sonpid = 6438
parent pid = 6437, sonpid = 6438
parent pid = 6437, sonpid = 6438
parent pid = 6437, sonpid = 6438
...

如上所知,使得进程终止的信号编号为15,通过 kill –l可知15号信号为SIGTERM:

yu@ubuntu:~/cplusplus/wait进程控制$ 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    
任务描述 通过上一个实训的学习,我们学会了使用forkvfork创建子进程,在使用fork创建子进程的时候,子进程父进程的执行顺序是无法预知的。本关我们将介绍如何使得fork创建出来的子进程先执行,随后父进程再执行。 本关任务:学会在多进程中,学会进程的等待处理。 相关知识 在上一个实训的学习,我们知道使用fork可以创建一个进程,并且创建的子进程其执行顺序可能在父进程前,也可能在父进程后。因此,这是由于fork创建的进程是由操作系统调度器来决定执行顺序的。如果,当子进程在父进程前结束,则内核会把子进程设置为一个特殊的状态。这种状态的进程叫做僵死进程(zombie)。尽管子进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存。但是仍然保留了一些信息(如进程号pid退出状态 运行时间等)。只有父进程获取子进程的这些信息后,子进程才会彻底的被销毁,否则一直保持僵死状态。如果系统中产生大量的僵尸进程,将导致系统没有可用的进程号,从而导致系统不能创建新的进程。 Linux处理僵死进程的方法之一是使用进程等待的系统调用waitwaitpid来使得父进程获取子进程的终止信息。 wait函数waitpid函数是系统调用函数,因此使用man 2 函数名来查看其使用方法。 wait函数使用方法 wait函数的具体的说明如下: 需要的头文件如下: #include <sys/types.h> #include <sys/wait.h> wait函数格式如下: pid_t wait(int *status); 参数说明: 参数status是一个整数指针,当子进程结束时,将子进程的结束状态字存放在该指针指向的缓存区。利用这个状态字,需要时可以使用一些由 Linux 系统定义的宏来了解子程序结束的原因。这些宏的定义与作用如下: 宏定义 含义 WIFEXITED(status) 子进程正常结束时,返回值为真(非零值) WEXITSTATUS(status) 当WIFEXITED为真时,此宏才可以使用。返回进程退出的代码 WIFSIGNALED(status) 子进程接收到信号结束时,返回值为真。但如果进程接收到信号时调用exit函数结束,则返回值为假 WTERMSIG(status) 当 WIFSIGNALED 为真时,将获得终止该进程的信号 函数返回值说明: 调用成功时,返回值为被置于等待状态的进程的 pid;执行失败返回-1并设置错误代码errno。 案例演示1: 编写一个程序,使用fork函数与wait函数结合创建一个新进程,使得新创建的子进程在父进程前执行。详细代码如下所示: #include <stdio.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main() { pid_t pid; pid = fork(); if(pid == -1) { //创建进程失败 printf("创建进程失败(%s)!\n", strerror(errno)); return -1; } else if(pid == 0) { //子进程 sleep(2); printf("This is child process\n"); exit(1); } else { //父进程 int status; if(wait(&status) != -1) { if(WIFEXITED(status)) printf("子进程正常退出退出代码:%d\n", WEXITSTATUS(status)); } printf("This is parent process\n"); exit(0); } } 将以上代码保存为waitProcess.c文件,编译执行。可以看到执行waitProcess程序后,尽管子进程使用sleep睡眠了2秒,还是子进程先执行,然后父进程才执行。这就是wait的作用,使得父进程一直等待子进程执行结束后才继续执行。 waitpid函数使用方法 waitpid函数的具体的说明如下: 需要的头文件如下:
最新发布
04-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值