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

【Linux仓库】进程创建与进程终止【进程·柒】

🌟 各位看官好,我是

🌍 Linux == Linux is not Unix !

🚀 今天来学习Linux的指令知识,并学会灵活使用这些指令。

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦!

目录

进程创建

写时拷贝

为什么要写时拷贝

进程终止

return 0

退出场景

前两种场景:

FILE结构体

​编辑


进程创建

在linux中fork函数是非常重要的函数,它从已存在进程中创建⼀个新进程。新进程为⼦进程,⽽原进程为⽗进程。(上几个章节中,我们也对fork有了简单的认识)
#include <unistd.h>
pid_t fork(void);
返回值:子进程中返回0,⽗进程返回⼦进程id,出错返回-1

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

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

当⼀个进程调⽤fork之后,就有两个⼆进制代码相同的进程。⽽且它们都运⾏到相同的地⽅,但每个进程都将可以开始它们自己的旅程。(注意:fork之后,谁先执⾏完全由调度器决定。

写时拷贝

通常,父子代码共享,⽗⼦再不写入时,数据也是共享的,当任意⼀⽅试图写⼊,便以写时拷贝的⽅式各⾃⼀份副本。(因为有写时拷贝技术的存在,所以⽗⼦进程得以彻底分离!完成了进程独立性的技术保证!)
  

为什么要写时拷贝

但是仔细一想会有两点疑惑:

问题1:为什么创建子进程后,不直接将数据进行分开,直接拷贝不就好了?为什么要写时拷贝? 

数据分开的本质是“按需获取”,节省内存。而写时拷贝是一种“惰性”申请,等需要写入时再进行写时,也是为了节省内存。

问题2:为什么要拷贝?直接开辟对应的空间不就好了?

  1. 减少内存占用:当 fork 系统调用创建子进程时,子进程会复制父进程的地址空间。如果直接开辟新的内存空间并将父进程的数据全部复制过去,在很多情况下,子进程并不会修改父进程的大部分数据。
  2. 加速 fork 操作:直接开辟空间并复制数据会增加 fork 操作的时间开销。

 实际上我们之前所使用的C/C++也用到了"惰性"申请:

进程终止

进程终止是什么?一个进程既然被创建出来,那么自然也要对它进行负责,因此需要回收子进程的资源。(创建进程的反方向)

进程终⽌的本质是释放系统资源,就是释放进程申请的相关内核数据结构和对应的数据和代码。

return 0

这里对我们之前的C/C++中main函数为什么要返回return 0 进行解惑。我们都清楚我们的程序是由bash创建子进程来运行的,那么bash之后肯定要回收子进程,因此可以确定的是子进程的return 0的退出码是给父进程的。return 0 会被“系统”获得 --> 它被用来让系统辨别:该进程的执行情况!!!因此,0表示该进程执行成功。

那退出码是否可以被我们人为获取呢?答案是可以的。
   

退出场景

进程退出无非就三种情景:

  1. 代码跑完了,结果正确;
  2. 代码跑完了,结果错误;
  3. 代码没跑完,结果异常。(代码异常了,退出码本身就没意义了! --> 意义在为什么会出现异常,管理者OS要知道:一般都是发出进程信号来杀掉这个进程)

前两种场景:

前两种场景是由退出码来决定!!! --> exit(code)

查看退出码有三种方法:

  1. main函数进行return n,n表示该进程的退出码;
  2. 直接调用exit(n),n表示该进程的退出码;
  3. 直接调用_exit(n)

那么这三种方法有什么区别呢?

return vs exit

return 表示函数调用结束,main函数return,表示进程退出;exit表示的是进程结束,在代码中任何地方调用,都会导致进程退出,即exit引起一个进程结束(会刷新缓冲区)

  

exit vs _exite

exit属于库函数,终止进程时会主动刷新缓冲区  ;_exit属于系统调用,直接终止进程但不会刷新缓冲区。

它们两的区别就在于是否刷新缓冲区,而我们知道进程主动请求终止的路径是要通过系统调用来完成,由此我们可以猜测exit接口在内部会调用_exit系统调用,即exit底层封装了_exit

FILE结构体


http://www.dtcms.com/a/338873.html

相关文章:

  • 通过C#上位机串口写入和读取浮点数到stm32的片内flash实战4(通过串口下发AD9833设置值并在上位机显示波形曲线)
  • 基于单片机智能点滴输液系统
  • 元素的width和offsetWidth有什么区别
  • java八股文-中间件-参考回答
  • Win11家庭版docker安装MaxKB
  • 【论文阅读】DETR3D: 3D Object Detection from Multi-view Images via 3D-to-2D Queries
  • 边缘智能体:Go编译在医疗IoT设备端运行轻量AI模型(中)
  • 【HTML】3D动态凯旋门
  • 【SpringBoot】15 核心功能 - Web开发原理 - 请求处理 - 常用请求参数注解
  • 【SpringBoot】Dubbo、Zookeeper
  • 【完整源码+数据集+部署教程】鳄梨表面缺陷检测图像分割系统源码和数据集:改进yolo11-MLCA
  • C语言第九章字符函数和字符串函数
  • Go语言快速入门指南(面向Java工程师)
  • 基于SpringBoot+Vue的养老院管理系统的设计与实现 智能养老系统 养老架构管理 养老小程序
  • 外网-内网渗透测试(文件上传漏洞利用)
  • MySQL事务篇-事务概念、并发事务问题、隔离级别
  • 链表基本运算详解:查找、插入、删除及特殊链表
  • 线段树结合矩阵乘法优化动态规划
  • 如何让你的知识分享更有说服力?
  • 云计算核心技术之云存储技术
  • 【React】简单介绍及开发环境搭建
  • JVM 面试精选 20 题(续)
  • react-quill-new富文本编辑器工具栏上传、粘贴截图、拖拽图片将base64改上传服务器再显示
  • 叉车结构设计cad+三维图+设计说明书
  • 浅看架构理论(一)
  • Parallels Desktop 26 技术预览版免激活下载适配Tahoe 26
  • 【撸靶笔记】第七关:GET - Dump into outfile - String
  • LeetCode算法日记 - Day 16: 连续数组、矩阵区域和
  • [系统架构设计师]信息系统架构设计理论与实践(十二)
  • 第八十四章:实战篇:图 → 视频:基于 AnimateDiff 的视频合成链路——让你的图片“活”起来,瞬间拥有“电影感”!