LinuxSir.cn,穿越时空的Linuxsir!

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

精通initramfs构建step by step

[复制链接]
发表于 2009-2-18 14:02:42 | 显示全部楼层
强贴留名,继续学习。。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-2-18 22:30:07 | 显示全部楼层

(十二)大结局 - 测试一下

三十五、测试一下
通过前十一节的内容,我们可以说已经完全掌握了initramfs构建的方法,那么现在就测试一下,拿一个实际的initramfs来分析,看我们是否能理解多少。
我们选择Debian 4.0 AMD64 版本的initramfs作为目标进行分析,它的initramfs文件是initrd.img-2.6.18-6-amd64。首先用cpio命令把initramfs文件解开,然后打开其中的init脚本文件具体分析。好了,大家利用前面各节的知识开始吧。

作为提示,在这里转载一篇文章,来自http://blog.chinaunix.net/u/12679/showart_429816.html

initrd执行顺序

这是安装过程中的笔记,放这里希望对大家有用。错误之处请指正。

(系统为debian etch, 以安装后默认的initrd.img-2.6.18-5为例)

解开initrd文件:
例如有initrd文件/boot/initrd.img, 用file命令看到这是个gzip压缩的文件,可以用下面的命令解开查看:


代码:
mkdir /boot/myinit
cd /boot/myinit
zcat ../initrd.img | cpio -id(注:用mkinitrd命令默认产生的是cramfs格式的。如果文件格式是压缩的ramfs文件系统,可以直接mount之后查看:mount -t cramfs /boot/initrd.img /mnt/)

如果是2.6内核,因为采用的是cpio压缩,方法如下:
cp /boot/initrd-***.img initrd.img.gz
gunzip initrd.img.gz
mkdir initrd
mv initrd.img initrd
cd initrd
cpio -mdiv < initrd.img


在当前目录下就有一些目录和文件init,其中文件init是启动时加载initrd之后执行的脚本。

目录结构:

/bin/: 文件有busybox, mknod, sh, uname, cat, mount, pivot_root等

--------/sbin/: 文件有modprobe, depmod, udevd, udevdtrigger

--------/lib/: 文件有:
----------------(1) 可执行文件需要的动态库
----------------(2) modules/: 内核模块
----------------(3) udev/: udev需要的可执行文件

--------/lib64/: 文件有:x86_64程序装载器

--------/etc/: 与modprobe, udev相关的配置文件

--------/conf/: 有如下的文件
----------------(1) modules: 列出了需要加载的模块
----------------(2) arch.conf: 设置变量DPKG_ARCH=amd64
----------------(3) initramfs.conf: 定义了一些变量

--------/scripts/:
----------------有如下的文件:
----------------functions: 定义了一些方便使用的函数
----------------local和nfs: mount根目录时执行的脚本,一般mount本地系统,执行local
----------------
----------------有如下的目录,其中放置各阶段执行的脚本:
----------------init_top/
----------------init_premount/
----------------init_bottom/
----------------local_top/
----------------local_premount/
----------------local_bottom/

--------/init: 启动时加载initrd之后执行的脚本


生成initrd文件:

find . |cpio -o --dereference -H newc | gzip -9 > ../initrd.img


init文件执行流程:

--------1) 创建目录/dev, /root, /sys, /proc, /tmp, /var/lock,其中/root是下面根文件系统要mount的位置

--------2) mount系统proc和sys

--------3) 执行脚本/etc/udev/udev.conf,仅定义变量

--------4) mount udev设备:mount -t tmpfs -o size=<xx> udev /dev

--------5) 创建/dev/console, /dev/null, /dev/.initramfs

--------6) 导入/conf目录下的initramfs.conf, /conf/conf.d/目录以及/scripts/functions定义的变量和函数, 并且根据传递的内核参数设置相应的变量,其中比较重要的变量有:
----------------a) rootdelay=<时间>, 加载根文件系统前等待的时间。如果根文件系统在U盘上,一定要在这里或在grub的kernel后加上这个参数,等待发现U盘后再mount根文件系统,否则会出现找不到根文件系统的错误.
----------------b) panic=<时间> 系统panic后,隔多长时间再reboot。当你试验新内核或新initrd,经常panic而不想按开机按钮时可以加上这个参数

--------7) depmod -a 在/lib/modules/<内核版本号>/目录下产生modules.dep文件

--------8) 执行init_top目录下的脚本文件。这里只有一个framebuffer,它处理内核参数video=,vga=,splash等参数, 另外创建节点/dev/tty[0-8]

