说明:本篇是对 http://www.ibm.com/developerworks/cn/linux/l-initrd.html 这篇文章的一点笔记,以及参考一些网络资料。如有疑问,请参考原文。
一. 什么是initrd?
initrd 即 initrd ramdisk, 是指一个临时文件系统(或临时根文件系统)。
我们首先来理清几个问题。
1. 所谓根文件系统,就是指我们Linux里用 / 表示的那个,其它的分区都要挂在 / 下的某个路径下,所以用 / 表示的那个就是根文件系统了。注意initrd是文件系统用还是根文件系统用,这有本质的区别。
2. 根文件系统里的目录结构。这里以我们的pc机上文件系统为例,列出一些常见的目录。
/bin /boot /dev /etc /home /lib /media /mnt /opt /proc /root /sbin
/tmp /usr
在做嵌入式的文件系统的时候,可以根据需要来选取就行了。
3. initrd 的作用
initrd中包含了各种可执行程序和驱动程序,它可以用来挂载实际的根文件系统,然后再将initrd卸载,释放内存。许多嵌入式Linux系统中,initrd就是最终的根文件系统(此时就不能称其为“临时”文件系统了)。
4. “临时”
很多时候都说initrd是临时的,例如在我们pc机上,initrd的生存周期很短,只是到真实文件系统的一个桥梁。但在某些嵌入式设备中,initrd就是永久的根文件系统。
二. 查看initrd的内容(在pc机上)
# mkdir temp ; cd temp
# cp /boot/initrd-2.6.14.2.img initrd-2.6.14.2.img.gz //注意这里先给它加了个.gz后缀
# gunzip initrd-2.6.14.2.img.gz
# cpio -i --make-directories < initrd-2.6.14.2.img
三. 制作initrd
#!/bin/bash
# Housekeeping...
rm -f /tmp/ramdisk.img
rm -f /tmp/ramdisk.img.gz
# Ramdisk Constants
RDSIZE=4000
BLKSIZE=1024
# Create an empty ramdisk image 为了创建 initrd,我们最开始创建了一个空文件,这使用了 /dev/zero(一个由零组成的码流)作为输入,并将其写入到 ramdisk.img 文件中。所生成的文件大小是 4MB(4000 个 1K 大小的块)
dd if=/dev/zero of=/tmp/ramdisk.img bs=$BLKSIZE count=$RDSIZE
# Make it an ext2 mountable file system 使用 mke2fs 命令在这个空文件上创建了一个 ext2(即 second extended)文件系统。这里可以换成其他文件系统,如romfs, cramfs...
/sbin/mke2fs -F -m 0 -b $BLKSIZE /tmp/ramdisk.img $RDSIZE
# Mount it so that we can populate 现在这个文件变成了一个 ext2 格式的文件系统,我们使用 loop 设备将这个文件挂载到 /mnt/initrd 上了
mount /tmp/ramdisk.img /mnt/initrd -t ext2 -o loop=/dev/loop0
# Populate the filesystem (subdirectories) 创建构成根文件系统所需要的子目录:/bin、/sys、/dev 和 /proc。这里只列出了所需要的目录(例如没有库),但是其中包含了很多功能。
mkdir /mnt/initrd/bin
mkdir /mnt/initrd/sys
mkdir /mnt/initrd/dev
mkdir /mnt/initrd/proc
# Grab busybox and create the symbolic links 为了可以使用根文件系统,我们使用了 BusyBox。这个工具是一个单一映像,其中包含了很多在 Linux 系统上通常可以找到的工具(例如 ash、awk、sed、insmod 等)。BusyBox 的优点是它将很多工具打包成一个文件,同时还可以共享它们的通用元素,这样可以极大地减少映像文件的大小。这对于嵌入式系统来说非常理想。将 BusyBox 映像从自己的源目录中拷贝到自己根目录下的 /bin 目录中...然后创建了很多符号链接,它们都指向 BusyBox 工具。BusyBox 会判断所调用的是哪个工具,并执行这个工具的功能。我们在这个目录中创建了几个链接来支持 init 脚本(每个命令都是一个指向 BusyBox 的链接。)
pushd /mnt/initrd/bin
cp /usr/local/src/busybox-1.1.1/busybox .
ln -s busybox ash
ln -s busybox mount
ln -s busybox echo
ln -s busybox ls
ln -s busybox cat
ln -s busybox ps
ln -s busybox dmesg
ln -s busybox sysctl
popd
# Grab the necessary dev files 创建几个特殊的设备文件。我从自己当前的 /dev 子目录中直接拷贝了这些文件,这使用了 -a 选项(归档)来保留它们的属性。
cp -a /dev/console /mnt/initrd/dev
cp -a /dev/ramdisk /mnt/initrd/dev
cp -a /dev/ram0 /mnt/initrd/dev
cp -a /dev/null /mnt/initrd/dev
cp -a /dev/tty1 /mnt/initrd/dev
cp -a /dev/tty2 /mnt/initrd/dev
# Equate sbin with bin
pushd /mnt/initrd
ln -s bin sbin
popd
# Create the init file 生成 linuxrc 文件。在内核挂载 RAM 磁盘之后,它会查找 init 文件来执行。如果没有找到 init 文件,内核就会调用 linuxrc 文件作为自己的启动脚本。我们在这个文件中实现对环境的基本设置,例如挂载 /proc 文件系统。除了 /proc 之外,我还挂载了 /sys 文件系统,并向终端打印一条消息
cat >> /mnt/initrd/linuxrc << EOF
#!/bin/ash
echo
echo "Simple initrd is active"
echo
mount -t proc /proc /proc
mount -t sysfs none /sys
# 调用了 ash(一个 Bourne Shell 的克隆),这样就可以与根文件系统进行交互了。linuxrc 文件然后使用 chmod 命令修改成可执行的。
/bin/ash --login
EOF
# 使用 chmod 命令修改成可执行的
chmod +x /mnt/initrd/linuxrc
# Finish up... 根文件系统就完成了。我们将其卸载掉,然后使用 gzip 对其进行压缩。所生成的文件(ramdisk.img.gz)被拷贝到 /boot 子目录中,这样就可以通过 GNU GRUB 对其进行加载了
umount /mnt/initrd
gzip -9 /tmp/ramdisk.img
cp /tmp/ramdisk.img.gz /boot/ramdisk.img.gz
-仅记录而已
阅读(1260) | 评论(0) | 转发(0) |