首页 > 代码库 > 程序员的自我修养-链接、装载与库-6 可执行文件的装载与进程

程序员的自我修养-链接、装载与库-6 可执行文件的装载与进程

   可执行文件的装载与进程

  可执行文件只有装载到内存后才能被CPU执行。基本过程就是把程序从外部存储器中读取到内存中的某个位置。

  程序(可执行文件)是一个静态的概念。就是一些预编译好的指令和数据组成的一个文件。进程则是一个动态的概念。很多时候,把动态库叫作运行时。

  每个程序在执行时,都拥有自己独立的 虚拟地址空间。

  虽然,内存中的虚拟地址空间很大,但是任意一个程序都必须在OS的监督下使用资源,不能任意访问或者占用内存。大多数时候我们在Windows下碰到的"进程因非法操作需要关闭" 和 Linux下“”Segmentation fault“错误都是因为访问了未经允许的内存地址。

 32位的操作系统上最多能够支持的物理内存大小为4GB(无PAE情况下) ; 硬件MMU提供地址转换功能;

页映射:

  页映射是虚拟存储机制的一部分,它随着虚拟存储的发明而诞生。页映射不是一下子就把程序的所有数据和指令都装入内存,而是将内存和所有磁盘中的数据和指令按照“页”“Page”为单位划分成若干页,以后装载和操作的基本单位就是页。4096 8192bytes 2Mb 4Mb等。

  换页规则:FIFO先进先出;LUR最少使用算法;

从操作系统的角度看程序的装载:

  创建一个程序然后装载相应的可执行文件并且执行。在有虚拟存储的情况下,上述过程最开始哦需要做三件事情:

  1.创建一个独立的虚拟地址空间。

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

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

 

页错误

  程序在运行的时候,CPU是由程序控制的,一旦发生页错误,也就是所需要访问的页并不在内存中,那就CPU控制权交还给系统。系统有专门负责处理页错误的功能。将上述第二部中的 虚拟地址空间与可执行文件的数据结构,OS查询出该页的虚拟地址,然后找出该页在可执行文件中的偏移量,然后在物理内存中开辟一个页大小的地址,然后将虚拟内存与分配的物理页之间建立映射关系,然后把控制权交还给进程。

技术分享

 

进程虚拟空间分布

  正常情况下,每个页面包含多个段,那么有可能会造成页资源的浪费(很简单因为一个也里面不一定包含页面大小个段)。机智的操作系统找到了一种简单的方案:

  那就是按照段的权限来分类合并到一起当做一个段来进行映射。将小的段Section-》大的段Segment组成一个页映射到内存。这样有效的减少了页面内部碎片,从而节省了内存空间。

  Section与Segment : ELF目标文件按照Section来存储,ELF按照Segment来划分

  技术分享

  ELF可执行文件引入了一个概念“Segment”,一个Segment包含一个或者多个属性类似的“”section“”。

  查看一个ELF可执行文件的Section:

  技术分享

  查看Segment是这样的:

   技术分享

  总的来说,Segment与Section是从不同角度来划分一个ELF文件。在ELF中被称为不同的视图(View)从Section角度看ELF文件就是链接视图(Linking View)

                                                   从Segment的角度来看就是执行视图(Execution View)

段对齐:

  使用Segment装载依然会出现内存浪费的情况,内存利用率很低。机智的OS采用了一个很取巧的办法:就是让那些各个段接壤部分共享一个物理页面。然后将该物理页面映射两次(有两个虚拟内存,让两个段以为是两个地址 )。这种映射方法下,对于一个物理页面可能包含两个段的数据,甚至可能是多个段。

 

  

程序员的自我修养-链接、装载与库-6 可执行文件的装载与进程