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

【linux】进程创建与进程终止

Alt

🔥个人主页Quitecoder

🔥专栏linux笔记仓

Alt

目录

    • 01.进程创建
    • 02.进程终止
      • 异常终止
      • 如何终止
      • `exit()`
      • `_exit()`

01.进程创建

#include <unistd.h>
pid_t fork(void);

返回值:自进程中返回0,父进程返回子进程id,出错返回-1

进程调用fork,当控制转移到内核中的fork代码后,内核做:

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

在这里插入图片描述
写时拷贝

在这里插入图片描述

02.进程终止

首先想清楚,终止是做什么:

  • 释放曾经的代码和数据所占据的空间
  • 释放内核数据结构

进程退出场景:

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确(这两点可以通过进程退出码判断)
  • 代码异常终止

在这里插入图片描述
上面的代码,进程11258为父进程bash,echo $?父进程获取到的是最近一个子进程退出的退出码,前面我们提到,echo是内建命令,打印的都是bash内部的变量数据
在这里插入图片描述

父进程bash为什么要得到子进程的退出码呢?要知道子进程退出的情况(成功,失败,失败的原因是什么?)

进程结束时,可以通过 return 语句(在函数中)或 exit() 函数(直接从程序中)指定一个退出码。这个退出码是一个整数,传递给父进程,用于表示子进程的终止状态。

常见惯例:

  • 0(EXIT_SUCCESS):通常表示成功。程序执行完成且没有错误。
  • 非0(EXIT_FAILURE):通常表示有错误发生。具体的非零值可以用来指示不同类型的错误

异常终止

在操作系统中,进程的异常终止通常是由于一些错误或意外情况导致程序不能正常运行到结束。以下是一些典型的异常终止情况:

  1. 程序错误

    • 段错误(Segmentation Fault):程序试图访问其内存空间以外的区域或非法的内存区域。常见于指针错误,如访问未初始化的指针、空指针或已释放的内存。
    • 除零错误:程序尝试进行除以零的运算,这在数学运算中是未定义的。
  2. 资源问题

    • 内存耗尽:程序请求更多内存时,如果系统无法分配(如堆内存耗尽),可能会导致程序异常终止。
    • 文件描述符耗尽:程序打开太多文件而没有关闭,达到系统限制,可能导致系统函数失败,影响程序继续运行。
  3. 信号

    • 致命信号
      • SIGSEGV(段错误信号):最常见的程序崩溃原因,通常是由于访问违法的内存地址。
      • SIGABRT(中止信号):通常是由于程序内部发生严重错误或调用 abort() 函数而触发。
      • SIGFPE(浮点异常信号):执行了一个无效的算术运算,比如除以零。
      • SIGKILL:无条件终止程序运行的信号,无法捕获或忽略。
      • SIGTERM:请求终止程序的信号,比 SIGKILL 更温和,允许程序进行清理(关闭文件、释放资源等)操作后退出。
    • 非致命信号(如 SIGINT、SIGHUP 等),如果没有被程序正确处理,也可能导致程序终止。
  4. 操作系统干预

    • 死锁检测:操作系统可能终止处于死锁状态的进程以解锁系统资源。
    • 资源超额:操作系统对程序使用的资源(如 CPU 时间、内存使用量)有限制,如果程序超出这些限制,如超过了设定的 CPU 时间,操作系统可能终止这个进程。
  5. 运行时异常

    • 未捕获的异常:在一些高级语言中(如 Java、Python),如果程序中发生了异常而没有被捕获和处理,这通常会导致程序异常终止。例如,Python 中未被捕获的 ValueErrorIndexError

一旦出现异常,退出码没有意义了!进程出异常,本质是因为进程收到了OS发给进程的信号!

在这里插入图片描述
在这里插入图片描述
段错误,OS提前终止进程

我们可以看进程退出的时候,退出信号是多少,就可以判断我的进程为什么异常了! ! !
在这里插入图片描述

  1. 先看是不是异常
  2. 不是异常,就一定是代码跑完了,看退出码就行

衡量一个进程退出,我们只需要两个数字:退出码,退出信号!
在这里插入图片描述

如何终止

正常退出:

  1. main函数return,表示进程终止(非main函数,return,函数结束)
  2. 代码调用exit函数,注意:我们代码的任意位置调用exit,都表示进程退出
  3. _exit(),系统调用

异常退出:

  • ctrl + c,信号终止

在 Unix 和类 Unix 系统中,_exit()exit() 都用于终止进程,但它们在功能和使用场景上有重要的区别。理解这些区别有助于正确地管理程序的终止过程,特别是在涉及资源清理和子进程管理时

exit()

exit() 函数是由 C 标准库提供的,用于结束程序。它执行几个重要的清理操作,然后调用底层的 _exit()exit_group() 系统调用来终止进程。

  • 特点和操作
    • 刷新缓冲区exit() 会自动刷新所有 stdio 的缓冲区,将缓冲区内的数据写入文件。这确保了所有挂起的输出(例如,使用 printf() 产生的输出)都被正确地写出。在这里插入图片描述
      在这里插入图片描述

    • 执行 atexit() 注册的函数:如果程序中使用了 atexit() 注册了任何终止时执行的函数,exit() 会在实际终止进程前按注册的逆序调用这些函数。这可以用于执行一些如关闭文件描述符、释放分配的内存等清理工作。

    • 关闭 stdio 库:关闭所有使用标准 I/O 库打开的文件等资源。

使用场景主要是普通的应用程序,在需要确保输出数据完整性和执行特定的清理操作时使用。

_exit()

_exit() 函数是由 POSIX 标准指定,直接调用系统级别的退出操作,用于立即结束程序,不执行标准 I/O 的清理操作和不调用 atexit() 或者 C++ 的全局对象的析构函数。

  • 特点和操作
    • 不刷新缓冲区:不处理 stdio 的缓冲区,如果缓冲区内有未写入的数据,这些数据将丢失。在这里插入图片描述
      在这里插入图片描述

    • 不执行 atexit() 注册的函数:任何通过 atexit() 注册的函数都不会被执行。

    • 立即终止:提供一种确保程序能迅速终止的方式,通常用于子进程退出或者在错误处理中需要立即终止程序时使用。

使用场景主要是在创建子进程后,子进程完成任务立即退出时,或者在程序遇到无法恢复的错误需要立即终止时使用。

  • 使用 exit() 当你需要正常终止程序,并且需要清理资源(如关闭文件、保存状态等)。
  • 使用 _exit() 在需要快速退出且不关心资源清理的场景下,比如在子进程中执行了某个任务后,或者在出现严重错误时安全退出。

选择合适的函数可以避免数据丢失和资源泄漏,确保程序的稳定和安全。

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


http://www.mrgr.cn/news/54188.html

相关文章:

  • Springboot项目
  • php常用设计模式之单例模式
  • XML 和 SimpleXML 简介
  • WSL2 构建Ubuntu系统-轻量级AI运行环境
  • OpenGL、OpenCL 和 OpenAL 定义及用途
  • 【linux开发-Qt】-网络编程
  • 【AI论文精读6】SELF-RAG(23.10)附录
  • 【C++篇】类与对象的秘密(上)
  • 充电桩高压快充发展趋势
  • Yocto - 使用Yocto开发嵌入式Linux系统_10 使用Yocto项目进行开发
  • SVM支持向量机python实现
  • KUKA外部自动配置(下)
  • 【动手学深度学习】8.3 语言模型(个人向笔记)
  • 计算机通信与网络实验笔记
  • FL Studio 2024 发布,添加 FL Cloud 插件、AI 等功能
  • NVIDIA NIM平台利用AI的功能,AI驱动知识问答助手的实现
  • 风速weibull分布随机风速生成【基础代码】
  • 【动手学深度学习】8.2. 文本预处理(个人向笔记)
  • 2024年-2025年Java毕业设计怎样选题?1000个计算机毕业热门选题推荐
  • llm-action,让天下没有难学的大模型
  • 同一个交换机不同vlan的设备为什么不能通信
  • 如何用代码将网页打开
  • 2024年第四届“网鼎杯”网络安全大赛-赛前模拟训练
  • 空开老化损坏更换
  • MatLab Desired port was :31515解决方案
  • 关于串口中断时的一些问题