目录
一、vmlinux、vmlinuz、zImage、bzImage、uImage
2、initramfs(Initial RAM Filesystem)
一、vmlinux、vmlinuz、zImage、bzImage、uImage
vmlinux
是编译出来的最原始的内核文件,未经压缩的原始Linux内核可执行文件(ELF格式),包含调试符号,体积非常大。
主要用于内核调试(如用GDB分析崩溃),不直接用于启动系统。
vmlinuz
vmlinux
的压缩版本(名称中的 z
表示压缩),去除了调试符号,体积更小,是bzImage/zImage文件的拷贝或指向bzImage/zImage的链接
实际用于系统启动的通用内核文件名称(如 /boot/vmlinuz-<version>
)
zImage
使用gzip压缩的小型内核镜像(适用于老式引导器),大小限制在约512KB
bzImage
Big zImage
,同样压缩但支持更大内核(现代x86系统的标准格式)
大多数x86架构系统的标准启动文件(如 /boot/bzImage-<version>
)
uImage
uboot
专用的内核镜像格式,在zImage/bzImage
前添加U-Boot头(包含加载地址等信息)
嵌入式系统中使用U-Boot引导时必需的文件(如ARM开发板)
二、initrd 和 initramfs
initrd
(Initial RAM Disk)和 initramfs
(Initial RAM Filesystem)都是 Linux 内核在启动过程中使用的临时根文件系统,用于在挂载真正的根文件系统之前提供必要的驱动、工具和脚本。尽管它们的目的一致,但实现方式不同。以下是它们的区别、工作原理及使用场景:
1、initrd(Initial RAM Disk)
基于块设备:
initrd
是一个压缩的磁盘映像(通常是gzip
压缩的ext2
或cramfs
文件系统),由引导加载器(如 GRUB)加载到内存。需要挂载:内核将其视为一个块设备(如
/dev/ram0
),并挂载为临时根文件系统(/
)。固定大小:需要预先分配固定大小的内存,可能导致资源浪费或空间不足。
工作流程
(1)引导加载器(如 GRUB)加载内核(vmlinuz
)和 initrd
到内存。
(2)内核解压 initrd
并挂载为临时根文件系统(/
)。
(3)initrd
中的 /linuxrc
或 /init
脚本执行,加载必要的模块(如磁盘驱动、LVM、加密等)。
(4)脚本挂载真正的根文件系统(如 /dev/sda1
),并切换根目录(pivot_root
或 chroot
)。
(5)真正的 init
进程(如 systemd
或 SysVinit
)接管,initrd
被卸载。
由于其基于块设备,效率较低。且大小固定不够灵活,因此现代 Linux 系统已逐渐淘汰initrd,改用initramfs。
2、initramfs(Initial RAM Filesystem)
基于 tmpfs(内存文件系统):initramfs是一个
cpio
归档文件(通常用gzip
压缩),直接解压到内核的内存文件系统(tmpfs
)。无需挂载:内核直接将其解压到根文件系统,无需额外的块设备驱动。
动态大小:按需使用内存,更高效灵活。
现代标准:从 Linux 2.6 开始成为默认机制。
工作流程
引导加载器 加载内核(
vmlinuz
)和initramfs
到内存。内核将
initramfs
解压到tmpfs
并作为初始根文件系统(/
)。/init
(通常是 shell 脚本或systemd
)执行,加载必要的驱动和工具。挂载真正的根文件系统,并切换根目录(
pivot_root
)。真正的
init
进程接管,initramfs
被释放。
更快的启动速度(无需挂载块设备)。动态调整大小,节省内存。支持更复杂的早期用户空间(如
systemd
在 initramfs 中运行)。
3、initrd vs. initramfs 对比
特性 | initrd | initramfs |
---|---|---|
存储方式 | 块设备(如 /dev/ram0 ) |
tmpfs (内存文件系统) |
格式 | 磁盘映像(ext2 +gzip ) |
cpio 归档(gzip 压缩) |
挂载方式 | 需要挂载为块设备 | 直接解压到内存 |
大小 | 固定大小 | 动态调整 |
性能 | 较慢(需块设备访问) | 更快(直接内存访问) |
现代使用 | 已淘汰(旧系统可能使用) | 现代 Linux 默认机制 |
4. 如何查看和生成 initramfs
(1)查看 initramfs 内容
lsinitramfs /boot/initramfs-$(uname -r).img
# 或
unmkinitramfs /boot/initramfs-$(uname -r).img /tmp/initramfs
(2)生成initramfs
# Debian/Ubuntu(使用 update-initramfs)
update-initramfs -u -k $(uname -r)
# RHEL/CentOS(使用 dracut)
dracut --force /boot/initramfs-$(uname -r).img $(uname -r)
(3)手动创建 initramfs
# 1. 创建一个简单的 initramfs 目录结构
mkdir -p initramfs/{bin,dev,proc,sys}
# 2. 复制必要的工具(如 busybox)
cp /bin/busybox initramfs/bin/
# 3. 创建 init 脚本(必须是可执行的)
echo -e '#!/bin/sh\nmount -t proc proc /proc\nexec /bin/sh' > initramfs/init
chmod +x initramfs/init
# 4. 打包成 cpio.gz
(cd initramfs && find . | cpio -H newc -o | gzip > ../initramfs.cpio.gz)
三、SystemV 和 SystemD 的区别
SystemV 和 SystemD 是 Linux 系统中两种不同的初始化(init)系统,用于管理系统的启动和服务。
特性 | SystemV (SysV) | SystemD |
---|---|---|
启动方式 | 顺序执行脚本(串行) | 并行启动服务 |
运行级别 | 0-6(如 runlevel3=多用户模式) | 使用 target (如 multi-user.target ) |
服务管理 | /etc/init.d/ 脚本 + service /chkconfig |
systemctl + .service 单元文件 |
日志管理 | 依赖 syslog |
内置 journalctl |
依赖管理 | 手动定义启动顺序 | 自动依赖解析 |
默认配置文件 | /etc/inittab |
/etc/systemd/system/default.target |
根据Linux内核驱动流程,在架构有关的汇编代码完成特定初始化后,会调用start_kernel开始内核的初始化工作;
- start_kernel函数中有关根文件系统挂载的简要执行流程概述如下:
start_kernel
→ vfs_caches_init()
→ mnt_init()
→ init_rootfs() // 注册rootfs
→ init_mount_tree() // 挂载rootfs到/
→ rest_init()
→ kernel_init()
→ do_basic_setup()
→ populate_rootfs() // 处理initramfs/initrd
→ 检查/init是否存在?
→ 是:执行init_post() // 用户空间接管
→ 否:prepare_namespace()
→ mount_root() // 挂载真实根文件系统
→ sys_mount(".", "/", MS_MOVE) // 切换根目录
- 其中,rest_init函数中依次创建了三个进程,idle进程,init进程以及kthreadd进程;
- kernel_init函数中调用do_basic_setup函数,解压释放initramfs类型文件系统到rootfs的根目录,其中就必须包括
/init
可执行文件;
对于采用SystemV管理的系统
在系统启动过程中,/init可执行文件通常是init程序本身,在制作initramfs根文件系统时,需要将init程序打包进去,并确保/init指向这个init程序。init程序启动后,会读取/etc/inittab文件来确定系统的默认运行级别,并执行相应的脚本。
具体步骤如下:
- 制作initramfs根文件系统时,将init程序打包进去。
- 创建/init到init程序的软链接。
- init程序启动后,读取/etc/inittab文件,确定系统的默认运行级别。
- 根据运行级别,init程序会执行/etc/rc.d/rc script,该脚本会进一步调用/etc/rc.d/rc<number>脚本(其中<number>是运行级别)。
- /etc/rc.d/rc<number>脚本会启动或停止相应的服务,以完成系统的初始化过程。
对于采用SystemD管理的系统,
- 实际上
/init
可执行文件是systemd的符号链接,所以在init_post函数中执行的用户进程即为systemd; - 在制作initramfs根文件系统时,将systemd程序也打包进去,创建
/init
到systemd的软链接,即可启动systemd; - systemd启动后,完成后续的linux操作系统加载过程。