[置顶] 泰晓 RISC-V 实验箱,配套 30+ 讲嵌入式 Linux 系统开发公开课
Linux 下的 initrd 映像文件初探
by falcon of TinyLab.org 2008/04/19
简介
如果自己制作过嵌入式 Linux 文件系统,那么应该比较了解 initrd 映像文件是个什么东西了?initrd 即 initial RAM disk,在内核解压之后,在真正的 root filesystem 被启动之前,它被加载到内存中,做一些系统初始化的操作,比如加载内核模块,挂载新的 Root 文件系统等。
initrd 本身是一个文件,内核启动时可以把它展开成一个文件系统。
在 2.6 版本的内核以前,initrd 基于一种特殊的 Loop设备,在展开成一个文件系统前需要通过一种 Loop 设备挂载起来,因为涉及到挂载操作,所以会涉及到一些操作权限。不过在 2.6 版本内核之后出现了 initramfs,它和 initrd 实现同样的功能,但是它基于一种 cpio 档,无须挂载就可以展开成一个文件系统,因此省去了各种相关的权限,在自动化方面更方便了。
initrd 的一个特别有趣的应用是Live CD,比如 Knoppix,它通过 initrd 启动一个初始化的文件系统,然后再通过一个 Cloop 设备挂载一个特别的压缩文件,展开为一个新的 Root 文件系统,这样一个 700M 左右的光盘就能够装下几个 G 的东西,包含大部分的软件和相应的内核模块,进而支持各种各样的功能。
initrd/initramfs 制作
下面简单介绍一下这两种初始化文件系统(initrd 和 initramfs)的制作过程。
先准备一个测试的目录。
$ cd /tmp $ mkdir initrd $ mkdir initrd/loop initrd/cpio
initrd (via a loop device)
首先通过 dd 命令产生一个指定大小的文件。先来计算一下大小,比如要产生一个 1M 大小的文件,那么可以设置该文件的数据块大小为 1024kbyte,然后弄上 1024 块。
$ dd if=/dev/zero of=ramdisk bs=1024 count=1024 $ ls -lh ramdisk -rw-r--r-- 1 falcon falcon 1.0M 2008-04-19 14:59 ramdisk $ file ramdisk ramdisk: data
得到这样一个文件以后就可以把这个文件系统格式化为 ext3 或者是 ext2 的文件系统。
$ mkfs.ext2 ramdisk $ file ramdisk ramdisk: Linux rev 1.0 ext2 filesystem data
如果想往这个文件系统里头添加内容(比如用 busybox 自动的创建一些内容,或者参照 Linux 的根文件系统,从头开始手动制作一个)那么就需要先通过 Loop 设备挂载一下。
不过挂载时需要 Root 用户才行,所以如果你没有 Root 用户的权限,做这个工作就不方便了,从这里就可以看出之后要介绍的 initramfs 的好处了。
$ mount ramdisk /mnt/ -o loop mount: only root can do that $ sudo mount ramdisk /mnt/ -o loop $ ls /mnt/ lost+found $ mount | grep ramdisk /tmp/initrd/loop/ramdisk on /mnt type ext2 (rw,loop=/dev/loop0)
挂载以后只有一个 lost+found
目录,如果要做成一个完整的 initrd,还得做一些工作,创建相应的目录和文件,详细内容可参考该书:Optimizing Embedded Systems using Busybox。
制作完文件系统以后就可以进行“打包”操作,制作成一个可以使用的 initrd 文件。
// 确保各项操作已经写入磁盘 $ sync // 卸载已经挂载的ramdisk $ sudo umount /mnt // “打包”成initrd文件,如果是解压,那么使用gunzip命令,后面直接跟上要解压的文件即可 $ gzip -9 ramdisk $ file ramdisk.gz ramdisk.gz: gzip compressed data, was "ramdisk", from Unix, last modified: Sat Apr 19 17:05:24 2008, max compression
如果想要这个 initrd 映像文件能够正常工作,那么得确保文件系统里头的基本工具都有了,并且确保内核已经编译了相关的支持,比如 Loop 设备的内核支持:
Device Drivers > Block Devices > Loopback Device Support.
以及其他的选项,比如 ext2 文件系统支持等,就可以考虑测试 ramdisk.gz 能不能用了,在 grub 下面可以考虑使用 initrd /path/to/ramdisk.gz
来测试它,而在 lilo 下则通过 initrd 变量来指定 initrd = /path/to/ramdisk.gz
。
initramfs (via a cpio archive)
这种方式仅仅需要把一个符合 Linux 标准的 Root 文件系统所在目录中的文件加到一个 cpio 档里头,然后“打包”即可。
首先,参考后续资料创建一个文件系统。
$ cd /tmp/initrd/cpio // 在这个目录下创建一个符合 Linux标准的 Root 文件系统 $ .... do what you should to do ...
之后是把这个目录下的内容加到一个 cpio 档里头。
$ find . | cpio -c -o > ../ramdisk $ file ../ramdisk ../ramdisk: ASCII cpio archive (pre-SVR4 or odc)
打包(压缩)一下。
$ sync $ cd ../ $ gzip -9 ramdisk $ file ramdisk.gz ramdisk.gz: gzip compressed data, was "ramdisk", from Unix, last modified: Sat Apr 19 17:37:25 2008, max compression
到这里,这个 ramdisk.gz 在 2.6 的内核之后也应该可以类似上面的一样使用了,不过别忘记了加上相应的内核选项,比如(initramfs)初始化文件系统支持。
下面来看看如何对 ubuntu 8.04 中的 initrd 文件“解包”吧。
看当前内核使用的 initrd:
$ ls /boot/initrd.img-`uname -r` /boot/initrd.img-2.6.24-12-generic $ file /boot/initrd.img-2.6.24-12-generic /boot/initrd.img-2.6.24-12-generic: gzip compressed data, from Unix, last modified: Thu Apr 3 18:35:25 2008
“解压”该文件:
$ mkdir /tmp/initrd/current $ cp /boot/initrd.img-2.6.24-12-generic /tmp/initrd/current/ $ cd /tmp/initrd/current/ $ mv initrd.img-2.6.24-12-generic initrd.img-2.6.24-12-generic.gz $ gunzip initrd.img-2.6.24-12-generic.gz $ file initrd.img-2.6.24-12-generic initrd.img-2.6.24-12-generic: ASCII cpio archive (SVR4 with no CRC)
现在展开 cpio 档,并查看里头的内容。
$ cpio -i < ./initrd.img-2.6.24-12-generic $ ls bin conf etc init initrd.img-2.6.24-12-generic lib modules sbin scripts usr var
这样就可以看看 Linux 中的 initrd 文件里头的庐山真面目了。如果有兴趣,可以考虑往里头加点自己的东西,然后通过上面介绍的方法,把它重新“打包”成 initrd 文件,并让 Linux 系统把你”hack”的 initrd 文件加载起来。
参考资料
- man boot-scripts (或 man 7 boot)
- initrd
- Linux initial RAM disk (initrd) overview
- Loop device
- Cloop
- Knoppix
- busybox
猜你喜欢:
- 我要投稿:发表原创技术文章,收获福利、挚友与行业影响力
- 知识星球:独家 Linux 实战经验与技巧,订阅「Linux知识星球」
- 视频频道:泰晓学院,B 站,发布各类 Linux 视频课
- 开源小店:欢迎光临泰晓科技自营店,购物支持泰晓原创
- 技术交流:Linux 用户技术交流微信群,联系微信号:tinylab
支付宝打赏 ¥9.68元 | 微信打赏 ¥9.68元 | |
请作者喝杯咖啡吧 |