Linux內核熱拔插機制
在Linux2.6.30.4的內核中,註冊驅動時調用device_create,卸載驅動時調用
device_destory函數最終都將導致kobject_uevent_env函數被調用,該函數用於
通知用戶空間設備發送了動態變化
添加:
device_create(struct class
*class, struct device *parent,
dev_t devt, void *drvdata, const char *fmt,
...)
device_register(dev);
device_add(dev);
kobject_uevent(&dev->kobj,
KOBJ_ADD);
kobject_uevent_env(kobj,
action, NULL);
移除:
device_destroy(struct class
*class, dev_t devt)
device_unregister(dev);
device_del(dev);
kobject_uevent(&dev->kobj,
KOBJ_REMOVE);
kobject_uevent_env(kobj,
action, NULL);
mdev函數分析:(busybox:mdev.c)
uevent_helper =
/sbin/mdev
env->envp[0] =
ACTION=add
env->envp[1] =
DEVPATH=/devices/virtual/misc/buttons
env->envp[2] =
SUBSYSTEM=misc
env->envp[3] =
MAJOR=10
env->envp[4] =
MINOR=58
env->envp[5] =
SEQNUM=410
env->envp[6] =
HOME=/
env->envp[7] =
PATH=/sbin:/bin:/usr/sbin:/usr/bin
action = getenv("ACTION"); //
action = "add"
env_path = getenv("DEVPATH");
// env_path ="/devices/virtual/misc/buttons"
seq = getenv("SEQNUM"); // seq
= "410"
snprintf(temp, PATH_MAX,
"/sys%s", env_path); // temp[] =
"sys/devices/virtual/misc/buttons"
if (!strcmp(action,
"remove"))
make_device(temp,
1);
else if (!strcmp(action,
"add"))
make_device(temp,
0);
add:
// 讀取主次設備號
len =
open_read_close("sys/devices/virtual/misc/buttons/dev", dev_maj_min
+ 1, 64);
device_name =
bb_basename(path);
type = S_IFCHR; //
判斷是字符設備還是塊設備
if
(strstr("sys/devices/virtual/misc/buttons/",
"/block/"))
type = S_IFBLK;
//
如果有"/etc/mdev.conf"文件將依據該文件創建設備文件
mknod(device_name, mode | type,
makedev(major, minor))
使用mdev在初始化腳本中需要以下代碼片段:
[0] mount -t proc proc
/proc
[1] mount -t sysfs sysfs /sys
[2] echo /bin/mdev
> /proc/sys/kernel/hotplug
[3] mdev -s
或者不使用/proc文件系統:
[1] mount -t sysfs sysfs
/sys
[2] sysctl -w
kernel.hotplug=/bin/mdev
[3] mdev -s
完整的啓動腳本中還會有以下代碼片段:
[4] mount -t tmpfs -o
size=64k,mode=0755 tmpfs /dev
[5] mkdir /dev/pts
[6] mount -t devpts devpts
/dev/pts
mdev.conf文件的編寫
mdev.conf是一個可選的配置文件,控制設備節點的所有權/權限,如果你的系統需要改變默認的root/root
660權限
文件的格式如下:
設備的正則表達式 用戶id
組id
八進制的權限
<device
regex>
<uid> :
<gid> <octal
permissions>
示例:
hd[a-z][0-9]* 0:3
660
正則表達式:
* :
重複0次或更多次
+
:重複1次或更多次
? :重複0次或1次
. :
匹配換行符以外的任意字符
[] : 匹配裏面的某個字符
配置文件的解析將停止於第一個匹配的行,如果沒有一行可以匹配,將使用默認的0:0
660
你也可以重命名/移除設備節點通過以下可選的域:
設備的正則表達式 用戶id 組id
八進制的權限
<device
regex>
<uid> :
<gid>
<octal permissions>
[=path]
如果你想將設備節點放置於某個子目錄中,確保路徑中含"/",如果你想給某個設備節點重命名
只需要放置名字。
hda 0:3 660
=drives/
這樣會將設備文件"hda"放置到drives/
子目錄中
hdb 0:3 660 =cdrom
這樣會將"hdb"重命名爲"cdrom"
類似的,">path"
重命名/移除設備但還會創建一個符號鏈接從"/dev/DEVNAME"到重命名/移除的設備
可以支持運行自己編寫的命令,此時文件的格式如下:
<device
regex>
<uid>:<gid>
<octal permissions> [=path]
[@|$|*<command>]
或者
<device
regex>
<uid>:<gid>
<octal permissions>
[>path]
[@|$|*<command>]
相關字符的意思:
@ 創建設備之後運行
$ 移除設備之前運行
*
在創建設備之後和移除設備之前都運行
命令是通過system()函數來執行(這意味着你應該給shell提供命令),所以你應該確保/bin/sh
shell
已經安裝,當內核指向hotplug
helpers時將stdin,stdout,stderr連接到/dev/null
使用環境變量$MDEV被設置成設備名。
掛載U盤的mdev.conf
sd[a-d]+[1-9]+ 0:0
660 * /bin/mount_udisk.sh
其中/bin/mount_udisk.sh的內容如下:
#!/bin/sh
if [ $ACTION = "add"
];
then
mount /dev/$MDEV
/mnt/udisk;
else
umount /mnt/udisk;
fi
相關連接:
正則表達式
:http://deerchao.net/tutorials/regex/regex.htm
mdev的配置文檔:
busyboxXXX/doc/mdev.txt
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.