【Linux进程】进程控制(上) {进程创建:fork的用法,fork的工作流程,写时拷贝;进程终止:3种退出情况,退出码,常见的退出方法}

news2024/11/24 8:50:17

一、进程创建

在这里插入图片描述

1.1 fork的初步认识和基本使用

在linux中fork函数是非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

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

返回值:子进程中返回0,父进程返回子进程pid,创建失败返回-1

详细内容请看另一篇文章:
【Linux进程】进程的基本概念 {PCB结构体,进程表,Linux中的task_struct,查看进程,获取进程PID,使用fork创建子进程}


1.2 fork的具体工作流程

在这里插入图片描述

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

  1. 创建:分配新的内核数据结构和内存块(用于加载代码和数据)给子进程
  2. 初始化:将父进程内核数据结构的部分内容拷贝至子进程
  3. 组织管理:添加子进程到系统进程列表当中,交由操作系统管理进程。
  4. 开始执行:fork返回,开始调度器调度,子进程开始执行。

1.3 写时拷贝

在这里插入图片描述

  1. 在进行写入操作之前,父子进程的页表会将他们的地址空间映射到同一段物理内存;
  2. 同时将所有页表项暂时设置成只读权限,表示该页表项指向的物理内存被父子共享不能随意修改。
  3. 当父子任意一方试图进行写入时,与页表项的只读权限发生冲突,操作系统才会将被写入的页表项指向的物理内存拷贝分离;
  4. 并将该页表项的只读权限取消,表示该页表项指向的物理内存被一个进程独占可以直接进行写入。

为什么要进行写时拷贝?

  • 由于进程具有独立性,创建子进程时必须为其分配独有的内核数据结构。

  • 但在子进程创建过程中,并不会为其重新加载一份代码和数据,起初父子进程会共享同一份代码和数据。

  • 由于代码的只读属性,父子共享是没有问题的。但是数据可以被修改,所以必须通过某种方式进行分离。

  • 为什么不在进程创建时直接拷贝分离呢?原因有二:

    1. 分配的数据空间可能不会被立刻用到,空间闲置就是对内存资源的浪费。
    2. 有些数据可能根本不会被子进程访问,或者在运行过程中只会被读取,对于这样的数据没有拷贝分离的必要。
  • 基于这样的原因,操作系统选择了写时拷贝技术将父子进程的数据进行分离,保证了进程的独立性。写时拷贝是一种延时申请技术,可以提高整机内存的使用率

父子进程共享的代码是fork之后的还是所有的?

当然是所有代码都会被父子共享。

  1. 事实上,我们的代码通过编译就变成了二进制指令。程序加载到内存后,每条指令都会有对应的地址。

  2. 由于现代CPU采用并发控制,所有进程在执行过程中都有可能被中断,CPU转而去执行其他进程。当CPU资源再次分配到该进程时,进程当然需要从之前的位置继续执行。进程的执行位置记录在进程上下文中的PC值中,即程序计数器PC(Program Counter)。它是CPU内的寄存器数据,专门用于记录下一条要执行的指令的地址。

  3. 实际上所有的代码都会被父子进程共享。但在创建子进程时,父进程的进程上下文也会拷贝给子进程。由于PC值相同,父子进程会从fork之后的同一个位置开始向下执行。所以看起来就像是共享fork之后的代码一样。当然如果你愿意,子进程也可以去执行fork之前的代码。


1.4 fork的常规用法

  1. 一个父进程希望复制自己,使父子进程同时执行同一个程序的不同代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  2. 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

1.5 fork调用失败的原因

  1. 系统资源不足:当系统中可用的资源(如内存、进程表项等)不足以支持新的进程创建时,fork调用会失败。

  2. 进程数量限制:操作系统可能对同时运行的进程数量进行限制,当已达到最大进程数量时,fork调用会失败。

  3. 系统错误:可能存在其他系统错误导致fork调用失败,例如操作系统内部错误或者硬件故障。

