当前位置: 首页 > news >正文

Linux 进程终止 进程等待

目录

进程终止

退出码

错误码

代码异常终止(信号详解)

exit

_exit

进程等待

概念

等待的原因

wait

函数原型

参数

返回值

 监控脚本

waitpid

概念

函数原型

 参数

返回值

WIFEXITED(status)

WEXITSTATUS(status)

问题

为什么不用全局变量获得子进程的退出信息?

父进程如何得知子进程的退出信息?

模拟非阻塞等待轮询逻辑

重点


进程终止

退出码

  • 退出码是程序在结束时返回给操作系统的一个状态码,表示程序执行的最终结果,退出码通常用于告知操作系统或调用进程该程序是否成功执行
  • echo $?:Shell自动维护的特殊变量,可以打印出最后一个子进程执行完毕后的退出码(echo是内建命令)

错误码

for(int i = 0; i < 134; i++)printf("%d: %s\n", i, strerror(i));
  •  errno是一个全局变量(通过errno.h引入),用于存储最近一次系统调用库函数执行失败时的错误代码,错误时会将错误码设置到errno中
  • 可以通过strerror将错误码转换为错误描述

代码异常终止(信号详解)

  • 出异常时不看错误码,因为异常机制本身已经传递了足够的信息来描述错误情况
  • 程序崩溃:进程调度中出现异常,异常信息会被OS检测到,OS通过发送信号的方式杀掉、终止(释放)对应的进程
  • 异常通常是程序员自己写出来的
  • 一个进程是否出现异常,看有无收到信号
  • 父进程通过  信号数字  和  退出码  来判断子进程任务完成的怎样

exit

  • exit(int status):status 进程的退出码
  • 等价于在main函数中直接return,任意地点调exit,表示进程退出,后序代码不执行,直接终止进程
  • exit时候,会将冲刷缓冲区
  • exit 函数的底层封装了 _exit 系统调用接口

_exit

  • 是一个系统调用接口,直接与操作系统内核交互
  • _exit时候,不会冲刷缓冲区,内核之上是系统调用接口,说明缓冲区(C语言提供的)不在内核中
  • ★是一个底层的、直接与内核交互的系统调用,它的目标是立即终止进程,而不是进行任何用户空间的清理工作

进程等待

概念

  • 通过wait/waitpid,让父进程对子进程进行资源回收的等待过程

等待的原因

  • 解决子进程的僵尸问题带来的内存泄露
  • 子进程要将父进程给的任务的完成结果(即,子进程的退出信息->进程的退出码,信号编号)返回给父进程
  • 简:OS回收子进程资源获得进程的退出信息

wait

函数原型

#include <sys/wait.h>pid_t wait(int *status);

参数

  • 输出型参数
  • status:用于存储子进程的退出状态。父进程可以通过此参数判断子进程是正常退出还是因异常终止
  • 如果异常了,退出码就没用了;实测:子进程中途异常,exit code 为0

返回值

  • 成功时返回已终止子进程的进程 ID(pid_t 类型)
  • 如果没有子进程或调用失败,返回 -1,并设置 errno
void worker()
{int cnt = 3;while(cnt--){printf("child process, pid:%d, ppid%d\n", getpid(), getppid());sleep(1);}
}void creatSubProcess()
{pid_t id = fork();if(id == 0) {worker();exit(0);}else{    sleep(6);    pid_t rid = wait(NULL);if(rid == id)    {                                                                                    printf("wait success:pid: %d, rid: %d\n", getpid(), rid);    }    sleep(3);    }   
}

 监控脚本

  • 父进程结束的时候,会自动回收子进程,但是也可以在父进程运行中途回收
  • pid_t wait(int *status); status:指向整数的指针,用于存储子进程的退出状态信息
  • wait是一个系统调用接口;声明,相关的宏和数据类型在 sys/wait.h
  • wait能够回收处于僵尸状态的子进程;如果执行到父进程执行到wait这行代码时,子进程没退出,父进程会在wait这行代码上阻塞等待,知道子进程运行完毕,wait会对其回收;是一种等待软件资源的阻塞,一个进程 等待另一个进程执行完成
  • 僵尸进程无法被信号杀掉,只能通过父进程回收

waitpid

概念

  • waitpid 是一种系统调用,使父进程可以等待特定子进程的终止,或按指定的条件等待所有子进程终止,waitpid 通过 pid 参数指定要等待的进程,提供了灵活的子进程管理方式

