mdev的hotplug模式介紹
mdev的hotplug模式
上面的試驗中,我們在加載完驅(qū)動模塊后調(diào)用了mdev -s 命令來生成硬盤的設(shè)備文件。其實,可以使用mdev的hotplug模式在加載內(nèi)核時自動生成對應(yīng)的設(shè)備文件:
在執(zhí)行insmod命令前,用
echo /sbin/mdev > /proc/sys/kernel/hotplug
命令設(shè)置系統(tǒng)的hotplug程序為mdev。
后續(xù)使用insmod命令加載模塊時,系統(tǒng)自動調(diào)用mdev生成相應(yīng)的設(shè)備文件。
注意:內(nèi)核必須配置支持hotplug功能。
udev的coldplug模式
內(nèi)核在啟動時已經(jīng)檢測到了系統(tǒng)的硬件設(shè)備,并把硬件設(shè)備信息通過sysfs內(nèi)核虛擬文件 系統(tǒng)導(dǎo)出。sysfs文件系統(tǒng)由系統(tǒng)初始化腳本掛載到/sys上。udev掃描sysfs文件系統(tǒng),根據(jù)硬件設(shè)備信息生成熱插拔(hotplug)事 件,udev再讀取這些事件,生成對應(yīng)的硬件設(shè)備文件。由于沒有實際的硬件插拔動作,所以這一過程被稱為coldplug。我們的initramfs就是 利用這一機制,加載硬件設(shè)備的驅(qū)動程序模塊。
udev完成coldplug操作,需要下面三個程序:
udevd——作為deamon,記錄hotplug事件,然后排隊后再發(fā)送給udev,避免事件沖突(race conditions)。
udevtrigger——掃描sysfs文件系統(tǒng),生成相應(yīng)的硬件設(shè)備hotplug事件。
udevsettle——查看udev事件隊列,等隊列內(nèi)事件全部處理完畢才退出。
在initramfs的init腳本中可以執(zhí)行下面的語句實現(xiàn)coldplug功能:
mkdir -p /dev/.udev/db
udevd --daemon
mkdir -p /dev/.udev/queue
udevtrigger
udevsettle
許多文檔提到的在udevd --daemon 命令前要執(zhí)行
echo > /proc/sys/kernel/hotplug
命令,經(jīng)驗證,在我們的initramfs環(huán)境下的coldplug功能中并不需要。
用udev自動加載設(shè)備驅(qū)動模塊
了解了udev的coldplug的機理,我們就試驗一下用udev自動加載設(shè)備驅(qū)動模塊,并生成硬件設(shè)備文件。
(1)從 /sbin 目錄下拷貝udevd、udevtrigger、udevsettle程序到image目錄下的sbin目錄下,并用ldd命令找到它們所需要的動態(tài)庫文件,拷貝到image目錄下的lib目錄下。
(2)修改init腳本,增加coldplug功能:
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mdev -s
#using udev autoload hard disk driver module
mkdir -p /dev/.udev/db
udevd --daemon
mkdir -p /dev/.udev/queue
udevtrigger
udevsettle
mount /dev/sda8 /mnt
killall udevd
exec switch_root /mnt /sbin/init
注意:在切換到真正根文件系統(tǒng)前,要把udevd進程殺掉,否則會和真正根文件系統(tǒng)中的udev腳本的執(zhí)行相沖突。這就是上面killall udevd 語句的作用。
(3)編寫udev規(guī)則文件
規(guī) 則文件是udev的靈魂,沒有規(guī)則文件,udev無法自動加載硬件設(shè)備的驅(qū)動模塊。為了簡單,我們直接使用CLFS中的40- modprobe.rules,把它拷貝到image目錄下的etc/udev/rules.d目錄。
#
# Description : 40-modprobe.rules
#
# Authors : Based on Open Suse Udev Rules
# [url=mailto:kay.sievers@suse.de]kay.sievers@suse.de
#
# Adapted to : Jim Gifford
# LFS : Alexander E. Patrakov
#
# Version : 00.01
#
# Notes :
#
########################################################################
# hotplug
ENV{MODALIAS}=="?*", RUN+="/sbin/modprobe $env{MODALIAS}"
# scsi
SUBSYSTEM=="scsi_device", ACTION=="add", SYSFS{device/type}=="0|7|14", RUN+="/sbin/modprobe sd_mod"
SUBSYSTEM=="scsi_device", ACTION=="add", SYSFS{device/type}=="1", SYSFS{device/vendor}=="On[sS]tream", RUN+="/sbin/modprobe osst"
SUBSYSTEM=="scsi_device", ACTION=="add", SYSFS{device/type}=="1", RUN+="/sbin/modprobe st"
SUBSYSTEM=="scsi_device", ACTION=="add", SYSFS{device/type}=="[45]", RUN+="/sbin/modprobe sr_mod"
SUBSYSTEM=="scsi_device", ACTION=="add", RUN+="/sbin/modprobe sg"
# floppy
KERNEL=="nvram", ACTION=="add", RUN+="load_floppy_module.sh"
注意:上面的
ENV{MODALIAS}=="?*", RUN+="/sbin/modprobe $env{MODALIAS}"
語 句是實現(xiàn)自動加載硬件設(shè)備驅(qū)動模塊功能的關(guān)鍵,它根據(jù)sysfs文件系統(tǒng)中記錄的模塊aliases數(shù)據(jù),用modprobe命令加載對應(yīng)的內(nèi)核模塊。有 關(guān)模塊aliases的進一步說明,可參考CLFS手冊(CLFS-1.0.0-x86)中的11.5.2.4. Module Loading一節(jié)的描述。
(4)拷貝modprobe命令
前一節(jié)提到過,busybox的modprobe 命令不能正常使用,所以我們需要拷貝 /sbin 目錄下的modprobe命令到image目錄下的sbin目錄,供udev加載內(nèi)核模塊使用。
再用ldd命令檢查一下 /sbin/modprobe 命令所需的動態(tài)庫文件,如果有則拷貝到image/lib目錄下。(我的檢查結(jié)果是,除了libc6外,不需要其他動態(tài)庫,所以不需要拷貝)
好了,重新生成initramfs,initramfs能夠自動加載硬盤設(shè)備的驅(qū)動模塊,系統(tǒng)順利地從initramfs切換到了真正的根文件系統(tǒng)。