可执行文件的装载与进程

news2024/10/6 14:30:49

进程虚拟地址空间

        每个程序被运行起来以后,它将拥有自己独立虚拟空间地址,这个虚拟地址空间的大学由计算机的硬件平台决定,具体地说是由CPU的位数决定。硬件决定了地址空间的最大理论上限,即硬件的寻址空间大小,比如32位的硬件平台决定了虚拟地址空间的地址为0到2的32次方-1,即0x00000000到0xFFFFFFFF,也就是我们常说的4GB虚拟空间大小,64位硬件平台的虚拟空间地址为0x0到0xFFFFFFFFFFFFFFFF,下面按照32位硬件平台讨论。

        那么到底4GB的进程虚拟地址空间是怎样的分配状态?首先以Linux操作系统为例子,默认情况下,Linux操作系统将进程的虚拟地址空间做了如图1所示分配。

                                                      图1 Linux进程虚拟空间分布

        整个4GB被划分成两部门,其中操作系统本身用去了一部分:从地址0xC0000000到0xFFFFFFFF,共1GB.剩下的从0x00000000地址开始到0xBFFFFFFF共3GB的空间都是留给进程使用的。那么从原则上来说,我们的进程最多可以使用3GB的虚拟空间,也就是说整个进程在执行的时候,所有的代码,数据包括通过C语言malloc等方法申请的虚拟空间之和不可以超过3GB。

装载的方式

        程序执行时所需要的指令和数据必须在内存中才能正常运行,最简单的办法就是将程序运行所需要的指令和数据全部都装入内存,这样程序就可以顺利运行,但是很多情况下程序所需要的内存数量大于物理内存的数量,当内存的数量不够时,根本的解决办法就是添加内存。相对于磁盘来说,内存是昂贵且稀有的,这种情况自计算机磁盘诞生以来一直如此,人们希望能够在不添加内存的情况下让更多的程序运行起来,尽可能有效的利用内存。后来研究发现,程序运行时是有局部性原理的,所以我们可以将程序最常用的部门驻留在内存中,而将一些不太常用的数据存放在磁盘里面,这就是动态装入的基本原理。

        动态装入的思想是程序用到那个模块,就将那个模块装入内存,如果不用就暂时不装入,存放在磁盘中。

页映射

        页映射是虚拟存储进制的一部分,这里我们结合可执行文件的装载来阐述一下页映射是如何被应用到动态装载中去的。页映射也不是一下子就把程序的所有数据和指令都装入内存,而是将内存和所有磁盘中的数据和指令按照"页"为单位划分成若干个页,以后所有的装载和操作的单位就是页。硬件规定的页的大小有4096字节,8192字节,2MB,4MB等,最常用的InteliA32处理器一般都使用4096字节的页,那么512M的物理内存就拥有了512 * 1024 * 1024 / 4096=131072个页。

        为了演示页映射的基本机制,假设我们的32位机器有16KB的内存,每个页大小为4096字节,则公有4个页,如图2所示。

页编号地址
F0        0x00000000-0x00000FFF
F10x00001000-0x00001FFF
F20x00002000-0x00002FFF
F30x00003000-0x00003FFF

                                   图2

        假设程序所有的指令和数据总和为32KB,那么程序总共被分为8个页面。我们将它们编号为P0-P7。很明显,16KB的内存无法同时将32KB的程序装入,那么我们将按照动态装入的原理来进行整个装入过程。如果程序刚开始执行的入口地址为P0,这是装载管理器(我们假设装载过程由一个叫做装载管理器的家伙来控制)发现程序的P0不在内存中,于是将内存F0分配给P0,并且将P0的内容装入F0;运行一段时间以后,程序需要用到F5,于是装载管理器将F5装入F1;就这样,当程序用到P3和P6的时候,它们分别被装入到了F2和F3,图3是映射关系图

                                          图三   页映射与页装载

        很明显,如果这个时候程序只需要P0,P3,P5和P6这4个页,那么程序就能一直运行下去。但是问题很明显,如果这时候程序需要访问P4,那么装载管理器必须做出抉择,它必须放弃目前正在使用的4个内存页中的其中一个来装载P4。至于选择哪个页,我们有很多算法可以选择,比如可以选择F0,因为它是第一个被分配掉的内存页(FIFO,先进先出算法);假设装载器发现F2很少被访问,那么我们可以选择F2(LUR,最少使用算法)。假设我们放弃了F0,那么这个时候F0就装入F4。程序接着按照这样的方式运行。

        这个所谓的装载管理器就是现代的操作系统,更加准确的来讲就是操作系统的存储管理器。目前几乎所有主流操作系统都是按照这种方式装载可执行文件。

