shell运行可执行文件=fork+exec

2023-05-16

通过一个可执行文件被执行的过程理解进程的深刻性

转自:https://www.cnblogs.com/yilinglingyi/p/4098057.html

  不知大家在平时想过没有,我们放在磁盘(之前我一直认为Windows的C盘是主存,DEF盘是磁盘,哈哈,应该没有像我这样无知的人吧)上的一个可执行文件(或者应用程序)是如何得到执行的,而且为什么我们在写程序的时候怎么感觉程序中的一些变量的地址好像在各个不同的程序中都差不多,同时这个地址到底真正对应的是什么?是我们可执行文件对应所在位置的磁盘地址吗?下面我就以Linux为平台(Windows也一样,只是将命令方式变为图形方式了)为大家详细讲解一下一个可执行文件是如何得到执行的。

  在Linux中当我们打开shell时,我们相当于已经新建了一个进程,这个进程运行的是shell这个应用程序。当在shell中输入一个可执行目标文件的名字时,shell会用fork()函数创建一个新的进程,在这个新进程中调用execve()函数来加载和执行这个可执行文件。

  我准备详细来说明一下这个execve()函数是如何来工作的,比如它是如何将磁盘上的目标文件拷贝到主存中来让CPU运行的?程序中我们所看到的地址到底是什么?带着这些问题我们来一步一步分析。

  首先因为execve()函数是在shell这个进程的子进程中运行的,而子进程必定会拷贝(其实也不是拷贝,要不然这个进程设计的也太臃肿了,是一种叫写时拷贝的机制)很多父进程已存在的内容,所以必须删除掉。

然后它开始映射(看到映射有没有想到数学中叫函数映射的东西,本质上都是一样的)我们可执行文件中的内容,谈到映射那必然是X------>Y,现在Y是我们的可执行文件,那X呢?先给大家补充一点进程中的知识,等补充完了,才能说X。每个进程中都有一个叫页表的东西,页表有很多项,每一项叫页表项(为了简化问题的复杂性我们就假设Linux是一级页表吧),同时在操作系统中一般一个页或者物理块的大小为4KB(对应为12位的页内地址),所以在一个32的操作系统中只需要保存2^20个页表项就可以表示地址从0x00000000到0xffffffff的范围,其中这个地址的后12位为页内地址,而我们在程序中所见到的地址就是这个地址,根本不是什么我们程序对应的物理地址。记住,这个地址并不是真正对应的磁盘或者内存的地址,而是虚拟的,叫虚拟地址。如果现在还不太明白等我全部讲完就会懂的。

讲到这里大家先稍微理解理解,免得看的一头雾水。那我开始,刚刚我们说到进程中的页表项,每一个页表项从开始到结束对应的编号为0x00000-0xfffff(一共2^20个,大家可以画一画),这个页表项主要有两个部分,第一个部分用来指向磁盘的物理块或者内存上的块,第二个部分表明所指向的块是在磁盘上还是内存上或者这部分就根本没用。

那么我们现在可以说X是什么了,就是虚拟地址!说完了X,Y,那还有映射规则呢,对于我们程序中的文本块,数据块,栈,堆等在Linux中分别对应不同的虚拟地址,而且是固定的,对所有程序都一样。这也就可以解释为什么不同的程序不同的变量有时候地址却差不多,因为他们的虚拟地址都是从0x00000000---0xffffffff,因此当他们的变量都保存在栈中时,对应的虚拟地址也很接近。

映射完之后,execve()调用启动代码,启动代码将调用main()函数,大家一定会想现在可执行目标不是还在磁盘上吗?它是怎么拷贝到内存上,然后被CPU执行的呢?确实如此,因此当启动代码将main()函数的虚拟地址传递给CPU时,CPU通过解析虚拟地址发现内存中没有main()相对应的页或者物理块,然后CPU通过进程中的页表项找到我们可执行文件所在的磁盘位置,将磁盘上的块拷贝到内存中,这样CPU就可以顺利的执行我们的程序了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

