fork,execve,_exit从第一个程序到所有程序

操作系统启动后到底做了什么

  • CPU Reset → Firmware → Loader → Kernel _start() → 第一个程序 /bin/init → 程序 (状态机) 执行 + 系统调用

  • 操作系统会加载 “第一个程序”

    • 寻找启动程序代码

    • if (!try_to_run_init_process("/sbin/init") ||!try_to_run_init_process("/etc/init") ||!try_to_run_init_process("/bin/init") ||!try_to_run_init_process("/bin/sh"))return 0;panic("No working init found.  Try passing init= option to kernel. ""See Linux Documentation/admin-guide/init.rst for guidance.");
      
    • linux中的pstree的systemd的来历

    • 在这里插入图片描述

fork()

  • 操作系统:状态机的管理者
    • C 程序 = 状态机
      • 初始状态:main(argc, argv)
      • 程序可以直接在处理器上执行
    • 虚拟化:操作系统在物理内存中保存多个状态机
      • 通过虚拟内存实现每次 “拿出来一个执行”
      • 中断后进入操作系统代码,“换一个执行”
  • int fork();
    • 立即复制状态机 (完整的内存)
    • 新创建进程返回 0
    • 执行 fork 的进程返回子进程的进程号
  • 因为状态机是复制的,因此总能找到 “父子关系”
    • 因此有了进程树 (pstree)
    • 在这里插入图片描述

execve()

  • 状态机管理:替换状态机
    • int execve(const char *filename, char * const argv, char * const envp);
      • 执行名为 filename 的程序
      • 允许对新状态机设置参数 argv (v) 和环境变量 envp (e)
      • 刚好对应了 main() 的参数!
  • 环境变量:“应用程序执行的环境”
    • 使用env命令查看
      • PATH: 可执行文件搜索路径
      • PWD: 当前路径
      • HOME: home 目录
      • DISPLAY: 图形输出
      • PS1: shell 的提示符
    • export: 告诉 shell 在创建子进程时设置环境变量
  • _exit()
    • 状态机管理:终止状态机
      • void _exit(int status)
        • 销毁当前状态机,并允许有一个返回值
        • 子进程终止会通知父进程
    • 结束程序执行的三种方法
      • exit(0) - stdlib.h 中声明的 libc 函数
        • 会调用 atexit(清理空间,安全退出)
      • _exit(0) - glibc 的 syscall wrapper
        • 执行 “exit_group” 系统调用终止整个进程 (所有线程)
        • 不会调用 atexit
      • syscall(SYS_exit, 0)
        • 执行 “exit” 系统调用终止当前线程
        • 不会调用 atexit
  • 程序的创建执行和销毁过程
    系统初始化的程序,通常是 init(在一些现代系统如 Fedora、Ubuntu 上通常是 systemd),负责进一步初始化操作系统并启动其他服务或进程。下面,我们将详细探讨在操作系统启动第一个程序后,如何使用 fork, execve, _exit 来创建、执行和销毁程序的过程。

程序的创建、执行和销毁

  1. 初始化和启动首个进程

    • 操作系统通过加载并执行 init 程序(或者在一些系统中是 systemd)开始。这个程序成为系统中的第一个进程(通常是进程号为1)。
  2. 进程的创建 (使用 fork)

    • 当系统需要创建一个新的进程时,init(或任何正在运行的进程)会调用 fork() 系统调用。fork() 创建一个与父进程几乎完全相同的子进程,拥有相同的内存映像和运行状态,但有一个新的唯一进程标识符。
    • 父进程中 fork() 返回新创建的子进程的进程ID,而在子进程中 fork() 返回0。
  3. 进程的执行 (使用 execve)

    • 通常在 fork() 之后,子进程需要运行与父进程不同的代码。为此,子进程会调用 execve() 系统调用,这个调用加载一个新的程序到当前进程的地址空间,并开始执行这个程序,从其 main 函数开始。
    • execve() 需要指定程序的路径、传递给程序的参数列表(argv),以及环境变量列表(envp)。这意味着执行后,子进程的原有代码和数据将被新程序替换。
  4. 进程的终止 (使用 _exit)

    • 当程序执行完成后,它可以通过调用 _exit() 系统调用来终止。这个调用立即结束进程的执行,并将一个状态码返回给操作系统,这个状态码可以被父进程通过 wait() 系列的调用来检索。
    • 使用 _exit() 而不是标准的 exit() 函数,因为后者还会执行标准库注册的各种清理函数(如由 atexit() 注册的函数),这在某些情况下可能不是必需或期望的。

实例:简单的 shell

假设 init 系统已经启动,并且我们需要从一个简化的 shell 启动一个程序,如 ls 命令。以下是这个过程的概述:

  1. Shell 进程调用 fork(),创建一个子进程。
  2. 子进程使用 execve() 调用来加载并运行 ls 命令。
  3. ls 命令执行完成后,子进程调用 _exit() 来结束执行,返回执行结果状态。
  4. Shell 进程使用 wait() 等待子进程结束,并获取其终止状态。

这样,我们就看到了一个完整的程序生命周期:创建、执行和终止,都是通过操作系统提供的系统调用来管理的。

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

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

相关文章

在 Windows 上将 Tomcat 设置为服务并在启动时添加 JVM 参数

