【Linux】进程终止

ops/2024/10/18 18:23:15/

思维导图

学习内容

       进程终止是进程控制里面的一个重要的知识,通过这一篇博客,我们可以学习到进程终止的概念,进程终止的三种情况,进程终止的退出码和退出信号,最后在来学习进程是如何进行终止的。

学习目标

一、进程终止的概念

       在计算机系统中,进程是操作系统分配资源的基本单位,而进程终止则是指操作系统因为某种原因结束一个进程的执行。这可能是因为进程完成了某种任务,也可能是因为出现了错误或异常。

       创建一个进程的过程是:先创建一个内核的部分数据结构,再进行复制代码和数据。那么终止一个进程的过程是和创建一个进程的顺序是相反的,终止一个进程的本质是:释放曾经的代码和数据所占据的空间,释放内核数据结构。

二、echo 内建命令

       echo内建命令的概念:打印的是bash内部的变量数据。

       ?符号的意义:父进程bash获取到最近一个子进程退出的退出码,0表示正常退出,非0表示异常退出。这个返回值需要让父进程得到,告诉父进程,子进程将任务完成的怎么样。

       不是?符号可以将最近一个子进程退出的退出码获取吗?但是上图中为什么获取了两个不同的子进程退出的退出码。 

       因为echo命令也是一个进程,当使用完echo命令后,变成了最近一次子进程,又因为echo命令正常退出,所以最近一次子进程退出的退出码是0。

三、进程退出码

3.1 strerror函数

3.1.1 strerror函数的用途获取指向错误信息字符串的指针。

3.1.2 strerror函数的介绍

#include <string.h>
char* strerror(int errnum)
// 返回值为char * 类型,指向描述错误错误的错误字符串的指针

3.1.3 利用strerror函数来获取C语言中所有的错误信息

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

3.2 父进程为什么要获取子进程的退出码?

       因为父进程要知道子进程完成任务的情况(成功或者失败,失败的原因是什么),要对子进程进行负责。

3.3 自定义退出码

       我们可以通过联合体为自定义退出码进行赋值,将退出码置为全局变量,在每一个函数的每一种结果中都需要将退出码进行修改,在通过接收退出码的值将退出码的值翻译为错误信息的字符串。

#include <stdio.h>enum{Success = 0,Div_Zero,Mod_Zero,
};int errcode = Success;int Div(int a, int b)
{if(b == 0){errcode = Div_Zero;return -1;}else{errcode = Success;return a / b;}
}char* geterror(int errno)
{switch(errno){case Success:return "Success";case Div_Zero:return "Div_Zero";case Mod_Zero:return "Mod_Zero";dafault:return NULL;}
}int main()
{int tmp1 = Div(10, 1);printf("answer: %d Error: %s\n", tmp1, geterror(errcode));int tmp2 = Div(10, 0);printf("answer: %d Error: %s\n", tmp2, geterror(errcode));return 0;
}

四、进程终止的三种情况

4.1 通过进程的退出码决定的进程终止的情况

  • 代码跑完,结果正确
  • 代码跑完,结果不正确

4.2 通过进程的退出信号决定的进程终止的情况 

最后一种情况:代码执行时,出现了异常,提前退出了,退出码没有意义。

  • 编译运行时,崩溃了,操作系统发现了你的进程做了不该做的事情,操作系统杀死了进程。
  • 一旦进程出现异常,退出码没有意义

进程异常的退出信号

我们可以使用kill命令来显示进程异常的退出信号所代表的含义:

kill -l

现在我们可以通过做个实验,来查看进程异常退出是否需要错误信号。

#include <stdio.h>
#include <unistd.h>int main()
{while (1){printf("I am process, pid = %d\n", getpid());sleep(1);}return 0;
}

当代码中出现一些异常错误时,进程也会发出错误信号,杀死进程。

总结:判断一个进程的退出情况,我只需要检查进程是否出现异常;如果没有出现异常,就检查进程的退出码。衡量一个进程退出,我们只需要两个数字:退出码和退出信号

五、进程如何终止

  • main函数调用return表示进程终止(普通函数的return,是退出函数)
  • 代码调用exit函数,在进程退出后,会冲刷缓冲区
  • 系统调用_exit函数,在进程退出后,不会冲刷缓冲区

我们可以通过代码来观察现象:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{printf("Hello world");exit(1);return 0;
}

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main()
{printf("Hello world");_exit(1);return 0;
}


http://www.ppmy.cn/ops/27846.html

相关文章

【C++】STL学习之优先级队列

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 前言一、优先级队列的使用1.1 基本功能1.2 优先级模式切换1.3 相关题目 二、模拟实现优先级…

STM32 CAN开发步骤

STM32 CAN开发通常涉及以下步骤&#xff1a; 1. 配置CAN外设&#xff1a;根据具体的STM32系列和型号&#xff0c;选择并配置CAN外设。可以使用STM32CubeMX软件进行可视化配置&#xff0c;或者直接编写寄存器级的配置代码。 2. 初始化CAN外设&#xff1a;使用HAL库或者寄存器级…

OpenHarmony实战开发-如何实现单一手势

点击手势&#xff08;TapGesture&#xff09; TapGesture(value?:{count?:number; fingers?:number})点击手势支持单次点击和多次点击&#xff0c;拥有两个可选参数&#xff1a; count&#xff1a;声明该点击手势识别的连续点击次数。默认值为1&#xff0c;若设置小于1的非…

Vue3 el-dialog 二次封装踩坑实录(v-model moduleValue 不触发)

如果你封装了一个el-dialog的子组件&#xff0c;想通过父组件v-model的形式调用&#xff0c;切记不能使用v-model&#xff0c;要使用 v-model:[你的参数]&#xff0c;例如 v-model:visible <template><el-dialogv-model"dialogVisibale":title"title&…

Java中的IO流

IO流的概述和分类 IO流分为输入输出流 输入流&#xff1a;读数据 输出流&#xff1a;写数据 流&#xff1a;是一种抽象的概念&#xff0c;是对数据传输的总称&#xff0c;流的本质是数据传输 按照数据类型来分 字节流&#xff1a;字节输入流&#xff0c;字节输出流 字符…

AJAX家政系统 自营+多商家(高级授权)+独立端口 -源码下载

应用介绍 后台&#xff1a;https://service.hnajax.com/hxeJVakAdf.php/index/login AJAX家政系统 自营多商家(高级授权)独立端口 基于FastAdmin和原生微信小程序开发的一款同城预约、上门服务、到店核销家政系统&#xff0c;用户端、服务端(高级授权)、门店端(高级授权)各端…

C、C++的联合体:union关键字含义

C、C的联合体&#xff1a;union关键字含义 **联合体&#xff08;Union&#xff09;**在C语言中是一种特殊的数据结构&#xff0c;它允许在相同的内存位置存储不同的数据类型。但是&#xff0c;在任何时候&#xff0c;联合体中只有一个成员是有效的&#xff0c;因为所有的成员都…

JDBC连接MySQL8 SSL

1.创建用户并指定ssl连接 grant all on . to test% identified by imooc require SSL(X509); 2.查看是否使用ssl SELECT ssl_type From mysql.user Where user"test" 3.配置用户必须使用ssl ALTER USER test% REQUIRE SSL(X509); FLUSH PRIVILEGES; 注意&#xff…