这是前面:<制作initrd(1):向initrd内部更新驱动模块>一文增补,简单解释在制作initrd过程中一些原理。
<制作initrd(1):向initrd内部更新驱动模块>中提到如果想向initrd.img中添加新的模块,可在/etc/initramfs-tools/modules文件中添加相应模块的模块名及其参数。为什么如此即可?
还是得从update-initramfs脚本说起。update-initramfs通过脚本函数generate_initramfs()进入mkinitramfs脚本。脚本中这几行正好可以解释这个疑问:
L8: CONFDIR="/etc/initramfs-tools" ... L208: for x in "${CONFDIR}/modules" /usr/share/initramfs-tools/modules.d/*; do if [ -f "${x}" ]; then add_modules_from_file "${x}" fi done脚本对/etc/initramfs-tools/modules等文件做add_modules_from_file操作,从函数名就可以看出,实现解析文件内容并向initrd.img添加模块的功能必定在这个函数中。
add_modules_from_file() { # Sanity check if [ ! -e "${1}" ]; then echo "W: add_modules_from_file: arg1='${1}' does not exist." >&2 return fi grep '^[^#]' ${1} | while read module args; do [ -n "$module" ] || continue force_load "${module}" "${args}" done }
force_load vmxnet3的形式调用force_load脚本函数
force_load() { manual_add_modules ${@} #将模块名和参数追加到initrd.img目录结构的conf/modules文件中 echo "${@}" >>"${DESTDIR}/conf/modules" }下面贴上manual_add_modules的脚本,之前遗漏了。他主要作用是按模块的名字获得模块所在的路径,并获得其依赖的固件,最后一并拷贝到initrd.img目录结构中
manual_add_modules() { local kmod firmware #以vmxnet3为例 运行modprobe --show-depends vmxnet3 --set-version=3.13.0-32-generic #输出insmod /lib/modules/3.13.0-32-generic/kernel/drivers/net/vmxnet3/vmxnet3.ko #运行modprobe --show-depends vmxnet3 --set-version=3.13.0-32-generic|awk '/^insmod/ { print $2 }' #输出/lib/modules/3.13.0-32-generic/kernel/drivers/net/vmxnet3/vmxnet3.ko #这是搜索模块对应的驱动文件 for kmod in $(modprobe --set-version="${version}" --ignore-install \ --quiet --show-depends "${1}" | awk '/^insmod/ { print $2 }'); do # Prune duplicates #如果initrd.img中已经存在该驱动文件 就算了 if [ -e "${DESTDIR}/${kmod}" ]; then continue fi #否则 连同目录结构一起拷过去 mkdir -p "${DESTDIR}/$(dirname "${kmod}")" cp -pL "${kmod}" "${DESTDIR}/$(dirname "${kmod}")" if [ "${verbose}" = "y" ]; then echo "Adding module ${kmod}" fi # Add required firmware #列出模块所依赖的farmware for firmware in $(modinfo -F firmware "${kmod}"); do if [ -e "${DESTDIR}/lib/firmware/${firmware}" ] \ || [ -e "${DESTDIR}/lib/firmware/${version}/${firmware}" ]; then continue fi # Only print warning for missing fw of loaded module # or forced loaded module if [ ! -e "/lib/firmware/${firmware}" ] \ && [ ! -e "/lib/firmware/${version}/${firmware}" ] ; then # Only warn about missing firmware if # /proc/modules exists if [ ! -e /proc/modules ] ; then continue fi if grep -q "^$(basename "${kmod}" .ko)[[:space:]]" \ /proc/modules \ || grep -q "^$(basename "${kmod}" .ko)" \ "${CONFDIR}/modules"; then echo "W: Possible missing firmware /lib/firmware/${firmware} for module $(basename ${kmod} .ko)" >&2 fi continue fi #拷贝firmware到initrd.img目录结构中 if [ ! -e "${DESTDIR}/lib/udev/firmware.agent" ] \ && [ -e "/lib/udev/firmware.agent" ]; then copy_exec /lib/udev/firmware.agent fi if [ -e "/lib/firmware/${version}/${firmware}" ]; then copy_exec "/lib/firmware/${version}/${firmware}" else copy_exec "/lib/firmware/${firmware}" fi if [ "${verbose}" = "y" ]; then echo "Adding firmware ${firmware}" fi done done }