| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> 可执行文件的装载与进程 -> 正文阅读 |
|
[系统运维]可执行文件的装载与进程 |
目录 可执行文件只有装载到内存中才能被CPU利用。随着MMU( Memory Management Unit )(内存管控单元)的发展、多进程、多用户、虚拟存储的操作系统出现后,其装载变得复杂起来。 一、进程虚拟地址空间程序和进程有什么区分: 程序可以看作代码。进程为执行整个代码的过程。 硬件位数决定了地址空间的上线,如32位的计算机。地址空间为0x0000000-0xFFFFFFFF,为4GB。64位的地址空间为:0x0000000000000000-0xFFFFFFFFFFFFFFFF,为8GB。 同样C语言指针的位数与虚拟地址位数相同。32位的指针位数同样为32位。 内存如何分配的呢?在Linux系统下内存分为两部分,一部分为系统内存1GB,另一部分为用户进程空间3GB,也就是进程空间。Windows上2GB系统内存,2GB为用户进程空间。 在Linux系统中,0x00000000-0xC0000000为进程地址空间,0xC0000000-0XFFFFFFFF为系统地址空间。 PAE (Physical Address Extension) 一个程序使用的地址空间可以超过4GB么?如果是虚拟地址,那么不行。如果是物理地址,那么可以。 ?二、装载方式程序指令需要装在内存中才能顺利运行,很多情况下程序需要的内存数量大于物理内存的数量,并且内存是很昂贵的,我们希望在不加内存的情况下让更多程序运行起来。而程序运行是有局部性原理的,我们可以将程序最常用的部分驻留在内存中,而将一些不常用的数据存放在磁盘里,这是动态装入的基本原理。 2.1 覆盖装入(Overlay)?2.2 页映射页映射将内存和所有磁盘的数据和指令按照 页 为单位分成若干个页,所有装载和操作的单位都是页。以目前的情况,硬件规定页的大小有4096B、8192B、2M、4M等。512M的物理内存有 512*1024*1024/4096这么多页数。 ?如果需要将P4装载,那么需要做出选择,有两种算法,先进先出算法(FIFO)和最少使用算法(LUR)。 ?三、从操作系统角度看可执行文件的装载? ?3.1 进程的建立? ?1. 创建一个独立的虚拟地址空间。 2. 读取可执行文件头,并建立虚拟空间与可执行文件的关系。 3. 将CPU的指令寄存器设置为程序的入口,启动运行。 虚拟地址空间的创建: 总结起来就是:创建页映射函数,将虚拟空间的各个页 映射至物理空间。分配一个页目录,不设置映射关系,到后面发生页错误时再进行设置。 读取可执行文件头: ?缺页时应当知道所需的页在可执行文件的哪一个位置,这便是虚拟空间与可执行文件的映射关系。这很重要。 ? ?有关虚拟内存区域: 将CPU指令寄存器设置为程序入口,启动。? 3.2 页错误?? 页错误: 四、进程虚拟空间分布?4.1 ELF文件链接视图和执行视图映射到进程虚拟地址空间的不值代码段,情况很复杂。 操作系统在装载程序时不关心里面的内容,只关心权限问题,权限由以下几种组合: 1. 以代码段为代表的可读可执行段 2. 以BBS和数据段为代表的可读可写段 3. 以只读数据为代表的只读段,? ?这里的segment从装载的角度重新划分了段,权限类似的放到同一个segment中,系统按照segment来进行可执行文件的映射。 加下来以一段代码为例子。
? ? ? 4.2 堆和栈总结一下:虚拟内存中存着管理进程的地址空间的东西,进程中的栈和堆同样存在VMA中,我们可以通过/proc来查看进程虚拟空间分布。 我们从表中可以看到5个VMA,其中前两个是映射到可执行文件的segment。另外三个没有映射到可执行文件中,?这种VAM叫匿名虚拟内存区域,我们可以看到里面的堆和栈,这几乎存在于所有的进程中。C语言中的malloc就是从堆中申请内存,堆由系统库管理。另一个vdso为内核模块,他的地址在内核空间中。 ?这里继续总结,操作系统通过划分一个一个VMA来管理进程的虚拟空间,基本原则是将相同权限属性的、有相同映像文件的映射为一个VMA,一个进程基本可以区分为如下几种VMA区域: 1. 代码VMA,权限只读,可执行,有映像文件。 2. 数据VMA,权限可读写,可执行,有映像文件。 3. 堆VMA,权限可读写,可执行,无映像文件,匿名,可向上扩展。 4. 栈VMA,权限可读写,不可执行 ? ?4.3 堆的最大申请数量4.4 段地址对齐?4.5 进程栈初始化?? ?这里总结一下,程序将初始化信息压入栈中。main函数里的argc和argv分别对应命令行参数数量、命令行参数字符串指针数组。 五、Linux内核装载ELF过程的简介当我们使用Linux的bash命令执行一个可执行文件时,系统先调用fork()形成一个新的进程,这个新的进程调用execve()来执行ELF可执行文件。原来的bash进程启动返回等待刚才启动的新进程结束,然后继续等待用户输入新的命令。execve被定义在unistd.h中: 这三个参数分别是 执行的程序文件名、执行参数、环境变量。具体如下: ?魔数再现: 下面是很复杂的过程,具体感兴趣还是去读原著吧。。。 ?六、Windows的PE的装载总结一下:就是说Windows的段都是以页为单位,段的起始地址都为4096的整数倍。这样比ELF简单许多,一个段就另起一页,用不到Segment这种概念了,并且PE文件没有那么多段,差不多有代码段、数据段、只读数据段、BSS等。 ? 1. 读取文件第一页,包含DOS头、PE文件头和段表。 2. Rebasing问题 3. 使用段表中提供的信息,将PE文件中所有段 映射到地址空间中相应的位置。 4. 装载DLL 5. 解析导入符号 6. 根据PE指定参数,建立初始化栈和堆 9. 建立主线程并启动进程 ? 小结?介绍了可执行文件的装载过程,页映射的方式以及为什么进行页映射。介绍了虚拟地址中的分布,数据段、代码段、BSS、堆、栈等。? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 15:48:39- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |