unix中父进程如何获取子进程的终止状态

news2024/11/17 7:30:46

一、前言

本文将介绍在unix系统中,父进程如何获取子进程的终止状态。本文主要围绕如下函数展开:
1.wait
2.waitpid
3.waitid
4.wait3、wait4
在讨论这些函数前,先介绍一个进程从创建到释放子进程的过程。

二、子进程的创建以及终止

在unix系统中,一个进程可以通过fork()函数来创建一个新的进程。如果父进程先终止,那么子进程就会成为孤儿进程,然后被init进程收留,成为init进程的子进程。如果子进程先终止,那么内核就会向父进程发送一个SIGCHLD的信号,父进程默认忽略该信号。如果子进程终止后,父进程没有去获取子进程的终止状态,那么子进程就会在内存保存一段信息,成为僵死进程。
父进程通过wait族函数来获取子进程的终止状态。

三、wait族函数介绍

wait族函数的作用是获取子进程的终止状态。下面将详细介绍每个函数:

3.1 wait

#include <sys/wait.h> pid_t wait(int *status);
参数:用于存储子进程的退出状态,如果不关心状态,可以传入NULL 返回值:成功返回子进程的PID,出错返回0或-1
调用wait函数会有如下三种情况:
1.如果所有的子进程都在运行中,则父进程阻塞
2.如果一个子进程已经终止,正等待父进程获取其状态,则返回该子进程的PID
3.如果没有任何子进程,则立即报错返回

unix通过四个宏来获取子进程的退出状态,如下:

  1. WIFEXITED(status):用于判断子进程是否正常退出。如果是则返回真。
  2. WEXITSTATUS(status):获取正常退出的子进程的返回值。
  3. WIFSIGNALED(status):判断子进程是否因信号而终止。如果是则返回真。
  4. WTERMSIG(status):获取导致子进程终止的信号号码
  5. WIFSTOPPED(status):检查子进程是否被停止。

3.2 waitpid

waitpid的功能比wait更为丰富,它能指定等待某个特定的子进程结束,且能够选择是否阻塞。

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

pid_t waitpid(pid_t pid, int *status, int options);
参数:
pid:要等待的子进程的PID。如果是正数,则等待对应的子进程;如果是-1,则等待任意子进程;如果是0,则等待与调用进程同组的任意子进程。
status:用于存储子进程的退出状态
options:控制函数行为选项,比如WNOHANG(非阻塞等待)。

返回值:成功的话返回被等待的子进程PID,没有匹配的子进程返回0,错误返回-1

3.3 waitid

waitid的功能和waitpid类似,只不过在传入参数上有些许差异。

#include <sys/types.h>
#include <sys/wait.h>

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

参入参数:
idtype: 指定要等待的进程 ID 类型,可以是以下值之一: P_PID: 等待指定进程的终止。
P_PGID: 等待指定进程组的终止。
P_ALL: 等待所有子进程的终止。
id: 取决于 idtype 的值。它可以是某个特定进程的ID,或是某个进程组的 ID,或是 0(针对所有子进程)。
infop: 是一个指向 siginfo_t结构体的指针,用于接收有关终止子进程的状态信息。
options: 控制函数行为的选项,使用方式类似于waitpid

返回值:成功时返回0,出错返回-1

ps:需要注意的是WCONTINUE、WEXITED、WSTOPPED这三个参数之一必须在options中指定。

3.4 wait3、wait4

wait3和wait4和前面几个函数相比主要多了一个获取终止进程及其子进程所使用的系统资源的功能。

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <unistd.h>

pid_t wait3(int *status, int options, struct rusage *rusage);
参数:
status:用于返回子进程的退出状态
options:控制调用的行为
rusage:指向 struct rusage的指针,用于获取子进程的资源使用情况
返回值:成功返回被等待的子进程的PID,失败返回-1

========================================
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
wait4与wait3相比就增加了可以选择等待特定的子进程

struct rusage数据结构的定义如下:

#include <sys/resource.h>