shell运行可执行文件=fork+exec 的相关文章

  • 如何从 Artifactory 存储库下载最新的工件?

    我需要来自存储库的最新工件 例如快照 人工工厂 http en wikipedia org wiki Software repository Repository managers 该工件需要通过脚本复制到服务器 Linux 我有什么选择
  • sed 错误“未终止的 's' 命令”故障排除

    我正在构建一个script https stackoverflow com questions 4036832 replacing a specific term in an xml file其中 它将用文件夹路径替换 XML 文件中的模式
  • 从 shell 命令调用 SOAP 请求

    我使用curl 向Web 服务发送SOAP 请求 并使用shell 脚本获取响应 请在下面找到我正在使用的命令 curl H Content Type text xml charset utf 8 H SOAPAction d sample
  • 如何通过保持目录结构完整来同步路径中匹配模式的文件?

    我想将所有文件从服务器 A 复制到服务器 B 这些文件在不同级别的文件系统层次结构中具有相同的父目录名称 例如 var lib data sub1 sub2 commonname filetobecopied foo var lib dat
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • sh / Bash shell 脚本中 !# (bang-pound) 的含义是什么?

    我想了解这个 Scala 脚本是如何工作的 usr bin env bash exec scala 0 object HelloWorld def main args Array String println Hello world arg
  • 调用 cat 时 shell 脚本挂起

    我有一个 shell 脚本 它通过电子邮件向我发送通过 crontasks 遇到的错误 如下所示 exec gt output cat shopt s nocasematch if output error output warning t
  • 如果未设置,则从控制台读取 Makefile 变量

    我正在更新一个从外部源访问某些资源的 Makefile 即存在以下形式的规则 External cvs up 对于不受限制的资源 它可以按预期工作 现在 出现了功能漂移 外部资源需要更复杂的登录 因此规则已更改为与此没有太大不同的内容 Ex
  • 检查 Bash 数组中是否存在元素[重复]

    这个问题在这里已经有答案了 我想知道是否有一种有效的方法来检查 Bash 数组中是否存在元素 我正在寻找类似于我可以在Python中做的事情 例如 arr a b c d if d in arr do your thing else do
  • adb shell:无法使用 ESCAPE 键

    I want to use vi when running adb shell Starting vi is easy However I found that the ESC key doesn t seem to get through
  • 无需 root 访问权限即可安装 zsh? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 有可能 以及如何 我确实需要在几台具有 ssh 访问权限 但没有 root 访问权限 的远程计算机上使用此功能 下载 zsh wget O zsh t
  • 如何列出 nginx 中的所有虚拟主机

    有没有一个命令可以列出 CentOS 上 nginx 下运行的所有虚拟主机或服务器 我想将结果通过管道传输到文本文件以用于报告目的 我正在寻找与我用于 Apache 的命令类似的命令 apachectl S 2 gt 1 grep 端口 8
  • shell解析json并循环输出组合变量

    杰斯克喜欢我之前的话题 https stackoverflow com questions 74063588 shell parsing json contains spaces in string 我知道如何解析带有空格的简单 json
  • 比较linux中的两个未排序列表,列出第二个文件中的唯一项

    我有 2 个包含号码列表 电话号码 的文件 我正在寻找一种列出第二个文件中第一个文件中不存在的数字的方法 我尝试过各种方法 comm getting some weird sorting errors fgrep v x f second
  • 如何使用 bash 中提供的工具生成一系列非周末日期?

    我想生成一个文件列表 其中名称包含 filename date 例如file 20111101 file 20120703 开始November 1 2011直到今天 应该不包括周末 Thanks 2011年试试这个 for y in 20
  • PHP exec rm -Rf 不适用于子目录

    我试图删除特定文件夹中的所有内容 但它似乎不会影响子文件夹 但它应该 因为 bash 命令是从控制台执行的 system rm Rf some dir 该命令中不需要星号 如果要与文件一起删除目录 请同时删除斜杠 留下斜杠将删除文件 但保留
  • Grep 递归和计数

    需要在具有大量子目录的目录中搜索文件内的字符串 我在用着 grep c r string here 我怎样才能找到总数量 如何仅输出至少具有一个实例的文件 使用 Bash 的进程替换 这给出了我认为是您想要的输出 如果不是 请澄清问题 gr
  • 在 C# 中编写批处理脚本的好方法是什么?

    我想用 C 编写简单的脚本 我通常会使用 bat 或 4NT btm 文件 复制文件 解析文本 询问用户输入等等 相当简单 但在批处理文件中正确执行这些操作确实很困难 例如没有例外 我熟悉像 AxScript 这样的命令行 脚本 包装器 这
  • 查找并删除超过 x 天的文件或文件夹

    我想删除超过 7 天的文件和文件夹 所以我尝试了 17 07 14 email protected cdn cgi l email protection find tmp mindepth 1 maxdepth 1 ctime 7 exec
  • 将变量插入 sh 脚本命令[重复]

    这个问题在这里已经有答案了 bin sh f set proj dir OutputDir for projname in lib proj1 proj2 do mv scripts projname BYTECODE proj dir s