函数原型

#include <sys/wait.h>pid_t waitpid(pid_t pid, int *status, int options);

 参数

  • pid:指定要等待的子进程
    • pid > 0:等待进程 ID 等于 pid 的子进程。
    • pid = 0:等待与调用进程在同一进程组的任一子进程
    • pid = -1:等待任一子进程(等价于 wait)
    • pid < -1:等待进程组 ID 等于 |pid| 的任一子进程

  • status:用于存储子进程的退出状态
  • options:控制等待行为
    • 0:阻塞等待子进程退出
    • WNOHANG非阻塞模式如果没有已退出的子进程,立即返回
    • WUNTRACED:如果子进程暂停(收到 SIGSTOP 等信号),则返回该子进程状态。
    • WCONTINUED:如果子进程被恢复运行(收到 SIGCONT 信号),则返回该子进程状态。

返回值

  • 成功时返回已终止的子进程的 pid。
  • 如果 WNOHANG 选项被设置,且没有已退出的子进程,返回 0。
  • 出错时返回 -1,并设置 errno

WIFEXITED(status)

  • #define WIFEXITED(status)   (((status) & 0x7F) == 0)
  • W:wait  IF:是否  EXITED:退出
  • 一个宏,用于检查一个子进程是否正常退出,返回非零值时,表示子进程通过 exitreturn 语句正常退出

WEXITSTATUS(status)

  • #define WEXITSTATUS(status)   (((status) >> 8) & 0xFF)
  • W:wait  EXIT:退出  STATUS:状态  
  • wait/waitpid的方式来等待的子进程的退出状态    其由退出码呈现
  • 用于获取子进程的退出状态码,只有在 WIFEXITED(status) 返回非零时(其实就是1),才能使用 WEXITSTATUS(status) 宏来获取子进程的退出码

问题

为什么不用全局变量获得子进程的退出信息?

  • 写实拷贝...进程间是相互独立的父进程无法直接拿到子进程的数据,只能通过系统调用获得
  • 像是一种通信

父进程如何得知子进程的退出信息?

  • 父进程调用系统调用接口来获得子进程的退出信息
  • 1.父进程给waitpid传status变量的地址 2.子进程结束后,代码的退出信息会回写到task_struct中,(task_struct中有这些字段,救就为了给父进程一个交代,也方面父进程去拿)
  • 之后再按照一定的方式回写给status  3.将子进程的exit_state改为X(X肯定是一个宏)
  • 我觉得回收资源是最重要的一点,这样可以创建更多的子进程帮我们完成任务;其次就是任务完成的结果
  • 父进程等待子进程的过程中,被链入子进程的等待队列;task_struct 本身不直接包含等待队列(wait_queue)成员

模拟非阻塞等待轮询逻辑

#include <stdio.h>    
#include <unistd.h>    
#include <stdlib.h>    
#include <sys/types.h>    
#include <sys/wait.h>    #define MAX_WORKER 5    
typedef void (*work)();    void father_work1()    
{    printf("father doing work1\n");    
}    void father_work2()    
{    printf("father doing work2\n");    
}    void father_work3()    
{    printf("father doing work3\n");                                                                                                                                               
}    
void worker()    
{    int cnt = 3;    while(cnt--)    {    printf("child process, pid_t: %d, ppid_t: %d, cnt: %d\n", getpid(), getppid(), cnt);    sleep(1);    }    
}    
void initArray(work array[])    
{    for(size_t i = 0; i < MAX_WORKER; i++)    array[i] = NULL; 
}void addWork(work array[], work w)
{for(size_t i = 0; i < MAX_WORKER; i++){                                                                                                                                                                             if(array[i] == NULL){array[i] = w;break;}}return;
}void doingWork(work array[])
{for(size_t i = 0; i < MAX_WORKER; i++)if(array[i]) array[i](); //(*array[i])();也可以//*array[i]这只是解引用函数,() 这才是调用函数
}
int main()
{work array[MAX_WORKER]; initArray(array);addWork(array, father_work1);addWork(array, father_work2);addWork(array, father_work3);pid_t id = fork();if(id == 0){worker();exit(1);}else{while(1){pid_t rid = waitpid(id, NULL, WNOHANG);if(rid > 0){printf("wait success\n");break;}else if(rid == 0){printf("father doing other thing\n");doingWork(array);}else{printf("wait failed\n");break;}sleep(1);}}return 0;
}
  • 代码风格是一个不错的点,尤其是对array的初始化和填值
  • 代码的核心目的就是简单的模拟:父进程不用一直等待没有被回收的子进程
  • waitpid直接可以返回,父进程去做别的工作,过一段时间再来检查子进程是否可以被回收

