制作initrd(1):向initrd内部更新驱动模块

来源:互联网 发布:网上开淘宝店赚钱吗 编辑:程序博客网 时间:2024/05/21 09:51

    从centos到ubuntu,grub从grub1进化到grub2,其配置文件的内容也跟着发生了巨大的变化。但是配置文件中有几项参数一直变化不大:linux root和initrd,一直指向内核镜像 根设备和initrd镜像的路径。就算换到uboot上,依然能见到这三项参数,其重要性可见一斑。3个参数以内核镜像最重要,而initrd却是时有时无的参数。

    虽然initrd的存在感不强,但却是本文核心角色。这起源于最近制作LFS,大部分时间花在制作initrd上;另外公司外包一个小系统出去,其核心部分也是定制initrd。出于这些原因,记录于此以备查阅。

    按grub.cfg的设置,initrd常化名为initrd.img-`uname -r`定居于/boot目录。编译内核代码执行make modules_install后会生成initrd.img,这是一个经cpio打包然后gzip压缩的文件,因此,完全可以把initrd.img解剖了研究。

#file initrd.img-3.13.0initrd.img-3.13.0:gzip compressed data
#mv initrd.img-3.13.0 initrd.img-3.13.0.gz
#gunzip initrd.img-3.13.0.gz
#file initrd.img-3.13.0
initrd.img-3.13.0:ASCII cpio archive
#cpio -i --make-directories < initrd.img-3.13.0 #解包
#ls
bin init run conf sbin etc lib scripts

从initrd.img解压的结果来看,initrd.img文件中也包含了一个跟文件系统的雏形。据悉,如果配置内核源码,使之支持initramfs(make menuconfig时在General setup中选中Inital RAM filesystem and RAM disk选项),当系统启动时,内核会创建一个ramdisk,把initrd.img的内容解压到其中,这样内核中就有一个临时个根文件系统,加载类似scsi驱动。关于这个根文件系统的作用,我将另起一文记录。

    有过嵌入式经验的读者都知道,这个根文件系统中有个至关重要的用户态进程--udev,负责加载模块。上文已经说道这个临时根文件系统会加载scsi模块,可是scsi模块在哪?可以从udev的行为来推出模块路径。udev启动时按/etc/modprobe.d/目录下的规则文件(*.rules)的设置,去/lib/modules/`uname -r`目录下加载模块。由此可知scsi模块路径十有八九在此了:

#以下命令执行在上面被肢解的initrd.img文件夹下#cd lib/modules/3.13.0/kernel/drivers#lsata ... block ... scsi uio

这些模块是执行make modules_install时被安装到/lib/modules/`uname -r`/目录下,而在make modules_install的结尾部分,Makefile会调用mkinitramfs将一些模块添加到initrd中。

    看到这,我觉得大家对initrd有个感性认识了。那好,我有个问题,如何在系统启动时加载一个模块?目前,我知道3种方式:

1.在类似/etc/initrc等配置文件的末尾加入insmod xx.ko,这个是最容易想到的

2.另一种方式,就是在/etc/modules文件中添加开机时需要装入的模块的模块名,来看下modules自己的注释:

# /etc/modules: kernel modules to load at boot time.## This file contains the names of kernel modules that should be loaded# at boot time, one per line. Lines beginning with "#" are ignored.
中文我就不翻译了。这里有一点需要注意,将被insmod的模块的位置不是随便指定的,必须在/lib/modules/(`uname -r`)/kernel/driver的子目录下能找到该模块。
以我的环境为例:我用的os是公版的ubuntu 12.04,另外, 桌面上待编译的内核为linux-3.13

root@ubuntu:~# uname -r3.13.0-32-genericroot@ubuntu:~# cat /etc/issueUbuntu 12.04.5 LTS \n \l
root@ubuntu:~# cd ~/Desktop/linux-3.13/root@ubuntu:~/Desktop/linux-3.13# pwd/root/Desktop/linux-3.13

两个内核的区别是,我往待编译的内核上添加了2个测试模块:


经过make all&&make modules_install&&make install后,在/boot/grub/grub.cfg中有两个启动项:

#公版启动项
menuentry 'Ubuntu, with Linux 3.13.0-32-generic' --class ubuntu --class gnu-linux --class gnu --class os {recordfailgfxmode $linux_gfx_modeinsmod gzioinsmod part_msdosinsmod ext2set root='(hd0,msdos1)'search --no-floppy --fs-uuid --set=root 9a661d2c-4456-4d23-93f2-60544bc54fe3linux/boot/vmlinuz-3.13.0-32-generic root=UUID=9a661d2c-4456-4d23-93f2-60544bc54fe3 ro   quiet splash $vt_handoffinitrd/boot/initrd.img-3.13.0-32-generic}
#添加了Simple模块的启动项menuentry 'Ubuntu, with Linux 3.13.0' --class ubuntu --class gnu-linux --class gnu --class os {<span style="white-space:pre"></span>recordfail<span style="white-space:pre"></span>gfxmode $linux_gfx_mode<span style="white-space:pre"></span>insmod gzio<span style="white-space:pre"></span>insmod part_msdos<span style="white-space:pre"></span>insmod ext2<span style="white-space:pre"></span>set root='(hd0,msdos1)'<span style="white-space:pre"></span>search --no-floppy --fs-uuid --set=root 9a661d2c-4456-4d23-93f2-60544bc54fe3<span style="white-space:pre"></span>linux<span style="white-space:pre"></span>/boot/vmlinuz-3.13.0 root=UUID=9a661d2c-4456-4d23-93f2-60544bc54fe3 ro   quiet splash $vt_handoff<span style="white-space:pre"></span>initrd<span style="white-space:pre"></span>/boot/initrd.img-3.13.0}
为了在系统引导时加载Simple模块,我的/etc/modules配置为:

