信号与进程(2):进程终止

server/2024/10/20 5:42:33/

进程终止

参考博客

exit()与_exit()的区别

exit() 和 _exit() 的区别

进程正常终止

进程正常终止的方法有3种:

  1. 执行exit()函数
  2. 执行_exit()函数
  3. 在主函数中执行return

exit()与_exit()函数

exit()和_exit()的效果都是让程序退出执行,而_exit()用来“尽快”退出

/* Call all functions registered with `atexit' and `on_exit',in the reverse of the order in which they were registered,perform stdio cleanup, and terminate program execution with STATUS.  */
extern void exit (int __status) __THROW __attribute__ ((__noreturn__));/* Terminate program execution with the low-order 8 bits of STATUS.  */
extern void _exit (int __status) __attribute__ ((__noreturn__));

区别:

  1. _exit直接进入内核,exit则先执行一些清除处理(在进程退出之前要检查文件状态,将文件缓冲区中的内容写回文件)再进入内核
  2. 调用_exit函数时,其会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新流(stdin,stdout,stderr…),exit函数是在_exit函数之上的一个封装,其会调用_exit,并在调用之前会刷新流
  3. exit()函数在退出前要检查文件的打开情况,把文件缓冲区的内容写回文件,_exit()函数直接将进程关闭,缓冲区的数据将会丢失

Linux标准函数中,“缓冲I/O”的操作,其特征即对应每一个打开的文件,在内存中都有一片缓冲区。每次读文件时,会连续读出若干条记录,在下次读文件时就可以直接从内存的缓冲区读取;同样每次写文件的时候也仅仅是写入内存的缓冲区,等满足了一定的条件(如达到了一定数量或遇到特定字符等),再将缓冲区中的内容一次性写入文件。这种技术大大增加了文件读写的速度

exit()与return

通常在main()之后就没什么待办的事情了,也不会关心exit()和return的差别,但对于C++程序而言,main()中对象的析构函数是在return之后执行的,如果中途调了exit()就不会执行到析构函数

一般情况下,析构函数就是释放对象的资源,而进程退出后,进程所有资源就都被释放了,所以实际上调用exit()退出程序也并不会出现资源泄漏。只是说如果析构函数涉及到与其他进程通信或IO操作等影响到系统其他资源的情况下就要注意了

示例:

#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;void exit_func(void)
{cout << "oh yeah!" << endl;
}class Date
{
public:Date(int year1 = 1970, int month1 = 12, int day1 = 31){cout << "Date constructor" << endl;this->year = year1;this->month = month1;this->day = day1;}void printDate(){cout << year << ":" << month << ":" << day << endl;}int isLeapYear() { return 1; }void setDate(int year, int month, int day) {}~Date() { cout << "Date destructor!" << endl; }private:int year;int month;int day;
};class A
{
private:int dataA;public:A() { cout << "A's constructor" << endl; }~A() { cout << "A's destructor!" << endl; }
};class B
{
private:int dataB;A dataClassA;public:B() { cout << "B's constructor" << endl; }~B() { cout << "B's destructor!" << endl; }
};static Date d199;int main(int argc, char *argv[])
{cout << "main start" << endl;Date d1(2022, 6, 14);d1.printDate();static Date d2;A a1;B b1;atexit(exit_func);cout << "main done" << endl;return 0;
}

运行输出:

prejudice@prejudice-VirtualBox:~/Cplus_learning/bin$ ./wait_return 
Date constructor
main start
Date constructor
2022:6:14
Date constructor
A's constructor
A's constructor
B's constructor
main done
B's destructor!
A's destructor!
A's destructor!
Date destructor!
oh yeah!
Date destructor!
Date destructor!

将main()中return 0改为exit(0),运行输出:

prejudice@prejudice-VirtualBox:~/Cplus_learning/bin$ ./wait_return 
Date constructor
main start
Date constructor
2022:6:14
Date constructor
A's constructor
A's constructor
B's constructor
main done
oh yeah!
Date destructor!
Date destructor!

看到main()中定义的对象的析构没有被调用

进程异常终止

