LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: laowang_buaa

精通initramfs构建step by step

[复制链接]
发表于 2008-10-18 21:55:17 | 显示全部楼层
支持,期待继续!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-19 01:05:49 | 显示全部楼层

(五)initrd

十七、配置内核支持initrd
到目前为止,我们的initramfs都由内核编译系统生成的,并链接到内核中。其实我们也可以用cpio命令生成单独的initramfs,与内核编译脱钩,在内核运行时以initrd的形式加载到内核,以增加灵活性。
首先配置内核使用单独的initrd:在 Device Driver / Block device / 配置目录下,选择 RAM filesystem and RAMdisk ( initramfs/initrd ) support 配置项;再到 General Setup 配置目录项下,将 initramfs source file(s) 配置项原有的内容清空。然后把内核源码树的usr目录下已由内核编译生成的initramfs文件initramfs_data.cpio.gz拷贝到 ~/initramfs-test 目录下,我们先直接用这个文件试验一下 initrd 方式的initramfs的效果。最后,执行make命令重新编译内核后,在QEMU试验环境中,把initrd配置框(linux配置框的下面)的内容写为 ~/initramfs-test/initramfs_data.cpio.gz,指定initrd的文件路径。
好了,试验一下新的initrd方式的initramfs吧,效果跟先前的完全一样。

十八、用cpio命令生成initramfs
cpio命令有三种操作模式:copy-out、copy-in、copy-pass,生成initramfs用的是它的copy-out模式,即把文件打包的操作模式。cpio的copy-out操作模式使用 -o 命令行选项指定。缺省情况下,cpio从标准输入读取输入数据,向标准输出写入输出数据。使用 -I 选项可以指定文件名代替标准输入,使用 -O 选项可以指定文件名代替标准输出,而 -F 选项指定的文件名则根据cpio操作模式的不同可代替标准输入或标准输出。
把~/initramfs-test/image目录下的文件打包成initramfs,执行下面的命令:
find . | cpio -o -H newc | gzip > ../image.cpio.gz
命令执行完毕后,在~/initramfs-test目录下就会生成文件名为imgae.cpio.gz的initramfs。
上面cpio命令的 -H 选项指定打包文件的具体格式,要生成initramfs,只能用newc 格式,如果使用其他格式,内核会打出这样的出错信息:Unpacking initramfs...<0> kernel panic - not syncing: no cpio magic

在QEMU试验环境下试验一下新的initrd方式的initramfs,效果跟先前的完全一样。

十九、cpio命令的其他用法
如果我们要解开一个cpio格式的打包文件,则要使用cpio命令的copy-in操作模式。cpio的copy-out操作模式使用 -i 命令行选项指定。例如,我们想把前一步从内核源码树 usr目录下拷贝的initramfs_data.cpio.gz 展开到~/initramfs-test/initramfs_data目录下,则使用下列命令:
mkdir ~/initramfs-test/initramfs_data
cd ~/initramfs-test/initramfs_data
cpio -i -F ../initramfs_data.cpio.gz --no-absolute-filename
命令执行完毕后,initramfs_data目录下出现多个目录和文件,用diff命令比较initramfs_data与image目录,两者的完全一样。
上面cpio命令的 --no-absolute-filename 选项的作用是展开文件时,去掉文件路径最前面的"/",把绝对路径名变为相对路径名。内核编译时生成的initramfs使用了绝对路径名,所以这个选项必须使用,否则initramfs内文件展开到"/"目录去了,如果你是root用户或有"/"目录的写权限,那么展开的文件就有可能覆盖同名的文件(在文件修改时间新于原有文件),那就糟糕了!
展开文件前,你可能会想先看看打包文件里都有哪些文件,这时就要用 -t 选项了。例如,我们想看看内核编译时生成的initramfs_data.cpio.gz中都有哪些文件,我们就可以用下面的命令:
zcat initramfs_data.cpio.gz | cpio -t
在标准输出中打出文件名列表。
使用 -v 选项可以在cpio命令执行时输出详细信息:在打包或展开文件时,输出已处理的文件名;与 -t 选项连用时,则显示文件的详细信息,类似 ls -l 的输出内容。-V 选项则用打点的方式,显示cpio命令的执行进度信息,一个点代表处理一个文件。


---下节预告---

除了基于initramfs的系统(如第四节的mini linux),通常initramfs都是为安装最终的根文件系统做准备工作,它的最后一步需要安装最终的根文件系统,然后切换到新根文件系统上去。如何实现这一目标,请看下一个step:
精通initramfs构建step by step (六):switch_root
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-10-27 21:16:18 | 显示全部楼层

(六)switch_root

二十、switch_root 命令
除了基于initramfs的系统(如第四节的mini linux),通常initramfs都是为安装最终的根文件系统做准备工作,它的最后一步需要安装最终的根文件系统,然后切换到新根文件系统上去。以往的基于ramdisk 的initrd 使用pivot_root命令切换到新的根文件系统,然后卸载ramdisk。但是initramfs是rootfs,而rootfs既不能pivot_root,也不能umount。为了从initramfs中切换到新根文件系统,需要作如下处理:
(1)删除rootfs的全部内容,释放空间
find -xdev / -exec rm '{}' ';'
(2)安装新的根文件系统,并切换
cd /newmount; mount --move . /; chroot .
(3)把stdin/stdout/stderr 附加到新的/dev/console,然后执行新文件系统的init程序