从操作系统角度看可执行文件的装载

        从上面页映射的动态装入的方式可以看到,可执行文件中的页可能被装入内存的任何页。比如程序需要P4的时候,它可能被装入F0-F3这4个页中的任意一个。很明显,如果程序使用了物理地址直接进行操作,那么每次页被装入时都需要进行重定位。但是在虚拟存储中,现代的硬件MMU都提供了地址转换的功能。有了硬件的地址转换和页映射机制,操作系统动态加载可执行文件的方式跟静态加载有了很大的区别。

        本节我们将站在操作系统的角度来阐述一个可执行文件如何被装载,并且同时在进程中执行。

进程的建立

        事实上,从操作系统的角度来看,一个进程最关键的特征是它拥有独立的虚拟地址空间。这使得它有别于其他进程。很多时候一个程序被执行同时都伴随着一个新的进程的创建,那么我们就来看看这种最通常的情形:创建一个进程,然后装载相应的可执行文件并且执行。在有虚拟存储的情况下,上述过程最开始只需要做三件事情:

        1、创建一个独立的虚拟地址空        

        2、读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系

        3、将CPU的指令寄存器设置成可执行文件的入口地址,启动运行

        首先是创建虚拟地址空间,我们知道一个虚拟空间由一组页映射函数将虚拟空间的各个页映射至相应的物理空间,那么创建一个虚拟空间实际上并不是创建空间而是创建映射函数所需要的相应的数据结构,在i386的Linux下面,创建虚拟地址空间实际上只是分配一个页目录就可以,甚至不设置页映射关系,这映射关系等到后面程序发生页错误的时候再进行设置。

        

        读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系。上面那一步的页映射关系 函数是虚拟空间到物理内存的映射关系,这一步所做的是虚拟空间与可执行文件的映射关系。我们知道,当程序执行发生页错误时,操作系统将从物理内存中分配一个物理页,然后将该“缺页”从磁盘中读取到内存中,再设置页的虚拟页和物理页的映射关系,它应该知道程序当前所需要的页在可执行文件中的那个位置。这就是虚拟空间与可执行文件之间的映射关系。从某种角度来看,这一步是整个装载过程中最重要的一步,也是传统意义上的"装载"的过程。

        由于可执行文件在装载时实际上是被 映射到虚拟空间,所以可执行文件很多时候又被叫做映射文件。

        让我们考虑最简单的情况,假设我们的ELF可执行文件只有一个代码段“.text”,它的虚拟地址为0x08048000,它在文件中的大小为0x000e1,对齐方式为0x1000。由于虚拟存储的页映射都是以页为单位的,在32位的IntelIA32下一般为4096字节,所以32位ELF的对齐粒度为0x1000。由于该.text段大小不到一个页,考虑到对齐该段占用一个段。所以一旦该可执行文件被装载,可执行文件与可执行文件进程的虚拟空间的映射关系所图4所示

                                 图四     可执行文件与进程虚拟空间

        很明显,这种映射关系只是保存在操作系统内部的一个数据结构。Linux中将进程虚拟空间中的一个段叫做虚拟内存区域(VMA,Virtual Memory Area) 。操作系统创建进程后,会在进程相应的数据结构中设置一个.text段的VMA:它在虚拟空间中的地址为0x08048000-0x08049000,它对应ELF文件中偏移为0的.text,它的属性为只读(一般代码段都是只读),还有一些其他属性。

        将CPU指令寄存器设置成可执行文件入口,启动运行。

