欢迎光临散文网 会员登陆 & 注册

Linux内核映像的组成

2023-04-01 08:22 作者:满地是悲伤  | 我要投稿


1. Setup.bin

在内核初始化时,需要一些信息,如显示信息、内存信息。这些信息由工作在实模式下的setup.bin通过bios获取,保存在内核中的变量boot_params,该变量是boot_pramas下的一个实例。

 

实模式:虚地址到实地址转换:DS段寄存器左移4位与偏移地址相加,得到物理地址,最大寻址位是2的20次方,即1Mbyte。可寻址其中的任意地址,所有指令都相当于工作在特权级,直接操作CPU的各种功能,没有安全级别,没有分页功能,没有虚拟地址的概念,只有物理地址。各种寄存器的位宽基本上是16位的(段寄存器为20位)。


保护模式:虚地址到实地址转换经过MMU(内存管理单元),内存管理采用段式+页式的方式,最大寻址位2的32次方,即4G。操作系统工作在最高优先级0上,应用程序则运行在较低优先级。各种寄存器的位宽基本上都是32位的,但是可以兼容同名的16位寄存器,兼容实地址模式,即实地址模式的程序无需再编译即可跑在保护模式下。

 

linux-4.4.153\arch\x86\include\uapi\asm\bootparam.h

linux-4.4.153\arch\x86\boot\video.c

store_video_mode调用函数intcall获取显示方面信息,保存在screen_info

intcall是调用bios中断的封装

0x10是bios提供的显示服务的中断号

查看/linux-4.4.153/arch/x86/boot/bioscall.s

al是低8位寄存器

比较寄存器%al的值和标号3处所占用的1字节

相等则跳转到标号1

否则将寄存器%al的值复制到标号3处的1个字节的空间

再跳转到标号1

        随着新的bios的标准出现,尤其是efi的出现,为了支持新标准,出现新的32位启动协议。在新协议下,由bootloader实现收集这些信息,内核启动不用运行setup.bin,直接跳转到内核的保护模式。

        setup.bin另一个重要的功能就是负责在内核和bootloader之间传递信息。在加载内核的时候,bootloader需要从setup.bin中获取内核是否可重定位、内核对齐的要求、内核建议的加载地址。所以在构建映像的时候,内核需要用到这些信息,setup.bin还不能被放弃。


2. 内核非压缩部分


        内核保护模式部分是经过压缩的,运行前需要解压缩。

        内核在构建的时候压缩了自己,解压缩的时候也要由内核自己完成

        内核在压缩镜像外围添加一些非压缩代码,bootloader在加载内核映像的时候跳转至非压缩部分。这些指令直接送给cpu,负责解压内核的压缩部分。

        非压缩部分还负责内核重定位。

        内核非压缩部分工作在保护模式下,占用内存在完成使命后被释放。


3. Vmlinux

        在编译的时候,kbuild分别构建内核各个子目录中的目标文件,将他们链接为vmlinux。为了缩小内核体积,kbuild删除了vmlinux中的一些不必要的信息,将其命名为vmlinux.bin,最后将vmlinux.bin压缩为vmlinux.bin.gz。默认情况下内核使用gzip压缩。


4. 映像的格式

        bin是binary的缩写,表示文件格式是裸二进制。

        Linux在host environment模式二进制文件是ELF格式,操作系统也提供ELF文件的加载器。但是,操作系统本身工作在freestanding environment下。

        内核版本从2.6开始内核的压缩部分,即vmlinux采用了ELF格式。

        在内核解压镜像后,会跳转到解压映像的开头执行。ELF文件开头是ELF文件头。因此需要一个ELF加载器来加载ELF头部。

        内核非压缩部分调用函数decompress解压内核后,调用parse_elf处理ELF格式的内核映像。

linux-4.4.153\arch\x86\boot\compressed\misc.c

        在ELF中存放代码和数据段的类型是PT_LOAD

        在函数prase_elf中,对于类型是PT_LOAD的段,按照program headers中的信息,将他们移动到链接时指定的物理地址处,即p_paddr,若内核是可重定位的,还要考虑内核实际加载地址和编译时指定的加载地址的差值。

        若bootloader不是”the Xen domain builder”,可以不要保留内核的压缩部分为ELF格式,并且略去启动时进行的prase_elf操作。


1. 将压缩部分链接为裸二进制格式

将传递给命令objdump的参数追加-O binary

linux-4.4.153/arch/x86/boot/compressed/Makefile

1. 注释掉prase_elf

linux-4.4.153\arch\x86\boot\compressed\misc.c


Linux内核映像的组成的评论 (共 条)

分享到微博请遵守国家法律