initramfs/initrd作用以及原理

参考

linux 内核启动Initramfs与initrd 及其挂载

制作initramfs/initrd镜像

bing search
linux how to decompress initrd.img file
How to Extract initrd/initramfs to View Content in Linux
https://trendoceans.com/how-to-unpack-initrd-initramfs-to-view-content-in-linux/
How to unpack/uncompress and repack/re-compress an initial ramdisk (initrd/initramfs) boot image file on RHEL 5,6 ?
https://access.redhat.com/solutions/24029
How to Extract and Repackage Initial RAM Disk (initrd)
https://linuxconfig.org/how-to-extract-and-repackage-initial-ram-disk-initrd
initrd/initramfs文件制作及解压
https://blog.csdn.net/qq_42138566/article/details/110954142
深入解析 Linux initramfs:从基础到高级应用
https://blog.csdn.net/weixin_47763623/article/details/143484352
Ubuntu initramfs映像文件的解压 和 打包
https://blog.csdn.net/weixin_53351963/article/details/132125967
目标:添加驱动至Ubuntu 以支持PXE网络部署
问题:Ubuntu启动文件initrd缺少需要的驱动模块
解决办法:解压开initrd文件系统镜像,修改文件系统——添加驱动后,重新打包用于启动
目标:添加驱动至Ubuntu 以支持PXE网络部署
问题:Ubuntu启动文件initrd缺少需要的驱动模块
解决办法:解压开initrd文件系统镜像,修改文件系统——添加驱动后,重新打包用于启动
1.找到/boot目录下启动文件系统镜像
2.解压initramfs系统启动文件
第一种方法:手动解压
(1)先通过binwalk工具分析文件数据
安装 apt intstall binwalk
查看文件压缩格式 file initrd.img-6.11.0.13-generic
initrd.img-6.11.0.13-generic :ASCII cpio archive (SVR4 with no CRC)
通过分析格式,可以知道时gzip,lzba, xz,cpio
解析 sudo binwalk /home/test/Downloads/initrd.img-6.11.0.13-generic >init-img.log
(2)dd命令从文件中截取读取文件数据,分别读出第一层、第二层和第三层
第一层时amd 微码
第二层时amd 微码
第三层时 内存启动的文件,驱动等等
(3)分别通过cpio -i -F 和gunzip 解压开三个包,会得到三个文件夹,第三层包解开后就是我们需要修改的文件系统转存失败重新上传取消​编辑
(4)修改文件系统
(5)添加驱动完毕重新打包这三层包
第二种方法:通过unmkintramfs工具解压出分层文件夹(推荐用这个)
(1)通过Linux unmkintramfs工具解压和提取initramfs镜像文件中的内容到expand目录中:
unmkintramfs initrd.img-6.11.0.13-generic
(2)解压开镜像文件后expand目录的文件如下:
(3)添加驱动,修改文件系统
(4)同上第一种方法打包文件rebuild出initrd启动镜像
Error:
1.如果重新启动系统出现这种情况,是initrd文件系统构建失败,重新按步骤构建即可
新型的initrd的解压方法
https://blog.csdn.net/mingwei6/article/details/117960030

一、简介

Initramfs/initrd则是填充(仅仅是释放文件到rootfs根目录)/扩充(通过挂载其他文件系统类型到rootfs指定目录)rootfs的关键,以保证Linux系统的后续启动。
另外一个好处是,这样配置可以将一些驱动编译成内核模块(把它打包到initramfs中,当然用户工具包也是可以打包的)、从而减小内核img的开销。

1、initrd

在早期的linux系统中,一般只有硬盘或者软盘被用来作为linux根文件系统的存储设备,因此也就很容易把这些设备的驱动程序集成到内核中。
但是现在的嵌入式系统中可能将根文件系统保存到各种存储设备上,包括scsi、sata,u-disk等等。因此把这些设备的驱动代码全部编译到内核中显然就不是很方便。
为了解决这一矛盾,于是出现了基于ramdisk的initrd( bootloader initialized RAM disk )。
Initrd是一个被压缩过的小型根目录,这个目录中包含了启动阶段中必须的驱动模块,可执行文件和启动脚本。
当系统启动的时候,bootloader会把initrd文件读到内存中,然后把initrd文件在内存中的起始地址和大小传递给内核。
内核在启动初始化过程中会解压缩initrd文件,然后将解压后的initrd挂载为根目录,
然后执行根目录中的/linuxrc脚本(cpio格式的initrd为/init,
而image格式的initrd<也称老式块设备的initrd或传统的文件镜像格式的initrd>为/initrc),
您就可以在这个脚本中加载realfs(真实文件系统)存放设备的驱动程序以及在/dev目录下建立必要的设备节点。
这样,就可以mount真正的根目录,并切换到这个根目录中来。

2、initramfs

在linux2.5中出现了initramfs,它的作用和initrd类似,只是和内核编译成一个文件(该initramfs是经过gzip压缩后的cpio格式的数据文件),
该cpio格式的文件被链接进了内核中特殊的数据段.init.ramfs上,
其中全局变量__initramfs_start和__initramfs_end分别指向这个数据段的起始地址和结束地址。
内核启动时会对.init.ramfs段中的数据进行解压,然后使用它作为临时的根文件系统。