--------9) 用modprobe按顺序加载/conf/modules列出的模块。注意,udev需要unix模块,否则会出现错误: udevd[606]: error initializing udev socket

--------10) 执行/scripts/init-premount/下的脚本文件。
-------------10.1) 文件thermal: 它根据DPKG_ARCH的不同值加载相应需要的模块,并且加载fan和thermal模块。
-------------10.2) 文件udev: 执行如下过程:
------------------------a) mkdir -p /dev/.udev/db
------------------------b) udevd --daemon 以daemon形式启动udevd,大概用于监视hotplug设备的插拔
------------------------c) mkdir -p /dev/.udev/queue/ (不知道这两个mkdir的用途)
------------------------d) udevtrigger 对于coldplug的设备,(也就是开机前插入的设备),触发设备的uevents,以便内核处理
------------------------e) udevsettle 等待,直到内核uevents事件处理完

--------11) 执行/scripts/local, 它完成mount根文件系统的过程:
----------------11.1) 首先执行local-top/目录下的脚本
------------------------11.1.1) 文件udev_helper:
----------------------------------a) 针对根文件系统设备(如通常的/dev/sda1, /dev/sda2等)不存在的情况,加载了模块ide_generic。我可以针对找不到硬盘的情况,加载模块aic94xx, sd_mod.
----------------11.2) 如果根文件系统设备还不存在,则年等待一段时间(默认180s),过了这段时间还找不到根文件系统设备就panic.
----------------11.3) 取得根文件系统的类型:先看有没有传递参数rootfstype=,如果没有就执行/bin/fstype,如果还不知道文件系统类型就执行/lib/udev/vol_id来取得文件系统类型。
----------------11.4) 执行local-premount/ 下的脚本:
-------------------------11.4.1) 文件resume: (没看太懂)
------------------------------a) 处理传递的resume参数,它指定的是一个分区,格式为resume=LABEL=/dev/sda1或resume=UUID=xxx, 用于suspend to disk
----------------11.5) 根据文件系统类型加载相应的模块,例如如果根文件系统是ext2类型的,就加载ext2(如果没编译进内核)。
----------------11.6)mount根文件系统到/root上
----------------11.7) 执行local-bottom/下的脚本(这里没有脚本)。

--------12) 执行init-bottom/下的脚本:
---------------12.1) 文件udev:
------------------------a) kill掉udevd
------------------------b) nuke /dev/.udev/queue/ (不知啥意思)
------------------------c) 执行/etc/udev/udev.conf 设置变量tmpfs_size=10M
------------------------d) mkdir /dev/.static/dev (注意,这个目录不是在硬盘上创建的)
------------------------e) mount -n -o bind /root/dev /dev/.static/dev 把真实文件系统的/dev目录下的node(在硬盘上) bind到/dev/.static/dev/下
------------------------f) mount -n -o move /dev /root/dev 把tmpfs类型的udev移到真实的文件系统的/dev下,(注意前面一开始就在/dev上mount了udev), 这时真实文件系统的/dev上mount了udev,而原来在硬盘的/dev目录下的node到了/dev/.static/dev下,实际上在硬盘上没有/dev/.static这个目录. (这个不太好理解)
------------------------g) nuke /dev (不知啥意思)
------------------------h) ln -s /root/dev /dev 前面mount -o move之后,目录/dev下什么也没了,这时/root还没真正成为根。这一步使得,如果其它脚本要使用/dev/下的设备文件时不至于找不到。

--------13) mount -n -o move /sys /root/sys

--------14) mount -n -o move /proc /root/proc

--------15) exec run-init /root /sbin/init "$@" </root/dev/console > /root/dev/console 这一步应该是使真实文件系统成为根,并执行它的/sbin/init(没看懂)

注:加载aic94xx时,需要从目录/usr/lib/hotplug/firmware或者/lib/udev/firmware下读入firmware数据,所以还要建立目录usr/lib/hotplug/firmware或者lib/udev/firmware (在initrd的根目录下,即/boot/myinit) ,然后,把aic94xx-seq.fw拷到任何一个目录中。 可以看出,如果把aic94xx编译进内核,就应把firmware数据也放进内核,但这个功能还没实现。参见内核文档Documentation/firmware_class/README的末尾。
回复 支持 反对

使用道具 举报

发表于 2009-3-5 21:14:49 | 显示全部楼层
学习中,支持lz,呵呵
回复 支持 反对

使用道具 举报

