vmlinux 和普通elf文件的差别 linux kernel加载简述

vmlinux其实也是一个elf格式文件,它和普通elf是有些区别的。

linux下可执行程序格式是elf的。

elf格式的文件中有一个Program Headers,这个数据结构告诉 程序加载器,应该如何把
这个elf文件加载到虚拟地址空间中去执行。

elf格式还有一个数据结构是Section Headers,这个不是用于程序加载,是用于编译、链接的。
因此gcc -c也可以生成目标代码,这些目标代码可能不能直接执行,而是作为一个大型程序的一部分,最后编译器会把这些很多个目标代码链接起来,生成一个可执行的elf文件,这时候就需要Section Headers的信息。

也就是说,可执行程序的elf中一定需要Program Headers。而目标代码可以不需要Program Headers。

普通elf文件生成和执行过程:

以一个含有2个源文件的c程序来说,编译器分别生成2个.o格式的elf文件,然后链接器根据Section Headers中的信息,把这两个.o生成一个可执行的elf文件,这个文件里的Program Headers会告诉加载器如何加载自己。

当在shell中执行这个可执行程序时,链接器读取elf中的相关信息,初始化执行环境,根据elf中信息把二进制的程序加载到虚拟内存中的指定位置,然后跳转到程序入口执行。

linux kernel执行过程
linux kernel是个特殊的程序,它和普通程序有不一样的地方。
普通程序执行时,执行环境都已经搭建好,比如mmu已经打开,而linux kernel执行的开始是没有这样的环境的。

linux kernel需要其他软件的辅助才能执行。
计算机上电后会跳转到固定的位置执行,这时候会有个程序负责对硬件进行简单初始化,
然后从存储介质读取linux kernel 加载到内存,然后跳转到其中的入口。
x86计算机这个过程是由BIOS和类似grub的程序完成的。
arm等是通过uboot等bootloader完成的。

当linux kernel被加载到内存中的时候,这时候通常mmu还没有开启。什么意思呢,这时候应该是使用的物理地址。
跳转到linux kernel的入口后,这时候计算机的执行权利就交给linux kernel了。
如果linux是压缩的,这里的入口会将kernel解压。
然后通常会是一段汇编代码,主要完成地址映射和一些必要的初始化工作。
主要就是建立页表,以便实现地址映射,目的是为了开启mmu以支持虚拟地址。

完成上面步骤后,就可以进入start_kernel函数,这后面就是c语言完成的,这里就不介绍了。

从上面分析看出,内核的加载和普通elf还是有很多不一样的地方,最重要的差别就是其必须完成一部分自举工作,使得mmu可以工作。

猜你喜欢

转载自blog.csdn.net/wdjjwb/article/details/81145255
今日推荐