测试代码:父进程不断创建子进程,子进程死循环不退出,直至创建失败!

#include <stdio.h>    
#include <unistd.h>    
    
int main(){    
  int max_proc = 0;    
  while(1)    
  {    
    pid_t id = fork();    
    if(id == -1)    
    {    
      perror("fork error:");    
      printf("max_proc:%d\n", max_proc);    
      return 1;    
    }    
    else if(id == 0)    
    {    
      while(1){    
        sleep(1);    
      }    
    }                                                                                                                            
    else    
    {      
      ++max_proc;    
    }       
  }      
}

运行结果:
在这里插入图片描述
我的虚拟机配置较低,只创建了4093个进程就造成了系统资源不足的问题。此时系统处于崩溃边缘,很多命令无法正常运行。


二、进程终止

在这里插入图片描述

进程终止时会释放占用的系统资源,包括CPU资源和内存空间(内核数据结构和对应的数据和代码),最后结束进程。

2.1 进程的退出情况

  1. 代码跑完,结果正确
  2. 代码跑完,结果不正确
  3. 代码没有跑完,程序崩溃

其中,代码跑完结果是否正确及错误原因通过退出码返回给上一级进程(父进程)

如果程序崩溃,崩溃原因通过退出信号返回给上一级进程


2.2 进程退出码

  1. 进程退出码返回给上一级进程,是用来评判该进程执行结果用的,可以忽略。

  2. 进程退出码用0表示运行成功且结果正确。非0表示运行结果不正确。

  3. 非0值有很多个用于表示不同的错误原因,当程序运行结束后方便定位错误。

  4. 在Linux系统中,退出码是无符号整数,占8位,范围[0,255]。

提示:使用echo $?获取最近一个进程执行完毕后的退出码。

得到退出码后如何将退出码转换成错误描述呢?

在这里插入图片描述

利用strerror函数打印0~15错误码的字符串描述:

在这里插入图片描述

ls 和 kill命令在执行时同样也是进程,进程退出就有退出码:

  1. ls命令的错误描述与其退出码相对应,说明他使用的是库函数的预置退出码方案。

  2. kill命令的错误描述与其退出码不对应,说明他使用的是自定义退出码方案。

  3. 我们的程序可以使用库函数预置的退出码解释方案。当然,如果你愿意也可以自己设计一套退出码解释方案!但是不要随意制定退出码方案,否则会导致误解退出码含义。


2.3 进程退出信号

进程崩溃

在这里插入图片描述

  1. 程序崩溃,崩溃原因通过退出信号返回给上一级进程,退出信号在下一节 “进程等待” 章节的 “进程状态” 部分讲解
  2. 程序崩溃时,退出码无意义。因为return/exit没有被执行,此时的退出码是一个随机值。

2.4 进程常见的退出方法

2.4.1 return语句

  1. return是C/C++语句

  2. 其他函数内的return语句表示该函数退出。

  3. 而main函数内的return语句表示进程退出,return后跟的数字就是退出码。


2.4.2 _exit函数

在这里插入图片描述

  1. _exit是Linux系统调用
  2. _exit在任何地方调用,都表示直接终止进程!
  3. _exit直接终止进程,不考虑缓冲区的问题。

2.4.3 exit函数

在这里插入图片描述

  1. exit是C库函数,底层封装_exit系统调用。

  2. exit在任何地方调用,都表示直接终止进程!

  3. exit在终止进程之前会将缓冲区中的数据刷新到显示器上。

  4. 推荐使用exit终止进程

在这里插入图片描述

注意:我们之前讨论的缓冲区,实际是由C标准库为我们维护的,而不是操作系统。

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

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

相关文章

批量AI智剪:让您的短视频制作更加轻松有趣!

