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

原创 2015年11月22日 21:55:33

    从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.0
initrd.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
#ls
ata ... 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 -r
3.13.0-32-generic
root@ubuntu:~# cat /etc/issue
Ubuntu 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 {
	recordfail
	gfxmode $linux_gfx_mode
	insmod gzio
	insmod part_msdos
	insmod ext2
	set root='(hd0,msdos1)'
	search --no-floppy --fs-uuid --set=root 9a661d2c-4456-4d23-93f2-60544bc54fe3
	linux	/boot/vmlinuz-3.13.0-32-generic root=UUID=9a661d2c-4456-4d23-93f2-60544bc54fe3 ro   quiet splash $vt_handoff
	initrd	/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.

lp
simple_ops_export
simple
重启ubuntu后,选择进入3.13.0,进入系统后lsmod|grep -i simple即可看到新添加的模块

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

root@ubuntu:~# uname -r
3.13.0-32-generic
root@ubuntu:~# lsmod|grep -i simple
root@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 EDIT
vmxnet3
vmw_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 EDIT
vmxnet3   #附注,这里可以看出vmware如何添加vmtools模块
vmw_pvscsi
simple_ops_export
sample
# 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/char
root@ubuntu:~/Desktop/lib/modules/3.13.0/kernel/drivers/char# ls
simple_ops_export.ko
再次启动进入3.13.0内核查看模块加载结果(去掉/etc/modules文件中的配置,以免影响测试):



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



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

initrd的制作和解压

initrd 的英文含义是 boot loader initialized RAM disk,就是由 boot loader 初始化的内存盘。在 linux内核启动前,boot loader 会将存储...

编译linux kernel及制作initrd ( by quqi99 )

编译linux kernel及制作initrd ( by quqi99 ) 作者:张华  发表于:2013-01-27 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及...
  • quqi99
  • quqi99
  • 2013年01月27日 17:41
  • 12231

制作initrd(4):initrd.img中启动脚本init分析

概述:这篇文章主体内容来源于网上转载。前面几篇文章倾向于制作initrd.img,这篇文章更倾向于initrd.img的运行过程:加载framebuff驱动 ide驱动和文件系统驱动,最后进入到真正的...

initrd文件中没有磁盘阵列驱动导致系统无法启动的处理

 initrd文件中没有磁盘阵列驱动导致系统无法启动的处理Hansel He hansel@163.com>2010-3-5一、问题现象:今天公司的开发服务器(Redhat Enterprise Li...
  • hansel
  • hansel
  • 2010年03月05日 18:52
  • 4224

initrd.img 干了什么

我也是一边学一边把我简单理解的东西拿出来和大家分享,如有错误还希望大家指出。initrd.img 里的东西我还没有吃透。不过我觉得也没关系毕竟我写的是学习笔记而不是教程,有些解释不透的东西大家还希望大...

浅谈linux启动的那些事(initrd.img)

本文记录下linux系统的启动过程,分析下每一步都做了什么。 一、linux系统的启动过程   1.加载BIOS,上电自检。因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信...

initrd.img处理

initrd (boot loader initialized RAM disk) linux2.6 内核支持两种格式的 initrd,一种是 linux2.4内核那种传统格式的文件系统镜像-imag...
  • jiazhen
  • jiazhen
  • 2009年03月25日 11:24
  • 4906

什么是 initrd.img

对我个人而言,学习一个系统的最好的方法就是随着其启动运行的过程一点一点跟进(就好象看一个程序的源码要从main函数或者说从入口函数开始步步跟进)。当然具体的学习过程重点不是找到入口点就OK的。中间还有...

Hacking initrd.img - 添加网卡驱动,网络安装 Linux

 本文通过将网卡驱动加入到 initrd.img 中,使 Linux 内核在启动的过程中能正确识别并加载网卡驱动,从而使网络安装得以进行。 前言 ...

修改initrd文件

打包: A)含子目录打包:  find /usr/lib -print | cpio -o > /usr/temp.cpio B)不含子目录的打包:ls /usr/lib | cpio -o > /u...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:制作initrd(1):向initrd内部更新驱动模块
举报原因:
原因补充:

(最多只允许输入30个字)