【Linux学习】深入探索进程等待与进程退出码和退出信号

文章目录

  • 退出码
    • return退出
  • 进程的等待
    • 进程等待的方法


退出码

main函数的返回值:进程的退出码。
一般为0表示成功,非0表示失败。
每一个非0退出码都表示一个失败的原因;

echo $?命令

作用:查看进程退出码。(最近一次进程退出时的退出码)
在这里插入图片描述

查看进程的退出码对应的错误描述:

  1. 使用系统自带函数:strerror
    作用:将一个错误吗转化为错误描述。
    在这里插入图片描述

示例:

测试代码:

   #include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>int main(){for(int i =0 ;i<200;i++){printf("%d: %s\n",i,strerror(i));                                                                                        }return 0;}

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

  1. 自定义
   enum{success=0,Operation_not_permitted, No_such_file_or_directory };const char* errorstr(int error){switch(error){case success: return "success";case Operation_not_permitted: return "Operation not permitted";case No_such_file_or_directory: return "No such file or directory";default:return "unkown";}}

除了进程退出,还有函数退出,怎么知道函数的执行情况? 函数返回值。

函数返回值

调用函数我们通常想看到两种结果:

  1. 函数的执行结果------函数返回值

  2. 函数的执行情况------成功 ,失败及什么原因

    就比如fopen函数:
    如图:翻译:如果打开成功,返回该文件指针,如果失败,返回NULL,并且会设置一个错误码,名字叫errno,表明失败原因
    在这里插入图片描述

示例:
测试代码:

#include<stdio.h>
#incldue<stdlib.h>
#incldue<errno.h>
int main()
{FILE* fp = fopen("./c.txt","r");printf("%d:%s\n",errno,strerror(errno));return 0;
}

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

函数exit :终止进程。
使用:exit(退出码)。

exit与_exit的区别:exit会支持刷新缓冲区,而_exit不支持。

示例:
测试代码一:

int main()
{printf("hello linux");sleep(2);exit(1);return 0;
}

运行结果:
在这里插入图片描述
当将上面的exit换为_exit时,运行结果如下:
在这里插入图片描述

exit与_exit的关系:exit是对_exit的封装,就是调用的_exit。
在这里插入图片描述

return退出

return是一种更常见的退出进程方法。执行 return n等同于执行exit(n),因为调用main的运行时函数会将main的返回值当做 exit的参数。

任何进程最终的执行情况,我们可以是使用两个数字表示的:1.退出码 2.退出信号

退出信号:

如图:(注意是从1开始的)
在这里插入图片描述

进程的等待

进程等待必要性

  • 子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
  • 另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。
  • 最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

进程等待的方法

  1. wait方法
  • 在进行等待的时候,默认进行的是阻塞等待。
  • 返回值:
  • 成功返回被等待进程pid,失败返回-1。
  • 参数:
  • 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
    在这里插入图片描述

测试代码:

 #include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<errno.h>#include<sys/wait.h>#include<sys/types.h>int main(){pid_t id = fork();if(id==0){//子进程int cnt = 2;while(cnt--){printf("child  pid:%d  ppid: %d\n",getpid(),getppid());                                                                sleep(1);}printf("子进程准备退出\n");exit(0);}//fatherprintf("父进程休眠\n");sleep(4);printf("父进程回收僵尸进程\n");pid_t rid = wait(NULL);if(rid>0){printf("等待成功,僵尸进程 id:%d\n",rid);}printf("父进程回收成功\n");sleep(2);return 0;}

运行结果:fork之后,父子进程谁最先运行?不确定。
谁最后退出,父进程。
在这里插入图片描述

  1. waitpid的使用在这里插入图片描述

返回值:

  • 当正常返回的时候waitpid返回收集到的子进程的进程ID;
  • 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
  • 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

参数:pid

  • Pid=-1,等待任一个子进程。与wait等效。
  • Pid>0.等待其进程ID与pid相等的子进程。

如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
如果不存在该子进程,则立即出错返回。