页错误

        上面的步骤执行完以后,其实可执行文件的真正指令和数据都没有被装入内存中。操作系统只是通过可执行文件头部的信息建立可执行文件和进程虚拟之间的映射关系而已。假设在上面的例子中,程序的入口地址为0x08048000,即刚好是.text段的起始地址。当CPU开始打算执行这个地址的指令时,发现页面0x08048000-0x08049000是个空页面,于是它就认为这个一个页错误。CPU将控制权交给操作系统,操作系统专门的页错误处理例程来处处理这种情况。这时候我们前面提到的装载过程的第二步建立的数据结构体起到了关键作用,操作系统将查询这个数据结构,然后找到空页面所在的VMA,计算出相应的页面在可执行文件中的偏移,然后再物理内存中分配一个物理页面,将进程中该虚拟页与分配到的物理页之间建立映射关系,然后把控制权再还给进程,进程从刚才页错误的位置重新开始执行。

        随着进程的执行,页错误也会不断产生,操作系统也会为进程分配相应的物理页面来满足进程执行的需求,如图5所示。当然有可能进程所需要的内存会超过可用的内存数量,特别是在有多个进程同时执行的时候,这时候操作系统就需要精心组织和分配物理内存,甚至有时候应将分配给进程的物理内存暂时收回等。

                              图五   页错误 

 

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

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

相关文章

欢迎使用Markdown编辑器

欢迎使用Markdown编辑器欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个…

HTML的常用结构标签(详细)

1.文本标题 &#x1f340; <h1> </h1>~~~<h6> </h6>,从h1到h6字体由大到小 2.段落 &#x1f340; <p> </p> 3.加粗 &#x1f340; <b> </b> 和 <strong> </strong> 4.倾斜 &#x1f340; <i></i&…

[MQ] SpringBoot使用扇型(广播)交换机/主题交换机

✨✨个人主页:沫洺的主页 &#x1f4da;&#x1f4da;系列专栏: &#x1f4d6; JavaWeb专栏&#x1f4d6; JavaSE专栏 &#x1f4d6; Java基础专栏&#x1f4d6;vue3专栏 &#x1f4d6;MyBatis专栏&#x1f4d6;Spring专栏&#x1f4d6;SpringMVC专栏&#x1f4d6;SpringBoot专…

刷式过滤器 不锈钢全自动刷式过滤器

原理概述 当水从进水口进入过滤器滤筒内部&#xff0c;杂质被拦截在过滤筒内壁&#xff0c;过滤后的干净水从出水口流出&#xff0c;当滤筒内壁的杂质越积越多时&#xff0c;自清洗过滤器进出口的压差达到预设值、达到清洗时间或手动预制时&#xff0c;过滤器将开始自清洗过程…

Feng Office 3.7.0.5 - 文件上传

Feng Office 3.7.0.5 - 文件上传 POST /ck_upload_handler.php HTTP/1.1 Host: www.baidu1.com Content-Length: 213 Cache-Control: max-age0 Upgrade-Insecure-Requests: 1 Origin: http://www.baidu1.com Content-Type: multipart/form-data; boundary----WebKitFormBoundar…

Linux基本指令2——时间相关

Linux内核&#xff1a;Centos 7.6 64位 date指令默认的date不适合阅读date 指定格式显示时间&#xff1a; date %Y:%m:%ddate 用法&#xff1a;date [OPTION]... [FORMAT]在显示方面&#xff0c;使用者可以设定欲显示的格式&#xff0c;格式设定为一个加号后接数个标记&#…

AlexNet学习笔记

