Chinaunix首页 | 论坛 | 博客
  • 博客访问: 499454
  • 博文数量: 176
  • 博客积分: 4045
  • 博客等级: 上校
  • 技术积分: 2491
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-19 11:23
文章分类

全部博文(176)

文章存档

2011年(7)

2009年(12)

2008年(157)

我的朋友

分类:

2008-06-17 17:24:03

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

 原文地址
阅读(1128) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~