在 Windows 上将 Tomcat 设置为服务并在启动时添加 JVM 参数(如 -Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTIONtrue),你需要修改 Tomcat 服务的启动配置。这通常通过使用 tomcat9w.exe(对于 To…

Git的常见面试题

Git 是一种广泛使用的版本控制系统,对于开发者面试来说,了解 Git 相关的知识非常重要。以下是一些常见的 Git 面试题及其答案,这些问题可以帮助你准备软件开发相关的面试。 1. 什么是 Git? 答案:Git 是一个开源的分布…

学成在线 - 第3章任务补偿机制实现 + 分块文件清理

7.9 额外实现 7.9.1 任务补偿机制 问题:如果有线程抢占了某个视频的处理任务,如果线程处理过程中挂掉了,该视频的状态将会一直是处理中,其它线程将无法处理,这个问题需要用补偿机制。 单独启动一个任务找到待处理任…

Java+SpringBoot+JSP实现在线心理评测与咨询系统

前言介绍 随着互联网技术的高速发展,人们生活的各方面都受到互联网技术的影响。现在人们可以通过互联网技术就能实现不出家门就可以通过网络进行系统管理,交易等,而且过程简单、快捷。同样的,在人们的工作生活中,也就…

一体化设计的ATA(FXS网关)设计——电源插头、WiFi、双网口、S口、USB等接口集于一身

目录 集成电源插头集成WiFi集成USB两个网口FXS接口(Phone)集成创新 ATA(FXS网关)已经走过几十年的发展,很难有创新。 下面介绍的这款ATA(FXS网关)通过一体化设计的集成创新,成为一款…

大数据Scala教程从入门到精通第三篇:Scala和Java的关系

一:Scala和Java的关系 1:详解 一般来说,学 Scala的人,都会 Java,而 Scala 是基于 Java 的,因此我们需要将 Scala和 Java 以及 JVM 之间的关系搞清楚,否则学习 Scala 你会蒙圈 Scala可以使用SDK…

爬虫学习:XPath匹配网页数据

目录 一、安装XPath 二、XPath的基础语法 1.选取节点 三、使用XPath匹配数据 1.浏览器审查元素 2.具体实例 四、总结 一、安装XPath 控制台输入指令:pip install lxml 二、XPath的基础语法 XPath是一种在XML文档中查找信息的语言,可以使用它在HTM…

Pycharm导入自定义模块报红

文章目录 Pycharm导入自定义模块报红1.问题描述2.解决办法 Pycharm导入自定义模块报红 1.问题描述 Pycharm 导入自定义模块报红,出现红色下划线。 2.解决办法 打开【File】->【Setting】->【Build,Execution,Deployment】->【Console】->【Python Con…

五分钟解决Springboot整合Mybaties

SpringBoot整合Mybaties 创建maven工程整合mybaties逆向代码生成 创建maven工程 1.通过idea创建maven工程如下图 2.生成的工程如下 以上我们就完成了一个maven工程,接下来我们改造成springboot项目。 这里主要分为三步:添加依赖,增加配置&…

1851G-Vlad and the Mountains

题目链接:Vlad and the Mountains 由题意我们可知,从u到v不管怎么走,山的高度始终不能超过h(st)e,那么问题就转化为了给定q次询问,是否存在一条路径,使得从u到v的所有点的高度不超过h(u)e。那么就可以考虑…

运行一个jar包

目录 传送门前言一、Window环境二、Linux环境1、第一步:环境配置好,安装好jdk2、第二步:打包jar包并上传到Linux服务器3、第三步:运行jar包 三、docker环境1、Linux下安装docker和docker compose2、Dockerfile方式一运行jar包2.1、…

JavaScript学习—JavaScript高级

原型链和继承 在 JavaScript 中,每个对象都有一个原型(prototype),这个原型指向另一个对象。这个链式的原型关系被称为原型链。当访问一个对象的属性时,如果该对象没有该属性,它会沿着原型链向上查找&…

牛客网刷题 | BC80 奇偶统计

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 任意输入一个正整数…

迅饶科技 X2Modbus 网关 AddUser 任意用户添加漏洞复现

0x01 免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删…

如何学好mysql,系统整体+实战课程

为什么要学习mysql MySQL 使用和面试中遇到的问题,很多人会通过搜索别人的经验来解决 ,零散不成体系。实际上只要理解了 MySQL 的底层工作原理,就能很快地直戳问题的本质。 如何学习 一,基础篇。为你深入浅出地讲述 MySQL 核心…

Python运维-文本处理、系统和文件信息监控、外部命令

本节主要目录如下: 一、文本处理 1.1、Python编码解码 1.2、文件操作 1.3、读写配置文件 1.4、解析XML文件 二、系统信息监控 2.1、监控CPU信息 2.2、监控内存信息 2.3、监控磁盘信息 2.4、监控网络信息 2.5、获取进程信息 2.6、实例:常见的…

双非二本找工作前的准备day22

学习目标: 每天复习代码随想录上的题目1-2道算法(时间充足可以继续) 今日碎碎念: 1)昨天赶飞机,哎飞机延误,通宵到的学校,太痛苦啦 2)保持打卡!加油啦&…

【知识点随笔分享 | 第十篇】快速介绍一致性Hash算法

前言: 在分布式系统中,数据的分布和负载均衡是至关重要的问题。一致性哈希算法是一种解决这些挑战的有效工具,它在分布式存储、负载均衡和缓存系统等领域得到了广泛应用。 随着互联网规模的不断扩大,传统的哈希算法在面对大规模…

cmake进阶:变量的作用域(目录作用域与全局作用域)

一. 简介 前面从函数作用域方面学习了变量的作用域,本文从目录作用域方面来学习变量的作用域。 二. cmake进阶:从目录作用域方面学习变量的作用域 1. 目录作用域 什么是目录作用域? 我把这个作用域叫做目录作用域。子目录会将父目录的所…

uniapp打包安卓 使用echarts插件 柱状折线等...

uniapp打包安卓 使用echarts插件 柱状折线等… 因为安卓端没有dom操作所以要使用 renderjs 直接上代码 html <template><view class"content"><viewid"echartsa":prop"viewProp":change:prop"echarts.updateEcharts&quo…