程序员自我修养阅读笔记——可执行文件的装载过程

本文详细介绍了进程在操作系统中的装载过程,包括虚拟地址空间的概念、装载方式、进程创建过程及虚拟地址空间分布等内容,并对比了Linux ELF和Windows PE两种不同格式的可执行文件的装载流程。

1 可执行文件的装载过程

1.1 进程虚拟地址空间

  一个可执行文件被装载到内存变成程序后(进程和程序的区别在于一个是静态的一个是动态的,程序就是菜谱,进程就是厨师参考菜谱做菜的过程),拥有自己独立的地址空间。该地址空间是一个虚拟的地址空间,在该进程看来该空间内包含内核和自身,32bit系统该空间的大小是4GB,64bit系统是2的64次方-1bit。也就是说,一个程序实际上能够用到的虚拟内存空间实际上是小于理论值的,因为操作系统需要占用。

1.2 装载的方式

  静态装入:将程序执行时所需要的指令和数据全部载入到内存中。
  动态装入:利用程序的局部性原理,仅仅将程序中需要运行的部分装入,类似虚拟页的换入换出。
  动态转入的两种实现:

  • 覆盖装入:覆盖装入的方法把挖掘内存潜力的任务交给了程序员,程序员在编写程序的时候必须手工将程序分割成若干块,然后编写一个小的辅助代码来管理这些模块何时应该驻留内存而何时应该被替换掉;
  • 页映射:页映射是将内存和所有磁盘中的数据和指令按照页为单位划分成若干个页,以后所有的装载和操作的单位就是页,利用页面调度算法进行页面调度。

1.3 进程的创建过程

  一般进程的创建需要做三件事情:

  • 创建独立的虚拟内存空间。进程首次创建时只会分配一个页目录,页映射关系是在有后续发生页错误时进行设置;
  • 读取可执行文件,建立虚拟地址空间和可执行文件的映射关系。系统会根据可执行文件的大小建立相关的映射关系。
  • 将CPU指令寄存器设置成可执行文件的入口,开始进入进程调度循环。

1.4 进程虚拟地址空间分布

1.4.1 ELF文件链接视图和执行视图

  创建进程时,由于可执行文件往往存在多个段,如果针对每个段都单独进行内存映射,这样很容易造成内存的浪费。比如数据段可能就2个字节,但是如果依然按照一个页大小分配,剩余的4k-2的内存都浪费了。如果站在操作系系统的角度看,操作系统并不关心不同段的内容,只关心段的权限(可读?可写?可执行?)。因此可以通过将相同权限的段合并统一进行映射减少内存的浪费。在ELF中多个段的合并的集合就是一个Segment,而Segment中每个段都是相同类型的Section。

  • 代码段可读可执行;
  • 数据段和BSS段可读可写;
  • 只读数据段只读。

  下面利用下面简单的程序展示如何合并

//编译命令clang -static main.c -o main.elf
#include <unistd.h>

int main(){
   
   
    while(1){
   
   
        sleep(1000);
    }

    return 0;
}

  使用readelf -S main.elf查看详细的Section。

Section Headers:
  [Nr] Name              Type             Address           Offset   Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000 0000000000000000  0000000000000000           0     0     0
  [ 1] .note.ABI-tag     NOTE             0000000000400190  00000190 0000000000000020  0000000000000000   A       0     0     4
readelf: Warning: [ 2]: Link field (0) should index a symtab section.
  [ 2] .rela.plt         RELA             00000000004001b0  000001b0 0000000000000228  0000000000000018  AI       0    19     8
  [ 3] .init             PROGBITS         00000000004003d8  000003d8 0000000000000017  0000000000000000  AX       0     0     4
  [ 4] .plt              PROGBITS         00000000004003f0  000003f0 00000000000000b8  0000000000000000  AX       0     0     8
  [ 5] .text             PROGBITS         00000000004004b0  000004b0 000000000008f3d0  0000000000000000  AX       0     
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值