上述步骤比较麻烦,而且要解决一个重要的问题:第一步删除rootfs的所有内容也删除了所有的命令,那么后续如何再使用这些命令完成其他步骤?busybox的解决方案是,提供了switch_root命令,完成全部的处理过程,使用起来非常方便。
switch_root命令的格式是:
switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGUMENTS_TO_INIT]
其中NEW_ROOT是实际的根文件系统的挂载目录,执行switch_root命令前需要挂载到系统中;NEW_INIT是实际根文件系统的init程序的路径,一般是/sbin/init;-c /dev/console是可选参数,用于重定向实际的根文件系统的设备文件,一般情况我们不会使用;而ARGUMENTS_TO_INIT则是传递给实际的根文件系统的init程序的参数,也是可选的。

需要特别注意的是:switch_root命令必须由PID=1的进程调用,也就是必须由initramfs的init程序直接调用,不能由init派生的其他进程调用,否则会出错,提示:
switch_root: not rootfs
也是同样的原因,init脚本调用switch_root命令必须用exec命令调用,否则也会出错,提示:
switch_root: not rootfs

二十一、实践:用initramfs安装CLFS根文件系统
现在实践一下switch_root命令,用它切换一个CLFS的根文件系统硬盘分区。我的CLFS安装在/dev/sda8硬盘分区,我们就以此为例说明。
我们还是在以前的image目录中构建
(1)改写init脚本
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mdev -s
mount /dev/sda8 /mnt (注意:为了简单,我们直接把CLFS分区写死在init脚本中了)
exec switch_root /mnt /sbin/init   
(2)生成新的initrd
按上一节“精通initramfs构建step by step (五):initrd”描述的cpio命令生成新的initrd。
(3)把新的initrd拷贝到CLFS分区的/boot目录下,改名为clfs-initrd
(4)在GRUB的menu.lst配置文件中增加一个启动项
#test for initramfs of CLFS
title test for initramfs of CLFS (on /dev/sda8)
root (hd0,7)
kernel /boot/clfskernel-2.6.17.13 (注意:并没有向内核传递root参数信息)
initrd /boot/clfs-initrd


全部做完后,重启机器,选择 test for initramfs of CLFS 启动项,机器顺利进入了CLFS系统,我们构建的initramfs用switch_root命令完成了CLFS实际根文件系统的安装和切换。



---下节预告---

在这节里我们直接使用了CLFS本身的内核,它已经包含了CLFS根文件系统的硬盘驱动和文件系统驱动,所以可以顺利地安装CLFS的根文件系统。实际上,initramfs的最重要的功能就是包含大量的硬盘驱动和文件系统驱动,而不需要把所有的驱动程序编译进内核,减少内核大小。initramfs负责在安装实际根文件系统前根据具体的文件系统设备情况加载合适的驱动到内核中,使系统能够正常安装实际的根文件系统。如何在initramfs中增加驱动程序模块,请看下一个step:
精通initramfs构建step by step (七):modules
回复 支持 反对

使用道具 举报

发表于 2008-10-29 10:04:29 | 显示全部楼层
这贴可以当精华贴,强烈顶^_^
期待后续……
回复 支持 反对

使用道具 举报

发表于 2008-11-3 02:24:18 | 显示全部楼层
按步骤做第一部分的时候,出现这样的问题

Unpacking initramfs...<0>Kernel panic - not syncing: bad gzip magic numbers

然后死在那里,google了很久都没有解决。
回复 支持 反对

使用道具 举报

发表于 2008-11-3 08:34:39 | 显示全部楼层
今天早上起来搞定了
原先那个问题是按最简内核编译的时候少了RAM block device support (在device drivers -> block devices里),真是不应该...
但是又遇到qemu提示说没有initial console的问题
我想,是不是手动建的console是不是要放在dev文件下,于是在image文件夹下建了个dev文件夹,把console放进去,再重新编译内核,结果成功了

继续跟着楼主学习!
回复 支持 反对

使用道具 举报

发表于 2008-11-3 15:52:31 | 显示全部楼层
Post by Robinhox;1903061
今天早上起来搞定了
原先那个问题是按最简内核编译的时候少了RAM block device support (在device drivers -> block devices里),真是不应该...
但是又遇到qemu提示说没有initial console的问题
我想,是不是手动建的console是不是要放在dev文件下,于是在image文件夹下建了个dev文件夹,把console放进去,再重新编译内核,结果成功了

继续跟着楼主学习!

呵呵,一个小的选项漏掉了,就要重新编译整个系统,麻烦啊
回复 支持 反对

使用道具 举报

发表于 2008-11-3 17:04:00 | 显示全部楼层
(4)用QEMU试验一下新编译的内核。系统启动后,会打出一句话“please press Enter to active this console”——感觉还不错。但是按下回车键后,系统依然会打出错误信息“-/bin/sh:
can't access tty; job controll off ”。用tty命令看看当前的终端设备文件名:
# tty
/dev/console
它还是console,不是tty设备,所以问题没有解决。不过,reboot和halt命令倒是可以正常工作了。

是不是没有在inittab中加入1:2345:respawn:/sbin/mingetty tty1 ?
回复 支持 反对

使用道具 举报

发表于 2008-11-3 19:13:52 | 显示全部楼层
Good!
Tkx
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-11-7 21:35:19 | 显示全部楼层
Post by Robinhox;1903061
今天早上起来搞定了
原先那个问题是按最简内核编译的时候少了RAM block device support (在device drivers -> block devices里),真是不应该...
但是又遇到qemu提示说没有initial console的问题
我想,是不是手动建的console是不是要放在dev文件下,于是在image文件夹下建了个dev文件夹,把console放进去,再重新编译内核,结果成功了

继续跟着楼主学习!

1、console设备文件是要放在dev下,我写的时候漏掉了,应该是:
mknod -m 600 dev/console c 5 1

2、对initramfs而言,并不需要RAM block device support 的内核选项支持,这个问题我以前特别验证过。出现
Unpacking initramfs...<0> kernel panic - not syncing: no cpio magic
错误的原因很可能是cpio打包文件格式的问题。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表