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

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/
head.o架构初始化代码,被Bootloader执行head-<cpu>.o处理器初始化代码- decompress.o, misc.o 自解压代码
- *.gz. 包含裁剪过符号的vmlinux内核ELF的压缩包
产物:
- zImage 可执行自解压出内核ELF内压缩可执行文件,此外还有衍生的
Image.lz4+resource.img=>boot.img

文件系统 rootfs
有两种可选
- initrd/initramfs 只读虚拟最小文件系统,挂载的ramdisk镜像,安卓方案就是这个。
- 直接挂载储存器分区
/
然后内核就会启动rootfs上用户空间的第一个进程 init
LINUX KERNEL 阶段
init/main.c
无论启动方式如何,最后都会启动内核的start_kernel(void)函数
像内核驱动开发里面经常需要处理的 early_init 的钩子就在这里

浙公网安备 33010602011771号