Linux Kernel Init Bootstrap 内核初始化启动

抽象

Bootloader -> kernel 初始化-> 用户空间init进程

内核版本:6.10

入口

现代操作系统已经和以前不一样,不一定是从汇编启动了

  • lecacy BIOS,x86体系为主,arch/x86/boot/bootsect.S 汇编跳转到main入口,新版代码已经看不到了

  • grub 入口

    grub> set root=(hd0,1)
    grub> linux /boot/vmlinuz-3.13.0-29-generic root=/dev/sda1
    grub> initrd /boot/initrd.img-3.13.0-29-generic
    grub> boot
    
  • uefi 入口
    boot.efi

  • uboot 入口(arm体系为主)
    一般使用Image_header结构体+类似bl汇编跳转执行指令来启动kernel_start函数

built-in.a 内核的拓展静态库

defconfig/Makefile/Kbuild的可选开关

  • 内核内置目标 -obj-y
  • 可加载驱动模块-obj-m
  • 库文件目标 -lib-y
    选择Y会编译然后统一AR打成 built-in.a
    选择M会被打成.ko

这里只列举几种,更多见官网文档-Makefile

builtin的都会被内核进程通过 module_init/initcall 链接符号去调用

ELF vmlinux

image
vmlinux(Virtual Memory Linux) 就是我们常说的内核,本身是一个带有调试符号的ELF文件,包含了上面的built-in.a, 虚拟内存

Tips:ELF(Executable and Linkable Format)是UNIX世界的可执行文件,LINUX内核也是一个程序; vmlinux是一个ELF文件,如果是vmlinuz则代表是压缩过的vmlinux。但这里没有UNIX环境所以没办法直接启动。那为什么还编译出ELF呢?因为编译器只能编译出ELF(摊手🤷

zImage/bzImage

一个带有自解压的可引导的可执行二进制程序,通过OBJCOPY\AS\CC\LD等编译器操作将 带有vmlinux的压缩包+自解压程序及其解压所需链接库打在一起,然后用OBJCOPY去除了ELF和符号,加上了BIOS/UEFI/Loader可执行的程序码用于“原始”启动。

原料:主要由 arch//boot/compressed 构成

  • head.o 架构初始化代码,被Bootloader执行
  • head-<cpu>.o 处理器初始化代码
  • decompress.o, misc.o 自解压代码
  • *.gz. 包含裁剪过符号的vmlinux内核ELF的压缩包

产物:

  • zImage 可执行自解压出内核ELF内压缩可执行文件,此外还有衍生的 Image.lz4+ resource.img => boot.img
    image

文件系统 rootfs

有两种可选

  • initrd/initramfs 只读虚拟最小文件系统,挂载的ramdisk镜像,安卓方案就是这个。
  • 直接挂载储存器分区 /

然后内核就会启动rootfs上用户空间的第一个进程 init

LINUX KERNEL 阶段

init/main.c
无论启动方式如何,最后都会启动内核的start_kernel(void)函数
像内核驱动开发里面经常需要处理的 early_init 的钩子就在这里

posted @ 2026-04-16 17:17  蓝天上的云℡  阅读(4)  评论(0)    收藏  举报