Linux内核二进制布局详解
Linux内核二进制布局
Linux内核的二进制布局涉及编译后的内核镜像在内存中的结构和段分布,主要分为以下几个关键部分:
1. 内核二进制文件组成
- vmlinux:未经压缩的原始ELF格式内核文件,包含完整的符号信息,通常用于调试。
- bzImage:压缩后的可引导内核镜像(常见于x86架构),由引导加载程序(如GRUB)加载到内存。其结构包括:
- 引导程序(Bootsector):负责实模式初始化。
- setup部分:完成硬件检测和进入保护模式的准备工作。
- 压缩内核:包含压缩的vmlinux镜像和解压代码(如
gunzip
)。
2. 内存中的物理布局(以x86为例)
- 实模式阶段:
- 引导扇区:加载到物理地址
0x7C00
。 - setup部分:通常加载到
0x90000
,负责切换到保护模式。
- 引导扇区:加载到物理地址
- 保护模式阶段:
- 内核解压后的基地址:物理地址
0x100000
(1MB),这是内核代码段(.text
)的起始位置。 - 内核镜像布局:
- **
.text
**:代码段,包含内核核心逻辑。 - **
.rodata
**:只读数据(如字符串常量)。 - **
.data
**:已初始化的全局变量。 - **
.bss
**:未初始化的全局变量(清零区)。 init
段:初始化代码和数据(启动完成后可能被释放)。
- **
- 内核解压后的基地址:物理地址
3. 链接脚本(vmlinux.lds.S)
内核的段布局由链接脚本(如arch/x86/kernel/vmlinux.lds.S
)定义,关键部分包括:
1 | .text : { /* 代码段 */ |
4. 虚拟地址空间布局(x86-64)
内核启动后通过分页机制映射到高地址虚拟内存:
- 内核虚拟基址:
0xffffffff80000000
(起始地址)。 - 直接映射区(Direct Mapping):物理内存与虚拟地址线性映射,范围通常为
0xffff888000000000
。 - vmalloc/IO映射区:动态分配非连续内存。
- 内核代码段:位于虚拟地址
0xffffffff81000000
附近。
5. 关键符号与入口点
- 入口点:
_start
(定义于链接脚本),通常位于.text.head
段。 - 初始化流程:从实模式引导跳转到
startup_32
(32位)或startup_64
(64位),最终调用start_kernel()
进入主初始化逻辑。
6. 架构差异
- ARM:内核通常加载到物理地址
0x8000
(如树莓派),链接地址由设备树(DTB)决定。 - UEFI系统:可能直接加载内核到高地址(如x86_64的
0x200000
)。
总结
Linux内核的二进制布局是启动过程的核心,涵盖从实模式到虚拟内存管理的过渡。理解其布局需结合物理加载地址、链接脚本和架构特性,具体细节可通过objdump -d vmlinux
或readelf -S
工具进一步分析。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!