在如今的社交媒体时代&#xff0c;短视频已经成为了人们表达创意和分享生活的重要方式。然而&#xff0c;对于许多人来说&#xff0c;短视频制作却是一项繁琐且技术要求较高的任务。幸运的是&#xff0c;现在有了AI智剪&#xff0c;让您的短视频制作变得更加轻松有趣&#xff0…

java小区物业管理系统

java小区物业管理系统 计算机小区物业管理系统 ssh小区物业管理系统 基于javasshmysql小区物业管理系统的设计与实现 运行环境&#xff1a; JAVA版本&#xff1a;JDK1.8 IDE类型&#xff1a;IDEA、Eclipse都可运行 数据库类型&#xff1a;MySql&#xff08;8.x版本都可&a…

3.18 Bootstrap 列表组(List Group)

文章目录 Bootstrap 列表组&#xff08;List Group&#xff09;向列表组添加徽章向列表组添加链接向列表组添加自定义内容 Bootstrap 列表组&#xff08;List Group&#xff09; 本章我们将讲解列表组。列表组件用于以列表形式呈现复杂的和自定义的内容。创建一个基本的列表组的…

使用 Solon Cloud 的 Jaeger 做请求链路跟踪

<dependency><groupId>org.noear</groupId><artifactId>jaeger-solon-cloud-plugin</artifactId> </dependency>1、描述 分布式扩展插件。基于 jaeger 适配的 solon cloud 插件。基于 opentracing 开放接口提供链路跟踪支持。 2、配置示…

vulnhub打靶--raven

目录 vulnhub--raven1.nmap扫描端口服务2.点击主页service发现wordpress目录&#xff0c;识别为wordpress3.使用wpscan扫描4.扫描网站发现两个用户5.简单尝试下发现michael用户名和密码一致6.提权7.总结 vulnhub–raven 下载地址&#xff1a;raven 1.nmap扫描端口服务 2.点击…

Spring:xml 配置

Bean 配置xml 配置反射模式工厂方法模式Factory Bean 模式配置 在 Spring 中,配置 bean 实例一般使用 xml 配置方式或注解(Annontation) 方式进行配置。 xml 配置 在 xml 配置中分为三种方式,分别为反射模式、工厂方法模式和 Factory Bean 模式。 反射模式:指通过指定 …

IMU和视觉融合学习笔记

利用纯视觉信息进行位姿估计&#xff0c;对运动物体、光照干扰、场景纹理缺失等情况&#xff0c;定位效果不够鲁棒。当下&#xff0c;视觉与IMU融合(VI-SLAM&#xff09;逐渐成为常见的多传感器融合方式。视觉信息与IMU 数据进行融合&#xff0c;根据融合方式同样可分为基于滤波…

【NLP】视觉变压器与卷积神经网络

一、说明 本篇是 变压器因其计算效率和可扩展性而成为NLP的首选模型。在计算机视觉中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;架构仍然占主导地位&#xff0c;但一些研究人员已经尝试将CNN与自我注意相结合。作者尝试将标准变压器直接应用于图像&#xff0c;发现在…

4.2 Bootstrap HTML编码规范

文章目录 Bootstrap HTML编码规范语法HTML5 doctype语言属性IE 兼容模式字符编码引入 CSS 和 JavaScript 文件HTML5 spec links 实用为王属性顺序布尔&#xff08;boolean&#xff09;型属性减少标签的数量JavaScript 生成的标签 Bootstrap HTML编码规范 语法 用两个空格来代替…

【Verilog】乒乓操作

文章目录 乒乓操作乒乓操作简单介绍乒乓操作的处理流程代码参考功能代码testbench波形文件 乒乓操作应用场景何时考虑使用乒乓操作乒乓操作的三个优点具体实现分析不间断地处理数据&#xff0c;无缝缓冲与处理可以节约缓冲区空间用低速模块处理高速数据流 乒乓操作 乒乓操作简…

光电器件的种类、原理和应用