发表于 2009-4-29 11:35:23 | 显示全部楼层

高手帮我看看这个问题

自己编的内核2.6.27.14,基本上所有的模块都编入内核了
进入busybox shell 的时候看了一下, 没有hda*  sda*  不知是哪的错
下边是启动时候的截图(vbox)
还有init文件:
1 #!/bin/sh                                                                                                               
  2 mount -t proc proc /proc
  3 mount -t sysfs sysfs /sys
  4 echo /sbin/mdev > /proc/sys/kernel/hotplug
  5 mdev -s
  6 mkdir -p /dev/.udev/db
  7 udevd --daemon
  8 mkdir -p /dev/.udev/queue
  9 udevtrigger
10 udevsettle
11 mount  /dev/hda5 /mnt
12 if [ $? -ne 0 ]
13 then
14     echo "mount /dev/sda5 on /mnt failed."
15     exec /bin/sh
16 else
17     echo "will switch into root ..."
18     killall udevd
19     exec /sbin/switch_root /mnt /sbin/init
20     if [ $? -ne 0 ]
21     then
22         echo "switch into sda5 rootfs failed."
23         exec /bin/sh
24     fi
25 fi

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-1 01:47:43 | 显示全部楼层
内核中是否配置了IDE 或 SCSI硬盘支持?
回复 支持 反对

使用道具 举报

发表于 2009-5-4 09:28:02 | 显示全部楼层

谢谢

Post by laowang_buaa;1981899
内核中是否配置了IDE 或 SCSI硬盘支持?



内核是自己配的(摸索着配的)附件是我的内核config。
不过启动后echo add >> /sys/block/hda/hda5/uevent
然后ls /dev/hda5 存在
然后再挂载,但就是死活挂不上。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-7 23:51:07 | 显示全部楼层

IDE disk和芯片驱动没有配置

对照你前面的贴图,你的内核配置存在的问题:
1、IDE DISK支持未配置
# CONFIG_BLK_DEV_IDEDISK is not set
2、IDE芯片的驱动未配置

# CONFIG_BLK_DEV_PIIX is not set

再给你两个参考资料
http://linuxman.blog.ccidnet.com ... -itemid-280649.html

http://linuxman.blog.ccidnet.com ... -itemid-293122.html
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-7 23:53:46 | 显示全部楼层

IDE disk和芯片驱动没有配置

# CONFIG_BLK_DEV_IDEDISK is not set

# CONFIG_BLK_DEV_PIIX is not set
回复 支持 反对

使用道具 举报

发表于 2009-5-8 17:17:04 | 显示全部楼层

再次感谢,问题解决了

Post by laowang_buaa;1984742
对照你前面的贴图,你的内核配置存在的问题:
1、IDE DISK支持未配置
# CONFIG_BLK_DEV_IDEDISK is not set
2、IDE芯片的驱动未配置

# CONFIG_BLK_DEV_PIIX is not set

再给你两个参考资料
http://linuxman.blog.ccidnet.com ... -itemid-280649.html

http://linuxman.blog.ccidnet.com ... -itemid-293122.html

非常感谢,问题解决了
真是惭愧阿,这俩参考资料里有一个就是去年你帮我解决的一个问题
不过我还有个疑问,就像下边这个例子,得到了“硬盘控制器的型号”,怎么从这个“型号”判断哪一项该编进内核哪一项不该编而且不会漏编呢?(问了好多人未果)
呵呵这个问题可能比较烦,如果有现成资料的话您给个链接也行,或者给几个google的关键字
2)查找关键字,得到硬盘控制器的型号:
00:07.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 ISA (rev 01)

3)配置内核,把对应的驱动程序编译进内核:
Device Driver
|---->DriverATA/ATAPI/MFM/RLL
|---->Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support
  |----->generic/default IDE chipset support
  |----->CI IDE chipset support
    |---->Generic PCI IDE Chipset Support
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-5-13 00:01:56 | 显示全部楼层
Post by yantao123yt;1984935
不过我还有个疑问,就像下边这个例子,得到了“硬盘控制器的型号”,怎么从这个“型号”判断哪一项该编进内核哪一项不该编而且不会漏编呢?(问了好多人未果)
呵呵这个问题可能比较烦,如果有现成资料的话您给个链接也行,或者给几个google的关键字

http://kernel.xc.net/ ,用其中的搜索功能。

from:  http://www.linuxsir.cn/bbs/thread168339.html
回复 支持 反对

使用道具 举报

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

本版积分规则

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