posts - 297,  comments - 15,  trackbacks - 0
Initrd启动及功能分析 

Initrd这个设计的初衷是用来加载额外内核模块供启动的。可以参考 内核文档 Documentation/initrd.txt。 
在加载完内核后,如果存在initrd,则会执行 initrd 里的 /init。(文档里说的是/linuxrc,在 init/do_mounts_initrd.c 里也是这个,在 init/main.c 里是 /init,具体待考。) 

进入主题:简单说来,initrd 主要功能就一个:找到根分区,把权力交给主系统。 
要完成这个功能,涉及的功能主要有: 
1.有基本的程序运行环境 
2.检测存储设备,创建设备节点 
3.检测文件系统,挂载根文件系统 
4.将权力交给主系统的init 

一.基本的程序运行环境 
initrd 主要有两种格式: 
1. 传统的 ramdisk 
这种格式的好处是还可以返回到 initrd,进行些后继的处理。 
缺点是需要内核的文件系统支持,通常会用 ext2,且更改较为麻烦。 
制作方法: 
dd if=/dev/zero of=initrd bs=1M count=8 
mkfs.ext2 -f -m 0 initrd 
mount -o loop initrd /path/to/ 
在/path/to建立好initrd的系统后 
umount /path/to 
gzip initrd 

2. cpio 格式 
这种格式的好处是内核原生不需要额外的文件系统支持,制作也比较容易。 
制作方法: 
cd /path/to 
find . |cpio -o -H newc |gzip -c > ../initrd.gz 

如果没有特别的需要,通常使用cpio格式。 

找到根文件系统的任务通常是用shell脚本来完成,主要原因是: 
1.体积所限,通常initrd不会做很大,因为它功能很明确单一 
2.方便修改,针对不同硬件/系统通常会做一定更改,编译型语言更改起来较麻烦 

通常使用的shell有busybox的ash,klibc的sh等。 
busybox提供很多功能,可根据自己的需要编译,因为要支持udev等,所以推荐编译成动态链接的。 
klibc是专门设计为小巧的libc,它自带了一些程序,体积很小巧,功能相对busybox提供的不会那么多。 
还有相关的程序。对于很单一的应用用它是合适的,如果想在initrd里实现较复杂功能,使用klibc会显得有些捉襟见肘。
对于动态链接的程序,需要把相应的库和 helper 放进系统中。可用ldd实现这个功能,如: 
$ ldd /bin/busybox 
linux-gate.so.1 => (0xffffe000) 
libcrypt.so.1 => /lib/libcrypt.so.1 (0xb7f30000) 
libm.so.6 => /lib/libm.so.6 (0xb7f0b000) 
libc.so.6 => /lib/libc.so.6 (0xb7de1000) 
/lib/ld-linux.so.2 (0xb7f73000) 
我们也提供了一个程序来自动完成这个工作,见文后参考。 
对于klibc的,一般会有个库文件,例如 /usr/lib/klibc/lib/klibc-KC4v-FjcUUw8mDjRL-kY8PS8U3E.so 
将此文件放在相对initrd的根目录的 /lib 目录下即可。 

需要的设备有: 
mknod dev/console c 5 1 
mknod dev/null c 1 3 
# 如果为ramdisk,最好创建它 
mknod dev/ram0 c 1 0 

二.检测存储设备 
早先有 devfs hotplug等来检测,或是静态创建加载模块以支持存储设备如硬盘,光盘等。 
udev的出现使这个过程转移到用户空间,灵活性大大增强,使这个过程能自动完成。 
对于新版的 udev (大概是>098),完成这一过程只需写好相应的规则,有相应的模块,执行以下命令即可自动加载模块并创建相应的设备节点: 
# 挂载所需文件系统 
mount -t proc none /proc 
mount -t sysfs none /sys 
mount -t tmpfs -o size=10M none /dev 
# 关闭内核消息打印 
echo '0' > /proc/sys/kernel/printk 
# 一些连接 
ln -sf /proc/self/fd /dev/fd 
ln -sf /proc/self/fd/0 /dev/stdin 
ln -sf /proc/self/fd/1 /dev/stdout 
ln -sf /proc/self/fd/2 /dev/stderr 
ln -sf /proc/kcore /dev/core 
# 启动 udev 
/sbin/udevd --daemon 
/sbin/udevtrigger 
/sbin/udevsettle 

三.检测文件系统 
由于各系统和内核的不同,挂载文件系统有时不像我们平时使用的那样,会自动探测,可以使用udev或blkid来识别: 
udev的方法: 
# /lib/udev/vol_id -t /dev/hda5 
xfs 
blkid的方法: 
# blkid 
/dev/hda1: TYPE="ntfs" 
/dev/hda5: LABEL="Gentoo" UUID="78460951-666e-4d29-9d9b-85e9a9b16b62" TYPE="xfs" 
/dev/hda6: TYPE="ntfs" 
/dev/hda8: UUID="c51d3bb4-caee-4150-ae22-7d5931db31f5" LABEL="ROOT" TYPE="reiserfs" 
/dev/hda9: LABEL="Home" UUID="89b31278-b2a3-4626-99c5-e6ca77fe60f0" TYPE="xfs" 
/dev/hda7: LABEL="swap" UUID="8686fb94-560c-4c87-97dd-c5f97bbb6c78" TYPE="swap" 

另外,我们也可以使用UUID或者LABEL的方式来挂载文件系统, 
mount -U 
mount -L 

四.交权给主系统的init 
实现方法主要有 pivot_root 和 switch_root与 run-init。 
在这之前需要对之前挂载的虚拟文件系统与dev转移到主系统。 
mount --move /dev /root/dev 
mount --move /proc /root/proc 
mount --move /sys /root/sys 

1.pivot_root 
传统的做法是用 pivot_root,然而 pivot_root不会自动处理很多工作,如释放initrd所有的内存,执行主系统的init。 
使用方法如下: 
cd /root 
mkdir -p initrd 
pivot_root . initrd 
# 注意 /root 要是合法的设备挂载上的 如 /dev/sda1,如果不是这样,将可能出现错误。 
# 目标目录也需要存在,其它参阅man page 
exec chroot . sh -c 'umount /initrd; exec /sbin/init' dev/console 2>&1 
# 如果不需要清理,也可简单的运行 
exec chroot . /sbin/init 

2.switch_root/run-init 
这两者差别不大,前者是busybox提供的,后者是klibc的。有点区别的是后者可接受 - 开头的参数。 
用法: 
cd /root 
exec switch_root . /sbin/init 
或 
exec run-init . /sbin/init --debug 

至此,initrd的使命完成。 
转自:
posted on 2009-11-19 16:54 chatler 阅读(318) 评论(0)  编辑 收藏 引用 所属分类: Linux_SysAdmin

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2009年11月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

常用链接

留言簿(10)

随笔分类(307)

随笔档案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感觉这个博客还是不错,虽然做的东西和我不大相关,觉得看看还是有好处的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新评论

阅读排行榜

评论排行榜