随机推荐

  • 进程和文件

    进程和文件还有一个类似的地方就是 xff0c 除了0号进程外 xff0c linux系统中任何一个进程都是由其他进程创建的 感觉就像根文件系统 这也让人感受到一种美感
  • Linux系统中的美

    一切皆文件 xff0c 这种极简普适的思想 进程和文件还有一个类似的地方就是 xff0c 除了0号进程外 xff0c linux系统中任何一个进程都是由其他进程创建的 感觉就像根文件系统 这也让人感受到一种美感 用pstree就可以查看进程
  • 一些实战项目(linux应用层编程,多线程编程,网络编程)

    我觉得这个说得比较好 xff0c 不在于项目有多大 xff0c 有多难 xff0c 在于项目是否是自己真正做的 xff0c 自己是否完全消化了 https blog 51cto com 14419148 2416408 https blog
  • 我觉得专注于去学东西就好了,与世无争。

    我觉得专注于去学东西就好了 xff0c 感觉这样与世无争 xff0c 而不是每天去跟别人比外在的 不要老是想着去如何超过别人 xff0c 而是回过头专心地学东西 xff0c 垒实基础 xff0c 这个可能才是根本的 xff0c 而不是老是被
  • 进程的组成

    我发现我还是喜欢基于物理实体的理解 xff0c 或许我更适合去做驱动 就是真正分析到严谨的内存层面上 像研究进程我就想知道它的实体组成是什么样的 xff0c 而不是单纯的一个空洞的名词 xff0c 我觉得这样会理解得更为透彻一些 让我想起考
  • 浅谈nginx多进程模型

    浅谈nginx多进程模型 摘自 xff1a https zhuanlan zhihu com p 60504120 nginx是一款高性能的Web服务器 xff0c 由于它优秀的性能 成熟的社区 完善的文档 xff0c 受到广大开发者的喜爱
  • 原来k8s docker是用go语言写的,和现在所讲的go是一个东西!

    原来k8s docker是用go语言写的 xff0c 这个我在文思的时候 xff0c 那时东哥问我的时候我那时就知道了 xff0c 只是现在才意识到和他们所讲包括亚军弄的go是一个东西 xff01 xff01 xff01 xff01 xff
  • 有码照片还原成无码:谷歌大脑能让模糊人脸变清晰

    转换成为肉眼可辨识的人物图像 在观看岛国教育片的时候 xff0c 往往在不可描述的部位打上了马赛克 xff0c 固然呈现了朦胧美 xff0c 但部分观众依然希望变得更加清晰 现在 xff0c Google Brain 在提升图片分辨率方面取
  • linux c/应用层编程的书没有深入讲一些东西,可以去看Linux内核的书

    我刚刚想明白了一个东西 xff0c 因为我发现Linux c的书和课程都没有深入讲进程 xff0c 也就是应用层编程 xff0c 他们都是讲一些函数的调用 xff0c 我原以为书会讲一下但我发现我买的Linux c的书里面基本没有深入讲 x
  • 进程的创建分为两步,先fork(),再exec()

    终端其实也是一个进程 shell实际上是先fork xff0c 再exec 前台执行的进程都是终端的子进程 其实看pstree也看得出来
  • 关于守护进程

    很多服务都是通过守护进程来提供的比方说各种网络服务 xff0c 比如http服务 xff0c nfs服务等等 xff0c 它都是以守护进程的形式在运行 xff0c 所以以后要写一个后台服务程序 xff0c 就需要通过守护进程的形式来运行 下
  • 多线程编程似乎是个比较重要的东西

    以上拍自 高质量嵌入式linux c编程 我看 高质量嵌入式linux c编程 和 linux c编程完全解密 这两本书都把多线程编程单独放为一章 xff0c 而不是像华清一样放在进程那章讲了 上面截图自linux c程序设计王者归来 熟练
  • 对进程和线程的理解

    我发现我之前对线程的理解是错误的 xff0c 对 xff0c 是错误的 xff0c 导致之前听课没有很好理解 xff0c 和CPU的流水线作业混淆了起来 xff0c 导致你没有很好地理解进程 xff0c 你是真的弄混了 我看了华清的线程 x
  • 我发现应用层编程里面那些函数很多喜欢用指针作形参

    我发现应用层编程里面那些函数很多喜欢用指针作形参 xff0c 你传递一个函数就会用函数指针 xff0c 你传递一个指针那就会用双重指针 最典型的线程的创建函数 我觉得可能就算你写的实际一个东西 xff0c 实际传的可能还是首地址 xff0c
  • 指向void类型的指针

    malloc好像就是这样 xff0c 所以在用malloc的时候都要进行一个类型转换 linux自带的一些函数里面似乎也是这样 xff0c 注意一下
  • Linux C/C++ 学习路线(已拿腾讯、百度 offer)(转载)

    Linux C C 43 43 学习路线 xff08 已拿腾讯 百度 offer xff09 摘自 xff1a https blog 51cto com 14419148 2416408 lee哥说架构 0人评论 4236人阅读 2019
  • 用思维导图理清linux应用层编程那么多函数

    我突然发现Linux应用层编程 xff0c 包括进程编程线程编程那么多函数这几天弄得你很乱 xff0c 记不住理不清对吧 xff0c 真的是折腾了好几天也没有学出感觉 东西多了杂了自然就会想方法去把它理清晰些 xff0c 考研数学 xff0
  • 面向服务器的应用开发一直是Linux软件开发领域的重点

    面向服务器的应用开发一直是Linux软件开发领域的重点 xff0c 而Linux高性能服务器应用的开发则是重点中的难点 怪不得还有 Linux多线程服务端编程 这本书 xff0c 这两本书都说明了服务器应用的开发可能是Linux软件开发的重
  • GAN|生成对抗网络的前沿进展(论文、框架&资源)全面总结

    成模型 xff08 GenerativeModel xff09 是一种可以通过学习训练样本来产生更多类似样本的模型 在所有生成模型当中 xff0c 最具潜力的是生成对抗网络 xff08 Generative Adversarial Netw
  • shell运行可执行文件=fork+exec

    通过一个可执行文件被执行的过程理解进程的深刻性 转自 xff1a https www cnblogs com yilinglingyi p 4098057 html 不知大家在平时想过没有 xff0c 我们放在磁盘 xff08 之前我一直认