struct rusage {
struct timeval ru_utime; // 用户 CPU 时间
struct timeval ru_stime; // 系统 CPU 时间
long ru_maxrss; // 最高常驻集大小(以 KB 为单位)
long ru_ixrss; // 增加的共享内存大小
long ru_idrss; // 增加的独占内存大小
long ru_isrss; // 增加的共享数据段大小
long ru_minflt; // 页面未命中数
long ru_majflt; // 页面错误数
long ru_nswap; // 交换区使用的次数
long ru_inblock; // 输入块数
long ru_oublock; // 输出块数
long ru_msgsnd; // 发送的消息数
long ru_msgrcv; // 接收的消息数
long ru_nsignals; // 发送的信号数
long ru_nvcsw; // 自愿上下文切换次数
long ru_nivcsw; // 非自愿上下文切换次数 };

四、参考代码

wait函数的参考代码如下:

/*************************************************************************
        > File Name: wait_test.c
        > Author: conbiao
        > Created Time: 2024年09月25日 星期三 11时14分36秒
 ************************************************************************/

/***********************************************************************
 *                             HEADER
 **********************************************************************/
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/resource.h>

/***********************************************************************
 *                              MACRO
 **********************************************************************/
#define WAIT3

/***********************************************************************
 *                          GLOBAL VARIABLE
 **********************************************************************/


/***********************************************************************
 *                       FUNCTION DESCRIPTION
 **********************************************************************/



/***********************************************************************
* FUNCTION NAME:
 ***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************/


/***********************************************************************
 *                                MAIN
 **********************************************************************/
int main(int argc, char *argv[])
{
    int ret = 0;

    pid_t pid;
    int status;
    pid_t p;

    pid = fork();
    if(pid < 0)
    {
        printf("fork fail!\n");
    }
    else if(pid == 0)
    {
        printf("This is child process!\n");
#ifdef SIGNAL_EXIT
        int x = 2 / 0;
#endif
        sleep(2);
    }
    else
    {
#ifdef WAIT
        if((p = wait(&status))!= pid)
        {
            printf("wait child error! pid: %d. p: %d \n",pid,p);
        }
        else
        {
            printf("This is father process,child process: %d\n",pid);
        }
#endif

#ifdef WAITPID
        if((p = waitpid(pid,&status,WNOHANG)) == pid)
        {
            printf("This is father process,child process: %d\n",pid);
        }
        else
        {
            printf("p: %d\n",p);
        }
#endif

#ifdef WAITID
        siginfo_t info;
        int res = waitid(P_PID,pid,&info,WEXITED);
        if(!res)
        {
            printf("This is father process,child process:%d\n",pid);
        }
        else
        {
            printf("waitid fail! res: %d\n",res);
        }
#endif

#ifdef WAIT3
        struct rusage rus;
        if(wait3(&status, 0 ,&rus) == pid)
        {
            printf("This is father process,pid: %d,systime: %ld.%06ld seconds\n",pid, \
                    (long)rus.ru_stime.tv_sec, (long)rus.ru_stime.tv_usec);
        }
        else
        {
            printf("wait3 fail!\n");
        }

#endif

        if(WIFEXITED(status))
        {
            printf("child process over nomally,exit code is: %d\n",WEXITSTATUS(status));
        }
        else if(WIFSIGNALED(status))
        {
            printf("child process over by receive signal,signal is: %d\n",WTERMSIG(status));
        }

    }

    return ret;
}

运行结果如下:
在这里插入图片描述

(4-1)

参考资料:

《UNIX环境高级编程(第3版) (史蒂文斯 (W.Richard Stevens) 拉戈(StephenA.Rago))(Z-Library)》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2173327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】单元测试【主线学习笔记】

文章目录 前言测试分类JUnit单元测试介绍编写单元测试方法的条件IDEA中简易使用JUnit 前言 Java是一门功能强大且广泛应用的编程语言&#xff0c;具有跨平台性和高效的执行速度&#xff0c;广受开发者喜爱。在接下来的学习过程中&#xff0c;我将记录学习过程中的基础语法、框架…

大联大友尚集团推出基于炬芯科技产品的蓝牙音箱方案

大联大控股宣布&#xff0c;其旗下友尚推出基于炬芯科技&#xff08;Actions&#xff09;ATS2835P蓝牙音频SoC的蓝牙音箱方案。 图示1-大联大友尚基于炬芯科技产品的蓝牙音箱方案的展示板图 在智能音频设备市场持续升温的浪潮中&#xff0c;蓝牙音箱凭借音质卓越、操作简便等…

[Linux] Linux操作系统 进程的优先级 环境变量(一)

标题&#xff1a;[Linux] Linux操作系统 进程的优先级 个人主页水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 一、进程优先级 1.PRI and NI 2.PRI vs NI 的补充理解 二、命令行参数和环境变量 正文开始&#xff1a; 一、进程优先级 基本概念 进程的调用需要CP…

Study--Oracle-09--部署Openfiler存储服务器

免费的存储服务器软件有FreeNAS 和 Openfiler。 其中Freenas的网站上只有i386及amd64的版本&#xff0c;也就是说Freenas不能支持64位版本的Intel CPU&#xff0c;而Openfiler则提供更全面的版本支持&#xff0c;在其网站上可以看到支持多网卡、多CPU&#xff0c;以及硬件Raid的…

manim中获取并定位不规则页面的中心位置

介绍中心点 找到中心点非常重要&#xff0c;因为它在多个领域中都有重要的应用和意义。中心点可以指一个几何形状的中心、数据集的平均值中心、或是特定情境下的关键焦点。以下是一些中心点重要性的具体解释&#xff1a; 数学与几何&#xff1a;在几何中&#xff0c;中心点&…

jinaai/jina-embeddings-v2-base-zh向量模型报错解决

报错信息 OSError: We couldn’t connect to ‘https://huggingface.co’ to load this file, couldn’t find it in the cached files and it looks like jinaai/jina-bert-implementation is not the path to a directory containing a file named configuration_bert.py. 报…

C++ | Leetcode C++题解之第441题排列硬币

题目&#xff1a; 题解&#xff1a; class Solution { public:int arrangeCoins(int n) {return (int) ((sqrt((long long) 8 * n 1) - 1) / 2);} };

探索Python新境界:funboost库揭秘

文章目录 探索Python新境界&#xff1a;funboost库揭秘背景&#xff1a;为什么选择funboost&#xff1f;funboost是什么&#xff1f;如何安装funboost&#xff1f;简单的库函数使用方法场景应用常见Bug及解决方案总结 探索Python新境界&#xff1a;funboost库揭秘 背景&#x…

什么是前缀索引?

什么是前缀索引&#xff1f; 1、什么是前缀索引&#xff1f;2、为什么要使用前缀索引&#xff1f;3、如何选择前缀长度&#xff1f;4、创建前缀索引的SQL语法5、示例 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在处理包含长字符串的数据…

yolo自动化项目实例解析(七)自建UI--工具栏选项

在上一章我们基本实现了关于预览窗口的显示&#xff0c;现在我们主要完善一下工具栏菜单按键 一、添加工具栏ui 1、配置文件读取 我们后面要改的东西越来越多了&#xff0c;先加个变量文件方便我们后面调用 下面我们使用的config.get意思是从./datas/setting.ini文件中读取关键…

RedisBoost Web缓存加速平台

1.产品介绍 产品名称:RedisBoost Web缓存加速平台 主要功能: 智能缓存策略配置 功能描述:RedisBoost提供了一套直观易用的缓存策略配置界面,允许用户根据业务场景自定义缓存策略,包括缓存时间(TTL)、缓存淘汰算法(如LRU、LFU)、数据分区与分片策略等。支持动态调整策…

SSM私人诊所管理系统—计算机毕业设计源码36406

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

Redis高级特性及应用

一、Redis慢查询 1.1 Redis命令流程 1.2 慢查询配置&#xff1a; 可以通过以下命令配置慢查询时间阈值&#xff08;慢查询值得是上图中执行命令的时间&#xff0c;不包含其他时间&#xff09; config set slowlog-log-slower-than 10000 //单位微秒 config rewrite //写入…

【设计模式-访问者模式】

定义 访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;允许你在不修改已有类的情况下向这些类添加新的功能或行为。它通过将操作的执行逻辑从对象的类中分离出来&#xff0c;使得你可以在保持类的封闭性&#xff08;符合开闭原则&#xff…

Leetcode 740. 删除并获得点数

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums &#xff0c;你可以对它进行一些操作。 每次操作中&#xff0c;选择任意一个 nums[i] &#xff0c;删除它并获得 nums[i] 的点数。之后&#xff0c;你必须删除 所有 等于 nums[i] - 1 和…

LeetCode题练习与总结:搜索二维矩阵 Ⅱ--240

一、题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],…

详细解析msyql和消息队列数据一致性问题

目录 前言 保持系统数据同步&#xff08;双写问题&#xff09; 消息队列消息丢失的问题 总结 前言 在当今互联网飞速发展的时代&#xff0c;随着业务复杂性的不断增加&#xff0c;消息队列作为一种重要的技术手段&#xff0c;越来越多地被应用于各种场景。它们不仅能有效解…

ChatGPT-o1用来进行数据分析,对比效果很惊人!

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 在进行数据分析的时候&#xff0c;通常有一个场景&#xff1a;我有一批数据&#xff0c;但是不知道该怎么分析&#xff0c;才能找到写论文的突破口和角度。ChatGPT能不能给我一…

Java项目实战II基于Java+Spring Boot+MySQL的厨艺交流平台设计与实现(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在美食文化…

江协科技STM32学习- P20 实验-TIM编码器接口测速

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…