从一个ELF程序的加载窥探操作系统内核-(1)

从一个ELF程序的加载窥探操作系统内核-(1)

操作系统加载一个ELF程序看似一个EASY的动作,其实下面隐藏了很多很多OS内核的关键实现,让我们一起来解密其中的流程

作者是一个micro kernel的开发者,在设计动态链接器的时候,在此留下一些笔记,重点参考了以下资料文献

  • 《程序员的自我修养》
  • 《深入理解计算机系统》
  • 《现代操作系统-原理与实现》
  • 《深入理解LINUX内核》
  • 《设计模式/JAVA》
一个ELF程序的构成与运行

这里的ELF程序指的是可执行类型的文件,动态库和静态库也是ELF文件的一种类型。

  • 从ELF的生成角度看
    一个ELF程序由main程序和libs库组成,这里的库分为静态库或者动态库,经过链接器,最终生成ELF可执行文件,也就是最后我们运行的程序。
    在这里插入图片描述

  • 从ELF的运行角度看
    一个ELF程序的运行其实可以看作一个进程的执行,那么我们可以引入经典的LINUX地址空间布局图,理解这个地址空间布局很重要哦!!!
    在这里插入图片描述

左侧描述32位下的整个地址空间的布局,注意这里是虚拟地址

  • 0~3G低端内存
    • 用作用户空间使用,也就是用户态的代码/数据/堆栈等相关资源都要映射到这个地址范围内
  • 3G~4G高端内存
    • 用作内核空间使用,保存内核的代码/数据/堆栈
  • 如果你愿意你可以任意修改这个范围

右侧的图描述了一个进程运行时在虚拟地址空间的布局情况,我们来逐一解析

  1. Reserved区域
    1. 注意这里预留了0x08048000空间,为什么?在哪里实现的?
    2. 为什么:如果我们直接从0x00000000开始,那么我们的ELF程序的起始地址就是0x00000000,这个地址和NULL地址一样了,好像不太吉利。其实你是可以从这个地址开始的,这并不影响什么
    3. 如何做到从这地址开始:我们在ELF的链接文件ld里,在起始地址定义即可
    SECTIONS
    {
        . = 0x08048000;
        .text :
        {
            *(.text .text.*)
        }
    }
    
  2. Code区域
    1. 这里存储了ELF文件的code区域,包括code(代码)和RO(常量字符串等)
    2. 为什么要把代码和常量合二为一,code和常量虽然都是只读,但是code是具有可执行权限的,常量是没有的哦?
    3. 如果把code和ro进行分开映射会导致性能损失,在进行页表映射的时候会映射两次,而且容易造成内存碎片
  3. Data区域
    1. 保存了已初始化的静态变量和全局变量
  4. Bss区域
    1. 保存了未初始化或初始化为0的静态变量和全局变量
    2. BSS区域是不占用文件空间的,在ELF加载时会重新去分配内存空间并清零
    3. 在Mmap时,data和bss区域是合二为一进行映射的,他们都具有相同属性
  5. Heap区域
    1. 用户堆从bss结束后的地址+随机偏移进行分配
    2. 随机偏移是一种安全策略,在栈和mmap中也有运用
    3. 用户堆的内存管理是放在用户态做的,Linux下的heap是由glibc的ptmalloc来实现,当然还有性能更好的jemalloc/tcmalloc
    4. 用户堆的内存管理的初始化操作需要放入crt中实现
    5. glibc下超过128K内存直接从mmap中申请
  6. Mmap区域
    1. mmap区域主要是存放进程所依赖的动态共享库以及用户使用MMAP系统调用申请的Heap/共享内存
    2. mmap的方向是从高到低增长的,这样和Heap区正好形成一个对冲方向,这样能最大化使用地址空间
    3. mmap的随机偏移也是一种安全策略
  7. Stack区域
    1. 存放进程的局部变量/函数参数/函数返回值
    2. 堆栈随机偏移是为了实现栈地址随机化,是一种安全策略
    3. 堆栈的大小有一个最大值,LINUX下默认为8M,但是这个空间可以调整
    4. 堆栈的增长方向和堆是相反的,是向下增长的
未完待续
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值