重点

进程终止

  1. 退出码,信号数字;错误码
  2. exit与_exit的区别

进程等待

  1. 进程等待的概念、原因
  2. wait与waitpid
  3. WIFEXITED与WEXITSTAUTS

相关文章:

Linux 进程终止 进程等待

目录 进程终止 退出码 错误码 代码异常终止(信号详解) exit _exit 进程等待 概念 等待的原因 wait 函数原型 参数 返回值 监控脚本 waitpid 概念 函数原型 参数 返回值 WIFEXITED(status) WEXITSTATUS(status) 问题 为什么不用全局变量获得子进程的退出信…...

VBA 64位API声明语句第003讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…...

【问题记录】解决VMware虚拟机中鼠标侧键无法使用的问题

前言 有项目需要在Linux系统中开发&#xff0c;因为要测试Linux中相关功能&#xff0c;要用到shell&#xff0c;在Windows中开发太麻烦了&#xff0c;因此我选择使用UbuntuXfce4桌面来开发&#xff0c;这里我用到了Linux版本的IDEA&#xff0c;除了快捷键经常和系统快捷键冲突…...

Naive UI 级联选择器 Cascader的:render-lable怎么使用(Vue3 + TS)(鼠标悬停该条数据的时候展示全部内容)

项目场景&#xff1a; 在渲染Cascader级联选择器后&#xff0c;当文字过长的时候&#xff0c;多出来的部分会显示成省略号&#xff0c;这使我们不能很清晰的看到该条数据的完整信息&#xff0c;就需要加一个鼠标悬停展示完整内容。 解决方案&#xff1a; vue&#xff1a; &l…...

vue元素里面的 js对象中,:style后面里属性名不支持这种带-的写法(background-color)

首先要知道&#xff0c;在这个:style里面&#xff0c;虽然可以用 {属性: 属性值 , 属性: 属性值} 这种方方式来写很多属性&#xff0c;但也仅限于width这种普通属性&#xff0c;像background-color这种带-的特殊标签是不支持直接写的&#xff1b; <div class"box&quo…...

Git 常用命令与开发流程总结

引言 在我之前面试过程中&#xff0c;经常会问到关于公司使用什么代码版本管理工具。 无非是考察咱们是否用过 Git和SVN。 现在公司选择的工具直接影响到项目的开发流程和协作效率。当前市面上&#xff0c;Git 和 SVN&#xff08;Subversion&#xff09;是两种流行的版本控制系…...

链表中插入新的节点