测试代码:

  9 int main()10 {11   pid_t id = fork();12   if(id==0)13   {14     //子进程15     int cnt = 2;16     while(cnt--)17     {18       printf("child is running  pid:%d  ppid: %d\n",getpid(),getppid());19       sleep(1);20     }21     printf("子进程准备退出\n");22     exit(1);23   }24   int status = 0;25   pid_t rid = waitpid(id,&status,0);                                                                                                    26   if(rid>0){27     printf("等待成功,僵尸进程 id:%d status:%d\n",rid,status);28   }29   sleep(2);30 31   return 0;32 }

运行结果:
在这里插入图片描述
分析:退出码为1,这里为什么是256呢?

根据下面对status存储的解释:上面的status等于:
0000 0000 0000 0000 0000 0001 0000 0000 = 2^8 = 256

获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
如果传递NULL,表示不关心子进程的退出状态信息。
否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):
在这里插入图片描述


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

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

相关文章

I.MX6ULL Linux C语言开发环境搭建(点灯实验)

系列文章目录 I.MX6ULL Linux C语言开发 I.MX6ULL Linux C语言开发 系列文章目录一、前言二、硬件原理分析三、构建步骤一、 C语言运行环境构建二、软件编写三、链接脚本 四、实验程序编写五、编译下载验证 一、前言 汇编语言编写 LED 灯实验&#xff0c;但是实际开发过程中汇…

Go语言的内存泄漏如何检测和避免?

文章目录 Go语言内存泄漏的检测与避免一、内存泄漏的检测1. 使用性能分析工具2. 使用内存泄漏检测工具3. 代码审查与测试 二、内存泄漏的避免1. 使用defer关键字2. 使用垃圾回收机制3. 避免循环引用4. 使用缓冲池 Go语言内存泄漏的检测与避免 在Go语言开发中&#xff0c;内存泄…

【已解决】C#设置Halcon显示区域Region的颜色

前言 在开发过程中&#xff0c;突然发现我需要显示的筛选区域的颜色是白色的&#xff0c;如下图示&#xff0c;这对我们来说不明显会导致我的二值化筛选的时候存在误差&#xff0c;因此我们需要更换成红色显示这样的话就可以更加的明显&#xff0c;二值化筛选更加的准确。 解…

java: 无法访问org.springframework.ldap.core.LdapTemplate

完整错误&#xff1a; java: 无法访问org.springframework.ldap.core.LdapTemplate错误的类文件: /E:/apache-maven-3.6.3/repository/org/springframework/ldap/spring-ldap-core/3.2.3/spring-ldap-core-3.2.3.jar!/org/springframework/ldap/core/LdapTemplate.class类文件具…

《2024年中国机器人行业投融资报告》| 附下载

近年来&#xff0c;国内机器人行业取得了显著的技术进步&#xff0c;包括人工智能、感知技术、自主导航等技术方面的突破&#xff0c;使得机器人能够更好地适应复杂环境和任务需求&#xff0c;带动了机器人行业加快发展。 当然&#xff0c;技术的进步是外在驱动因素&#xff0…

探索集合python(Set)的神秘面纱:它与字典有何不同?

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、集合&#xff08;Set&#xff09;与字典&#xff08;Dictionary&#xff09;的初识 1. …

L2-038 病毒溯源

详解代码 #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 10010,M10010;int n; int h[N], e[M], ne[M], idx;//邻接表,h表示顶点&#xff0c;e表示当前边的终点&#xff0c;ne表示下一条边&#xff0c;idx当…

海外动态IP代理如何提高效率?

动态住宅IP代理之所以能够有效提升数据爬取的效率和准确性&#xff0c;主要归功于其提供的IP地址具有高度的匿名性和真实性。这些IP地址来自于真实的用户网络&#xff0c;因此相比于数据中心IP&#xff0c;它们更不容易被网站的安全系统标识为爬虫。此外&#xff0c;由于IP地址…

【vue-1】vue入门—创建一个vue应用

最近在闲暇时间想学习一下前端框架vue&#xff0c;主要参考以下两个学习资料。 官网 快速上手 | Vue.js b站学习视频 2.创建一个Vue3应用_哔哩哔哩_bilibili 一、创建一个vue3应用 <!DOCTYPE html> <html lang"en"> <head><meta charset&q…

NodeJS安装并生成Vue脚手架(保姆级)

文章目录 NodeJS下载配置环境变量Vue脚手架生成Vue脚手架创建项目Vue项目绑定git 更多相关内容可查看 NodeJS下载 下载地址&#xff1a;https://nodejs.org/en 下载的速度应该很快&#xff0c;下载完可以无脑安装&#xff0c;以下记得勾选即可 注意要记住自己的安装路径&…

【Linux】简单模拟C语言文件标准库FILE

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

R可视化:可发表的Y轴截断图

Y轴截断图by ggprism Y轴截断图by ggprism 介绍 ggplot2绘制Y轴截断图by ggprism加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE)library(tidyverse) library(ggprism) library(patchwork)rm(list = ls()) options(stringsAsFactors = F) options(future.…

Go语言的中间件(middleware)是如何实现的?

文章目录 Go语言的中间件&#xff08;Middleware&#xff09;是如何实现的&#xff1f;中间件的工作原理中间件的实现步骤示例代码总结 Go语言的中间件&#xff08;Middleware&#xff09;是如何实现的&#xff1f; 在Go语言中&#xff0c;中间件&#xff08;Middleware&#…

springboot实现多开发环境匹配置(超级简洁没废话)

首先logbok-spring.xml里面的内容 <?xml version"1.0" encoding"UTF-8"?> <configuration><!-- 开发、测试环境 --><springProfile name"dev,test"><include resource"org/springframework/boot/logging/log…

Java并发面试题,多线程通关秘籍

【知识点记录】- 不能不知道的知识点 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xf…

算法设计与分析

一、分治法 二、回溯法 三、贪心法 四、动态规划法 分治法一分而治之 对于一个规模为n的问题&#xff0c;若该问题可以容易地解决&#xff08;比如说规模n较小&#xff09;则直接解决&#xff0c;否则将其分解为k个规模较小的子问题&#xff0c;这些子问题互相独立且与原问题形…

【Linux】关于获取进程退出状态中的core dump标志补充

通过 wait/waitpid 可以获取子进程的退出状态, 从而判断其退出结果. 记录退出状态的 int 变量 status 的使用情况如下图所示: 如果是收到信号终止的话, 低 7 位为收到的终止信号, 而低第 8 位为 core dump 标志, core dump 标志有什么用呢? core dump 标志只存 0/1, 表示是否…

printf 模仿slf4j 的log.xxx效果

printf 模仿slf4j 的log.xxx效果 简介期待的效果颜色遇到的问题实际的效果代码实现使用效果图 简介 突然想玩一玩&#xff0c;能不能用printf实现slf4j里 的log.xxx 的效果。 性能是完全不考虑的&#xff0c;只要功能可用就好。 期待的效果 类似:info("这是第{}条日志…

ffmpeg-webrtc(metartc)给ffmpeg添加webrtc协议

这个是使用metrtc的库为ffmpeg添加webrtc传输协议&#xff0c;目前国内还有一个这样的开源项目&#xff0c;是杨成立大佬&#xff0c;大师兄他们在做&#xff0c;不过wili页面维护的不好&#xff0c;新手不知道如何使用&#xff0c;我专门对它做过介绍&#xff0c;另一篇博文&a…

不同类型水表计量技术的优缺点

1.单流束水表 1.1优点 (1)耐受悬浮固体。适用于硬水或悬浮颗粒物。 (2)多样性&#xff0c;可用性&#xff0c;容易找到需要的合适的表型。 (3)技术可靠&#xff0c;已使用了数十年。 (4)体积小&#xff0c;可以安装在狭小的空间里。 (5)13mm、15mm、20mm水表可能是市面…