二、区别

1.内核配置

make menuconfig
支持Initramfs的内核配置:
General setup->Initial RAM filesystem and RAM disk(initramfs/initrd) support
General setup->Initramfs source file(s)
填写根文件系统的具体路径,如:../out/target/product/tclm6/root
这时,根文件系统编入内核vmlinux\zImage\uImage。
支持initrd的内核配置(需要内核支持内存盘驱动):
General setup->Initial RAM filesystem and RAM disk(initramfs/initrd) support
RamDisk内存盘驱动
Device Drivers->Block devices->RAM block device support
启动参数
Boot options->Default kernel command string
填写如下:mem=32M console=ttySAC0 root=/dev/ram initrd=0xc1000000,0x00600000 ramdisk_size=8192 rw
Linux kernel在自身初始化完成之后,需要能够找到并运行第一个用户程序(这个程序通常叫做“init”程序)。
用户程序存在于文件系统之中,因此,内核必须找到并挂载一个文件系统才可以成功完成系统的引导过程。
在grub中提供了一个选项“root=”用来指定第一个文件系统,
但随着硬件的发展,很多情况下这个文件系统也许是存放在USB设备,SCSI设备等等多种多样的设备之上,
如果需要正确引导,USB或者SCSI驱动模块首先需要运行起来,可是不巧的是,这些驱动程序也是存放在文件系统里,因此会形成一个悖论。
为解决此问题,Linux kernel提出了一个RAM disk的解决方案,
把一些启动所必须的用户程序和驱动模块放在RAM disk中,
这个RAM disk看上去和普通的disk一样,有文件系统,有cache,
内核启动时,首先把RAM disk挂载起来,等到init程序和一些必要模块运行起来之后,再切到真正的文件系统之中。
上面提到的RAM disk的方案实际上就是initrd。
如果仔细考虑一下,initrd虽然解决了问题但并不完美。
比如,disk有cache机制,对于RAM disk来说,这个cache机制就显得很多余且浪费空间;
disk需要文件系统,那文件系统(如ext2等)必须被编译进kernel而不能作为模块来使用。
Linux 2.6 kernel提出了一种新的实现机制,即initramfs。
顾名思义,initramfs只是一种RAM filesystem而不是disk。
initramfs实际是一个cpio归档,启动所需的用户程序和驱动模块被归档成一个文件。
因此,不需要cache,也不需要文件系统。

I. initramfs

详细的initramfs的资料可以参考如下:
(1) 黃敬群先生的blog:深入理解 Linux 2.6 的 initramfs 機制
http://blog.linux.org.tw/~jserv/archives/001954.html
(2) initramfs, a new model for initial RAM
http://www.linuxdevices.com/articles/AT4017834659.html

下面是一些使用initramfs的简单帮助

1. 查看initramfs的内容

# mkdir temp ; cd temp
# cp /boot/initrd.img-2.6.24-16 initrd.img-2.6.24-16.gz
# gunzip initrd.img-2.6.24-16.gz
# cpio -i --make-directories < initrd.img-2.6.24-16

2. 创建initramfs

命令:mkinitramfs, update-initramfs
1) mkinitramfs
# mkinitramfs -o /boot/initrd.img 2.6.24-16
Note: 2.6.24-16是需要创建initramfs的kernel版本号,
如果是给当前kernel制作initramfs,可以用uname -r查看当前的版本号。
提供kernel版本号的主要目的是为了在initramfs中添加指定kernel的驱动模块。
mkinitramfs会把/lib/modules/${kernel_version}/ 目录下的一些启动会用到的模块添加到initramfs中。
2)update-initramfs
更新当前kernel的initramfs
# update-initramfs -u
在添加模块时,initramfs tools只会添加一些必要模块,
用户可以通过在/etc/initramfs-tools/modules文件中加入模块名称来指定必须添加的模块。

II. initrd

目前还是有不少Linux发行版采用initrd(即RAM disk的方式)来实现引导,所以了解一下mkinitrd这个命令也很有必要。

mkinitrd类似于mkinitramfs,是用于生成initrd的一个工具。最基本的用法参考下面:
#mkinitrd /boot/initrd.img $(uname -r)
如果需要指定哪些module在启动时必须load,需要加上--preload=module或者 --with=module这样的选项。
这两者的区别在于--preload指定的module会在/etc/modprobe.d/* 里声明的任何SCSI模块之前被加载,--with指定的module会在/etc/modprobe.d/* 里声明的任何SCSI模块之后被加载。
另外还有一个选项需要被注意,即--builtin=module。
在manual里这个选项的解释是:
Act as if module is built into the kernel being used.
mkinitrd will not look for this module, and will not emit an error if it does not exist.
This option may be used multiple times.
根据上面的解释,可以看出builtin选项另外还有一个取巧的用处。
以我所用的平台Acer Aspire One为例,
我在用mkinitrd制作RAM disk镜像是出现一个错误“No module ohci-hcd found ...”,
遇到这个情况,builtin选项就起作用了,
用--builtin=ohci-hcd, mkinitrd就可以忽略ohci-hcd不存在这个事实了。
posted @   scott_h  阅读(212)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示