AlexNet 概述 AlexNet是由2012年ImageNet竞赛参赛者Hinton和他的学生Alex Krizhevsky设计的。 创新点 非线性激活函数ReLU 选取了非线性非饱和的relu函数,ReLU函数的表达式为F(x)max(0&#xff0c;z)。若输入小于0&#xff0c;那么输出为0&#xff1b;若输入大于0&#xff…

内蒙古海天公司企业网的规划与设计

目 录 摘要 I ABSTRACT II 目 录 III 第一章 引 言 - 1 - 第二章 需求分析 - 3 - 2.1 背景分析 - 3 - 2.2 应用需求分析 - 3 - 2.2.1 内蒙古海天公司网的管理策略 - 3 - 2.2.2 网络中服务器简介 - 4 - 2.2.3 操作系统的选择…- 5 - 2.3 安全需求 - 5 - 2.4 网络扩展性需求 - 5 …

JVM 一张图带你了解内存分配过程 搞懂逃逸分析|标量替换|指针碰撞|空闲列表|TLAB

面试题 在栈上分配对象&#xff0c;使用标量替换的目的是什么&#xff1f; 内存分配过程 逃逸分析 如何确定对象是否在栈上进行分配&#xff0c;当然得通过逃逸分析了。 逃逸分析是什么意思呢&#xff1f;我们直接看两段代码 代码1: public Student get(){Student student …

CEAC之《企业信息管理》2

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;微微的猪食小窝 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 微微的猪食小窝 原创 收录于专栏 【CEAC证书】 1在每个文本框、组合框和列表框的属性表中&#xff0c;都可以找到3个属性&#xff0c;分别…

30.nacos做注册中心入门实例(springcloud)

一、新建nacos-client-a 1.因为官方的springboot没有集成nacos的依赖&#xff0c;所以不再使用springboot的官方下载依赖地址 2. 因为我的idea是2019版本&#xff0c;更改了springboot下载路径后&#xff0c;不会自动更新&#xff0c;第一次选中依赖时&#xff0c;仍然时sprin…

回溯算法(回溯搜索法)

回溯是递归的副产品&#xff0c;只要有递归就会有回溯。 回溯算法&#xff0c;不是一个高效的算法&#xff0c;纯暴力算法&#xff0c;实际上是递归算法的一部分&#xff0c;最多再剪枝⼀下。 回溯的本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出我们想要的答案&a…

Mac无法打开CORE Keygen

背景 显示如下图&#xff0c;无法打开CORE Keygen&#xff0c;不要方。一个神器即可解决。 方案-使用UPX&#xff1a; &#xff08;1&#xff09;先安装upx (什么&#xff0c;你说你没有brew&#xff1f;&#xff1f;&#xff1f;看看这篇文章 Mac安装brew_Hero.Lin的博…

一篇文章彻底理解 HDFS 的安全模式

一篇文章彻底理解 HDFS 的安全模式 1 什么是 HDFS 的安全模式 Hdfs 的安全模式&#xff0c;即 HDFS safe mode, 是 HDFS 文件系统的一种特殊状态&#xff0c;在该状态下&#xff0c;hdfs 文件系统只接受读数据请求&#xff0c;而不接受删除、修改等变更请求&#xff0c;当然也…

【攻破css系列——第九天】常规流

文章目录1. 常规流2. 常规流布局2.1 定义2.2 包含块2.3 块盒2.3.1 每个块盒的总宽度&#xff0c;必须等于包含块的宽度2.3.2 每个块盒垂直方向上的auto值2.3.3 百分比取值2.3.4 上下外边距合并&#xff08;margin塌陷&#xff09;2.4 行盒2.4.1 盒子沿着内容延伸2.4.2 宽高不可…

Redis基础入门教程 - 概览

Redis基础教程 欢迎加好友一起讨论问题 知识地图&#xff1a;Redis概述与安装https://blog.csdn.net/lili40342/article/details/127852124Redis的5大数据类型https://blog.csdn.net/lili40342/article/details/127897689Redis的发布和订阅https://blog.csdn.net/lili40342/art…

C++模拟OpenGL库——图片处理及纹理系统(四):UV纹理坐标

目录 引入UV纹理坐标及三角形绘制设置 纹理过滤 引入UV纹理坐标及三角形绘制设置 上图其实不是很直观。 UV坐标要解决的问题就是&#xff1a; 假设我有一张500500的纹理图片&#xff1b; 我要把它映射到一张200200的图片中&#xff1b; 这个问题要怎么去解决。 这里提出…

【附源码】Python计算机毕业设计网络考试系统设计

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

百度第三季度财报前瞻:财务业绩预计将超预期

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 百度&#xff08;BIDU&#xff09;此前于2022年11月8日发布了一份媒体新闻稿&#xff0c;强调其将在2022年11月22日公布其第三季度财报。 分析师预计百度第三季度的财务业绩将有所改善 根据卖方分析师对百度的一致财务预测&…

基于GPU的kokkos加速安装

基于GPU的kokkos加速安装基于GPU的kokkos加速安装1. 安装lammps2. 安装cmake3. cmake相关文件修改4. cmake编译5. 测试安装lammps及相关库的步骤网上很多&#xff0c;这里介绍在前期步骤准备好的情况下&#xff0c;如果in文件中包含反应力 场以及需要通过voronoi库计算应力&…