/* 节点结构体定义 */ struct xLIST_ITEM {TickType_t xItemValue; /* 辅助值&#xff0c;用于帮助节点做顺序排列 */ struct xLIST_ITEM * pxNext; /* 指向链表下一个节点 */ struct xLIST_ITEM * pxPrevious; /* 指向链表前一个节点 */ void * pvOw…...

AUTOSAR从入门到精通-BswM模块(二)

目录 前言 算法原理 BswM接口端口 BswM功能描述 模式仲裁 仲裁规则(Arbitration Rules) 模式仲裁来源 模式仲裁过程 模式条件(ModeCondition) 逻辑表达式(LogicExpressions) 模式控制 模式处理 操作执行 模式控制过程 模式控制基本流程 BswM Interfaces and …...

Spring DispatcherServlet详解

文章目录 Spring DispatcherServlet详解一、引言二、DispatcherServlet的初始化与工作流程1、DispatcherServlet的初始化1.1、加载配置和建立WebApplicationContext1.2、初始化策略 2、DispatcherServlet的工作流程2.1、请求分发2.2、代码示例 三、总结 Spring DispatcherServl…...

JS | 软件制作的流程是什么?

目录 一、 需求分析 二、 系统设计 三、 编码实现 四、 测试验证 五、 部署上线 六、 维护更新 软件制作的流程主要包含需求分析、系统设计、编码实现、测试验证、部署上线和维护更新。其中&#xff0c;需求分析是基础&#xff0c;它决定了软件的功能和性能&#xff1b;通…...

简单工厂模式

引言 简单工厂模式并不属于23种设计模式&#xff0c;它是工厂方法模式的“小弟”&#xff0c;由于日常编程中大家会经常用到&#xff0c;只不过没有察觉&#xff0c;因此下文将详解简单工厂模式。 1.概念 简单工厂模式(Simple Factory Pattern)&#xff1a;又称为静态工厂方法(…...

【django】Django REST Framework 序列化与反序列化详解

目录 1、什么是序列化和反序列化&#xff1f; 2、Django REST Framework中的序列化和反序列化 3、安装与配置&#xff08;第10章是从零开始&#xff09; 3.1 安装 3.2 配置 4、基本使用 4.1 创建序列化器 4.2 使用序列化器&#xff08;将数据序列化返回给前端&#xff…...

【Golang】Golang的Map的线程安全问题

文章目录 前言一、场景介绍二、线程安全的Map的使用四、总结 前言 在 Golang 编程中&#xff0c;map 是一种常用的数据结构&#xff0c;用于存储键值对。然而&#xff0c;Golang 的 map 在并发访问时是线程不安全的。如果多个 goroutine 同时读写同一个 map&#xff0c;可能会…...

指向指针的指针+ 值传递的理解

//17、下面的程序会出现什么结果 #include #include void getmemory(char *p) { p(char *) malloc(100); strcpy(p,”hello world”); } int main( ) { char *strNULL; getmemory(str); printf(“%s/n”,str); free(str); return 0; } // 程序崩溃&#xff0c…...

CSS常用定位

一、relative 相对原先的位置进行定位 {position: relative;left: 50px; /* 相对原先位置左边的距离 */top: 100px; /* 相对原先位置上边的距离 */ } 二、absolute 绝对定位&#xff0c;是相对于最近有定位的父级元素进行定位 {position: absolute;righ…...

【Linux】从零开始使用多路转接IO --- select

碌碌无为&#xff0c;则余生太长&#xff1b; 欲有所为&#xff0c;则人生苦短。 --- 中岛敦 《山月记》--- 从零开始认识五种IO模型 1 前言2 认识多路转接select3 多路转接select等待连接4 完善代码5 总结 1 前言 上一篇文章我们讲解了五种IO模型的基本概念&#xff0c;并…...

ArcGIS Pro SDK (二十一)渲染

ArcGIS Pro SDK (二十一)渲染 文章目录 ArcGIS Pro SDK (二十一)渲染1 定义唯一值呈现器定义2 为最新观测值设置唯一值渲染器3 为先前的观测值设置唯一值渲染器4 设置简单的渲染器以绘制轨迹线5 检查先前的观测值和轨道线可见性6 使轨迹线和先前的观测点可见7 检索当前观测…...

FPGA在物联网边缘计算中的应用!!!

FPGA&#xff08;现场可编程门阵列&#xff09;在物联网边缘计算中的应用正变得越来越重要。边缘计算是一种分布式计算架构&#xff0c;它将数据的处理分散到网络的边缘&#xff0c;靠近数据源&#xff0c;而不是集中在数据中心处理。以下是FPGA在物联网边缘计算中的几个关键应…...

【解决】Linux环境中mysqlclient安装失败问题

问题描述 在Linux系统下安装myslclient报异常。系统为Centos 8 使用 pip install mysqlclient 报出下面的异常 error: subprocess-exited-with-error Getting requirements to build wheel did not run successfully.│ exit code: 1╰─> [30 lines of output]/bin/sh: pkg…...

✨ Midjourney中文版:创意启航,绘梦无界 ✨

Midjourney AI超强绘画 (原生态系统&#xff09;用户端&#xff1a;Ai Loadinghttps://www.mjdiscord.com 项目详细介绍飞书文档&#xff1a;Docshttps://ivqklkndl4k.feishu.cn/docx/GRnMdCbcooWkwTx1RU4cZjGVnzb?fromfrom_copylk &#x1f310; 无缝体验&#xff0c;中文定制…...

技术视角:分布式投票系统的异步解耦架构与多语言协同实践

技术视角&#xff1a;分布式投票系统的异步解耦架构与多语言协同实践 【免费下载链接】example-voting-app Example Docker Compose app 项目地址: https://gitcode.com/gh_mirrors/exa/example-voting-app 在当今企业级应用架构设计中&#xff0c;如何平衡高并发处理、…...

解锁端侧智能:基于BigDL-LLM与Qwen-1.8B-Chat的CPU高效推理实践

1. 为什么要在CPU上部署大模型&#xff1f; 最近两年大模型技术发展迅猛&#xff0c;但大多数应用都依赖昂贵的GPU服务器。我在实际项目中发现&#xff0c;很多中小企业和个人开发者其实更需要能在普通电脑上运行的轻量化方案。这就是为什么基于CPU的大模型部署方案变得越来越…...

保姆级教程:在CentOS 7/8服务器上部署DrissionPage爬虫(含Chrome无头模式配置)

CentOS服务器上DrissionPage爬虫的工业级部署指南 1. 环境准备与Chrome浏览器安装 在CentOS服务器上部署基于DrissionPage的爬虫系统&#xff0c;首要任务是构建稳定可靠的浏览器运行环境。与个人开发环境不同&#xff0c;生产服务器通常需要面对无图形界面、资源受限等特殊场景…...

VHD2VL:破解硬件描述语言转换难题的开源解决方案

VHD2VL&#xff1a;破解硬件描述语言转换难题的开源解决方案 【免费下载链接】vhd2vl 项目地址: https://gitcode.com/gh_mirrors/vh/vhd2vl 在FPGA和ASIC设计领域&#xff0c;技术团队常常面临VHDL与Verilog两种硬件描述语言之间的转换挑战。当项目需要跨语言协作、工…...

移动端大语言模型本地部署:从模型轻量化到推理引擎实战

1. 项目概述&#xff1a;当GPT遇见移动端&#xff0c;一个开源项目的诞生最近在GitHub上闲逛&#xff0c;发现了一个挺有意思的项目&#xff0c;叫Taewan-P/gpt_mobile。光看名字&#xff0c;你大概就能猜到它的核心&#xff1a;把类似GPT这样的大语言模型&#xff08;LLM&…...

FPGA高速ADC数据采集实战——基于AD9253 LVDS接口与ISERDESE2设计

1. AD9253高速ADC核心特性解析 AD9253这颗14位125MSPS四通道ADC芯片&#xff0c;在通信和医疗成像领域堪称经典。我经手过的多个雷达项目中&#xff0c;它的信噪比表现总能带来惊喜——75.3dBFS的实测数据比手册标称值还要稳定。但真正让工程师们又爱又恨的&#xff0c;是它那个…...

Python与ChatGPT构建智能办公自动化:从任务分解到智能体系统

1. 项目概述&#xff1a;用Python与ChatGPT联手&#xff0c;让办公自动化“开口说话”如果你每天还在重复着打开Excel、复制粘贴数据、手动写邮件、整理报告这些枯燥的活儿&#xff0c;那这个项目可能就是你的“数字员工”入职通知书。Sven-Bo/automate-office-tasks-using-cha…...

Bifrost:轻量高效的实时数据同步平台架构与实战

1. 项目概述&#xff1a;Bifrost&#xff0c;一个被低估的现代数据同步利器如果你正在处理跨数据库、跨数据源的数据同步任务&#xff0c;并且对传统ETL工具的笨重、配置复杂感到头疼&#xff0c;那么maximhq/bifrost这个项目绝对值得你花时间深入了解。我第一次接触Bifrost是在…...

基于LLM的游戏AI智能体:从感知到决策的框架构建与实践

1. 项目概述&#xff1a;一个能“玩”游戏的AI智能体最近在GitHub上看到一个挺有意思的项目&#xff0c;叫ChattyPlay-Agent。光看名字&#xff0c;你可能会觉得这又是一个基于大语言模型的聊天机器人。但点进去仔细研究后&#xff0c;我发现它的定位非常独特&#xff1a;这是一…...

基于Nginx-Lua镜像构建高性能可编程网关的实践指南

1. 项目概述&#xff1a;一个为现代Web架构而生的Nginx镜像如果你和我一样&#xff0c;长期在容器化环境中部署和管理Web服务&#xff0c;那么你一定对Nginx的灵活性和Lua脚本的强大能力印象深刻。但将这两者结合&#xff0c;并打包成一个稳定、安全、功能齐全的Docker镜像&…...