进程异常终止主要有两种方式:

  1. 进程接受到特定的信号。这个信号可以是进程自己产生的,也可以是来自其他进程或内核。例如,进程企图访问越界的内存地址或者是除数为0时,内核都会产生信号中断进程
  2. 调用abort。这其实是第1种情形的特例,因为它产生一个SIGABRT信号
#include <stdlib>/* Abort execution and generate a core-dump.  */
extern void abort (void) __THROW __attribute__ ((__noreturn__));

abort()函数与exit()_exit()函数区别:

  1. abort()函数异常终止进程,进程的文件描述符未关闭,占用资源未释放
  2. exit()、_exit()正常终止进程,关闭进程的文件描述符并释放资源

示例:

// C++ code to demonstrate the example of
// abort() function#include <iostream>
#include <stdlib.h>
using namespace std;int main()
{float x, y;while (1){cout << "Input the value of x: ";cin >> x;cout << "Input the value of y: ";cin >> y;if (y == 0){cout << "Value of Y cannot be 0" << endl;abort();}cout << x << "/" << y << ": " << x / y << endl;}return 0;
}

运行输出:

prejudice@prejudice-VirtualBox:~/Cplus_learning/bin$ ./abort 
Input the value of x: 2
Input the value of y: 3
2/3: 0.666667
Input the value of x: 4
Input the value of y: 0
Value of Y cannot be 0
已放弃 (核心已转储)

http://www.ppmy.cn/server/35111.html

相关文章

Linux的基本指令(下)

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 这篇博客续博主的上篇博客Linux基本指令。 07 …

Leetcode 3138. Minimum Length of Anagram Concatenation

Leetcode 3138. Minimum Length of Anagram Concatenation 1. 解题思路2. 代码实现 题目链接&#xff1a;3138. Minimum Length of Anagram Concatenation 1. 解题思路 这一题的话我们首先统计出来所有的字母出现的频率。 然后&#xff0c;我们只需要从头开始重新计数一下&…

2024小米SU7首批锁单用户调研报告

来源&#xff1a;电动汽车用户联盟 80%的锁单用户认为自己是米粉&#xff0c;64%的用户拥有10个以上米家生态产品&#xff0c; 使用小米手机的比例为67%&#xff0c;使用苹果手机的比例为47% 2. 81%的用户为90后&#xff0c;均龄31岁&#xff0c;未婚者和已婚无孩者占比63%&am…

2分钟教你Flutter怎么避免引用内存泄漏

2分钟教你Flutter怎么避免引用内存泄漏 内存泄漏原因1. 在当前类&#xff0c;或者方法等移除改引用&#xff0c;让其他自动释放&#xff0c;等下一轮GC扫描释放。如2. 使用弱引用-----**WeakReference**&#xff0c;当前使用完&#xff0c;生命周期结束后&#xff0c;自动释放。…

Docker新建容器 修改运行容器端口

目录 一、修改容器的映射端口 二、解决方案 三、方案 一、修改容器的映射端口 项目需求修改容器的映射端口 二、解决方案 停止需要修改的容器 修改hostconfig.json文件 重启docker 服务 启动修改容器 三、方案 目前正在运行的容器 宿主机的3000 端口 映射 容器…

PXE高效批量网络装机

文章目录 一、系统装机过程二、PXE什么是PXE&#xff1f;实现过程详解PXE优点操作过程配置过程截屏 三、kickstart无人值守安装 一、系统装机过程 Linux启动操作系统有三种方式&#xff1a;1.硬盘2.光驱&#xff08;u盘&#xff09;3.网络启动&#xff08;pxe&#xff09; 系统…

浏览器开发者工具,控制台里读取指定网页节点内容,并保存到文件里

在网页控制台console里&#xff0c;读取body > div.bj-eee > div > div.layout-left > div.topic > div.clearfix.top-hd > div.select-left.pull-left.options-w 中的内容 // 使用querySelector选择单个元素 var element document.querySelector(body &…

省公派出国|社科类普通高校教师限期内赴英国访学交流

在国外访问学者申请中&#xff0c;人文社科类相对难度更大&#xff0c;尤其是英语语言学&#xff0c;作为非母语研究并不被国外高校看重。经过努力&#xff0c;最终我们帮助Z老师申请到英国坎特伯雷基督教会大学的访学职位&#xff0c;并在限期内出国。 Z老师背景&#xff1a; …