自研操作系统中子进程相关宏WIFEXITED & WEXITSTATUS使用

一、宏介绍

以下三组宏在fork调用过程中一般成对使用:

WIFEXITED + WEXITSTATUS

WIFSIGNALED + WTERMSIG

WIFSTOPPED + WSTOPSIG

第一组:WIFEXITED + WEXITSTATUS

1、WIFEXITED是一个宏,用来检查子进程是否正常退出。

函数原型:

#include <sys/wait.h>

Int WIFEXITED(int status)

参数:status:子进程退出的状态码,一般由wait()/waitpid()函数返回。

返回值:子进程正常退出(执行exit()退出或者在main函数中返回为正常退出)返回值为非0(一般为1);子进程因为接收到信号而异常中止,则返回0。

2、WEXITSTATUS 是一个宏,用于从子进程的退出状态中提取退出码(exit code)。

函数原型:

#include <sys/wait.h>

Int WEXITSTATUS (int status)

参数:status:子进程退出的状态码,一般由wait()/waitpid()函数返回。

返回值:返回子进程的退出状态码,介于0~255之间的整数值,表示子进程退出时传递给exit()函数的参数值。子进程正常退出,且WEXITSTATUS (status)返回0,代表子进程成功执行,子进程正常退出,WEXITSTATUS(status) 返回非 0,则表示子进程退出时出现了错误。

使用场景:

调用fork()新建子进程后,调用wait()/waitpid()父进程等待子进程结束,wait()/waitpid()会返回子进程的ID和状态码(status)。使用WIFEXITED检查状态码,确定子进程是否正常退出。如果WIFEXITED(status)为真(即正常退出),则可以使用WEXITSTATUS (status)获取子进程的退出码。

C示例代码:

#include <stdio.h>

#include <stdlib.h>

#include <sys/wait.h>

#include <unistd.h>

int main() {

    pid_t pid = fork();

    if (pid < 0) {

        perror("fork failed");

        exit(EXIT_FAILURE);

    }

    if (pid == 0) {

        // 子进程

        printf("这是子进程\n");

        exit(0); // 正常退出,状态码为0

    } else {

        // 父进程

        int status;

        waitpid(pid, &status, 0);

        if (WIFEXITED(status)) {

            int exit_status = WEXITSTATUS(status);

            printf("子进程正常退出,退出状态码: %d\n", exit_status);

        } else if (WIFSIGNALED(status)) {

            int signal_number = WTERMSIG(status);

            printf("子进程因信号终止,信号编号: %d\n", signal_number);

        } else if (WIFSTOPPED(status)) {

            int stop_signal = WSTOPSIG(status);

            printf("子进程因信号停止,信号编号: %d\n", stop_signal);

        } else if (WIFCONTINUED(status)) {

            printf("子进程已继续运行\n");

        }

    }

    return 0;

}

第二组:WIFSIGNALED + WTERMSIG

WIFSIGNALED 是一个宏,判断子进程退出是否因为信号而中止,因信号而中止,会返回非0值。WTERMSIG(status)可以获取导致子进程退出的信号的编号。示例见第一组示例。

第三组:WIFSTOPPED + WSTOPSIG

WIFSTOPPED是一个宏,用于判断子进程是否因信号而被停止,如果子进程因为信号被暂停,则返回非0值,否则返回0;

WSTOPSIG宏,获取导致子进程停止的信号的编号。

示例见第一组示例。

二、linux中LTP测试用例使用WEXITSTATUS分析

int main(void)

{

    char mqname[NAMESIZE], msgrv[BUFFER];

    const char *msgptr = "test message ";

    mqd_t mqdes;

    int prio = 1;

    int pid;

    struct timespec ts;

    struct mq_attr attr;

    int unresolved = 0, failure = 0;

    sprintf(mqname, "/" FUNCTION "_" TEST "_%d", getpid());

    attr.mq_msgsize = BUFFER;

    attr.mq_maxmsg = BUFFER;

    mqdes = mq_open(mqname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr);

    if (mqdes == (mqd_t) - 1) {

        perror(ERROR_PREFIX "mq_open");

        unresolved = 1;

    }

    pid = fork();

    if (pid != 0) {

        /* Parent process */

        int status;

        ts.tv_sec = TIME_T_MAX;

        ts.tv_nsec = 0;

        if (mq_timedreceive(mqdes, msgrv, BUFFER, NULL, &ts) > 0) {

            wait(&status);

            if (WEXITSTATUS(status)) {

                printf("mq_send error\n");

                unresolved = 1;

            }

        } else {

            printf("mq_timedreceive didn't block on waiting\n");

            wait(NULL); /* wait for child to exit */

            perror(ERROR_PREFIX "mq_timedreceive");

            failure = 1;

        }

        if (mq_close(mqdes) != 0) {

            perror(ERROR_PREFIX "mq_close");

            unresolved = 1;

        }

        if (mq_unlink(mqname) != 0) {

            perror(ERROR_PREFIX "mq_unlink");

            unresolved = 1;

        }

        if (failure == 1) {

            printf("Test FAILED\n");

            return PTS_FAIL;

        }

        if (unresolved == 1) {

            printf("Test UNRESOLVED\n");

            return PTS_UNRESOLVED;

        }

        printf("Test PASSED\n");

        return PTS_PASS;

    } else {

        /*  Child Process */

        sleep(2);   /* sleep 2 seconds,

                   assume that parent will block on waiting then */

        if (mq_send(mqdes, msgptr, strlen(msgptr), prio) == -1) {

            perror(ERROR_PREFIX "mq_send");

            return PTS_UNRESOLVED;

        }

        return 0;

    }

    return PTS_UNRESOLVED;

}

WEXITSTATUS(status)返回值为0则执行成功,返回其1~255,则代表子进程退出时的错误码(只有在正常退出时解析这个错误码才有意义)

怎么没有先使用WIFEXITED 判断是否正常退出呢?

在使用 waitpid() 函数等待子进程时,首先使用 WIFEXITED(status) 判断子进程是否正常退出是必要的,因为 WIFEXITED() 用于检查子进程是否通过正常的退出状态(即调用 exit() 或返回)。如果 WIFEXITED(status) 返回真,则可以使用 WEXITSTATUS(status) 宏来获取子进程的退出状态码。

如果不先检查 WIFEXITED(status),直接使用 WEXITSTATUS(status) 可能会导致未定义行为,因为 WEXITSTATUS(status) 仅在子进程正常退出的情况下有效。如果子进程是由于信号终止的(例如,调用了 abort() 或收到了未处理的信号),则 WIFEXITED(status) 会返回假,这时使用 WEXITSTATUS(status) 是不可靠的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值