光电器件是指能够将光信号转换成电信号或者将电信号转换成光信号的器件。它们广泛应用于通信、计算机、医疗、能源和环保等领域。本文将从光电器件的种类、原理和应用三个方面进行论述。 一、光电器件的种类 根据其功能和结构特点&#xff0c;光电器件可以分为多种类型&#…

【基于CentOS 7 的iscsi服务】

目录 一、概述 1.简述 2.作用 3. iscsi 4.相关名称 二、使用步骤 - 构建iscsi服务 1.使用targetcli工具进入到iscsi服务器端管理界面 2.实现步骤 2.1 服务器端 2.2 客户端 2.2.1 安装软件 2.2.2 在认证文件中生成iqn编号 2.2.3 开启客户端服务 2.2.4 查找可用的i…

Spring Boot-3

学习笔记&#xff08;今天又读了好多篇的博客&#xff0c;做个今天的总结&#xff0c;加油&#xff01;&#xff01;&#xff01;&#xff09; PS&#xff1a;快到中伏了&#xff0c;今天还是好热 使用阿里巴巴 FastJson 的设置 1、jackson 和 fastJson 的对比 有很多人已经…

spmvc基本要求

Mvc第一天 今天目标就是将所有的接口相关的注解理解,并且所有的注解都举例写出代码(cdsn上查) 1 mvc的基本概念: mvc: model,view,Controller,简单解释就是模型,视图,控制器.面试会问,md文档这些描述很到位,你可以看看 2 接口注解: (1) Controller/RestController表示当前…

【100天精通python】Day12:面向对象编程_属性和继承的基本语法与示例

目录 1 属性&#xff08;Attributes&#xff09; 1.1 属性的基本语法 1.2 创建用于计算的属性 1.3 属性的安全保护机制 2 继承&#xff08;Inheritance&#xff09; 2.1 继承的基本语法 2.2 方法的重写 2.3 派生类中调用基类的_init_()方法 3 总结 属性是类的特征或数…

记录WordPress安装后我常用的插件

记录WordPress安装后我常用的插件 一、WordPress安装二、插件使用1.添加Astra主题2.Easy Updates Manager2.WP Githuber MD3.WP-Optimize – Cache, Clean, Compress4. WP-PostViews或Post Views Counter5. Easy Table of Contents5. UpdraftPlus Backup/Restore6.WP Super Cac…

【开源项目】低代码数据可视化开发平台-Datav

Datav 基本介绍 Datav是一个Vue3搭建的低代码数据可视化开发平台&#xff0c;将图表或页面元素封装为基础组件&#xff0c;无需编写代码即可完成业务需求。 它的技术栈为&#xff1a;Vue3 TypeScript4 Vite2 ECharts5 Axios Pinia2 在线预览 账号: admin 密码: 123123预…

4.1 Bootstrap UI 编辑器

文章目录 1. Bootstrap Magic2. BootSwatchr3. Bootstrap Live Editor4. Fancy Boot5. Style Bootstrap6. Lavish7. Bootstrap ThemeRoller8. LayoutIt!9. Pingendo10. Kickstrap11. Bootply12. X-editable13. Jetstrap14. DivShot15. PaintStrap 以下是 15 款最好的 Bootstrap…

Zabbix监控安装grafana并配置图形操作

第三阶段基础 时 间&#xff1a;2023年7月20日 参加人&#xff1a;全班人员 内 容&#xff1a; Zabbix监控安装grafana 目录 安装并配置grafana 一、安装Grafana 二、下载安装插件 三、配置grafana 四、Web访问并配置&#xff1a; 安装并配置grafana 一、安装Graf…

微服务之服务注册与发现原理

1. 前言 在传统的开发中&#xff0c;由于提供服务的地址是相对静态的&#xff0c;所以我们只需要找到对应服务的开发人员&#xff0c;然后了解到对应的服务接口地址就可以了。 而在微服务架构开发过程中&#xff0c;如果我们需要调用一个RESTFul风格的API接口&#xff0c;我们…