# /etc/modules: kernel modules to load at boot time.## This file contains the names of kernel modules that should be loaded# at boot time, one per line. Lines beginning with "#" are ignored.lpsimple_ops_exportsimple
重启ubuntu后,选择进入3.13.0,进入系统后lsmod|grep -i simple即可看到新添加的模块

root@ubuntu:~# lsmod|grep -i simplesimple                   799  0 simple_ops_export       1184  1 simpleroot@ubuntu:~# uname -r3.13.0
但是如果进入Ubuntu, with Linux 3.13.0-32-generic,则系统引导后lsmod的结果中不会有Simple模块,因为/lib/modules/(`uname -r`)/kernel/driver下根本不存在这个模块

root@ubuntu:~# uname -r3.13.0-32-genericroot@ubuntu:~# lsmod|grep -i simpleroot@ubuntu:~#
3.最后一种方法就是向initrd内部更新Simple驱动模块,这也是标题的题意。

这种方法需要借用mkinitramfs套件,mkinitramfs会把/lib/modules/`uname -r`目录下一些启动必须的模块添加到initramfs中。如果用户需要手动添加一些模块,可以通过/etc/initramfs-tools/modules文件中加入模块名来实现。

来看下修改该文件前后initrd.img的变化:

3-1):默认情况下的/etc/initramfs-tools/modules

# List of modules that you want to include in your initramfs.# They will be loaded at boot time in the order below.## Syntax:  module_name [args ...]## You must run update-initramfs(8) to effect this change.## Examples:## raid1# sd_mod# Beginning of the block added by the VMware software - DO NOT EDITvmxnet3vmw_pvscsi
<span style="font-family: Arial, Helvetica, sans-serif;"># End of the block added by the VMware software</span>
root@ubuntu:~# update-initramfs -u -k 3.13.0
cp /boot/initrd.img-3.13.0 ~/Desktop/<span style="font-family: Arial, Helvetica, sans-serif;">initrd.img-3.13.0.gz</span>
<span style="font-family: Arial, Helvetica, sans-serif;">#gunzip </span><span style="font-family: Arial, Helvetica, sans-serif;">~/Desktop/</span><span style="font-family: Arial, Helvetica, sans-serif;">initrd.img-3.13.0.gz</span><pre name="code" class="cpp">#cpio -i --make-directories < initrd.img-3.13.0
<pre name="code" class="cpp">root@ubuntu:~/Desktop# cd lib/modules/3.13.0/root@ubuntu:~/Desktop/lib/modules/3.13.0#ls
modules.alias      modules.dep.bin  modules.softdep
modules.alias.bin  modules.devname  modules.symbols
modules.dep        modules.order    modules.symbols.bin

3-2):修改/etc/initramfs-tools/modules后

# List of modules that you want to include in your initramfs.# They will be loaded at boot time in the order below.## Syntax:  module_name [args ...]## You must run update-initramfs(8) to effect this change.## Examples:## raid1# sd_mod# Beginning of the block added by the VMware software - DO NOT EDITvmxnet3   #附注,这里可以看出vmware如何添加vmtools模块vmw_pvscsisimple_ops_exportsample# End of the block added by the VMware software
<pre name="code" class="cpp">root@ubuntu:~# update-initramfs -u -k 3.13.0
cp /boot/initrd.img-3.13.0 ~/Desktop/<span style="font-family: Arial, Helvetica, sans-serif;">initrd.img-3.13.0.gz</span>
<span style="font-family: Arial, Helvetica, sans-serif;">#gunzip </span><span style="font-family: Arial, Helvetica, sans-serif;">~/Desktop/</span><span style="font-family: Arial, Helvetica, sans-serif;">initrd.img-3.13.0.gz</span><pre name="code" class="cpp">#cpio -i --make-directories < initrd.img-3.13.0

<pre name="code" class="cpp">root@ubuntu:~/Desktop# cd lib/modules/3.13.0/root@ubuntu:~/Desktop/lib/modules/3.13.0#ls    #多了一个kernel文件夹
kernel             modules.dep      modules.order    modules.symbols.binmodules.alias      modules.dep.bin  modules.softdepmodules.alias.bin  modules.devname  modules.symbols
root@ubuntu:~/Desktop/lib/modules/3.13.0# cd kernel/drivers/charroot@ubuntu:~/Desktop/lib/modules/3.13.0/kernel/drivers/char# lssimple_ops_export.ko
再次启动进入3.13.0内核查看模块加载结果(去掉/etc/modules文件中的配置,以免影响测试):



root@ubuntu:~# uname -r3.13.0root@ubuntu:~# lsmod|grep -i simplesimple_ops_export       1184  0 root@ubuntu:~# 
这个结果充分说明了,方法3也是一种不错的方法~~



0 0