openwrt hotplug


由內核發出 event 事件.

  1. kobject_uevent() 產生 uevent 事件(lib/kobject_uevent.c 中), 產生的 uevent 先由 netlink_broadcast_filtered() 發出, 最后調用 uevent_helper[] 所指定的程序來處理.

  2. uevent_helper[] 里默認指定 "/sbin/hotplug", 但可以通過 /sys/kernel/uevent_helper (kernel/ksysfs.c) 或 /proc/kernel/uevent_helper (kernel/sysctl.c) 來修改成指定的程序.

  3. 在 OpenWrt 並不使用 user_helper[] 指定程序來處理 uevent (/sbin/hotplug 不存在), 而是使用 PF_NETLINK 來獲取來自內核的 uevent.

用戶空間監聽 uevent

openwrt 中, procd 作為 init 進程會處理許多事情, 其中就包括 hotplug.

procd/plug/hotplug.c 中, 創建一個 PF_NETLINK 套接字來監聽內核 netlink_broadcast_filtered() 發出的 uevent.

收到 uevent 之后, 再根據 /etc/hotplug.json 里的描述來處理.

通常情況下, /etc/hotplug.json 會調用 /sbin/hotplug-call 來處理, 它根據 uevent 的 $SUBSYSTEM 變量來分別調用 /etc/hotplug.d/ 下不同目錄中的腳本.

比如, 插入U盤或SD卡時, 會產生的事件消息如下:

procd: rule_handle_command(355): Command: makedev
procd: rule_handle_command(357):  /dev/sda1
procd: rule_handle_command(357):  0644
procd: rule_handle_command(358): 
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362):  ACTION=add
procd: rule_handle_command(362):  DEVPATH=/devices/101c0000.ehci/usb1/1-1/1-1.3/1-1.3:1.0/host16/target16:0:0/16:0:0:0/block/sda/sda1
procd: rule_handle_command(362):  SUBSYSTEM=block
procd: rule_handle_command(362):  MAJOR=8
procd: rule_handle_command(362):  MINOR=1
procd: rule_handle_command(362):  DEVNAME=sda1
procd: rule_handle_command(362):  DEVTYPE=partition
procd: rule_handle_command(362):  SEQNUM=865
procd: rule_handle_command(363): 
procd: rule_handle_command(355): Command: exec
procd: rule_handle_command(357):  /sbin/hotplug-call
procd: rule_handle_command(357):  block
procd: rule_handle_command(358): 
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362):  ACTION=add
procd: rule_handle_command(362):  DEVPATH=/devices/101c0000.ehci/usb1/1-1/1-1.3/1-1.3:1.0/host16/target16:0:0/16:0:0:0/block/sda/sda1
procd: rule_handle_command(362):  SUBSYSTEM=block
procd: rule_handle_command(362):  MAJOR=8
procd: rule_handle_command(362):  MINOR=1
procd: rule_handle_command(362):  DEVNAME=sda1
procd: rule_handle_command(362):  DEVTYPE=partition
procd: rule_handle_command(362):  SEQNUM=865
procd: rule_handle_command(363): 

第一個 makedev 會創建 /dev/sda1 節點. 第二個 exec 命令, 其附帶的消息中指定了 ACTION, DEVPATH, SUBSYSTEM, DEVNAME, DEVTYPE 等變量.
於是 hotplug-call 會嘗試執行 /etc/hotplug.d/block/ 目錄下的所有可執行腳本.

所以我們可以在這里放置我們的自動掛載/卸載處理腳本.

按鍵 button 的檢測

openwrt 中, 按鍵的檢測也是通過 hotplug 來實現的.

它首先寫了一個內核模塊: gpio_button_hotplug, 用於監聽按鍵, 有中斷和 poll 兩種方式. 然后在發出事件的同時, 將記錄並計算得出的兩次按鍵時間差也作為 uevent 變量發出來.

這樣在用戶空間收到這個 uevent 事件時就知道該次按鍵按下了多長時間.

hotplug.json 中有描述, 如果 uevent 中含有 BUTTON 字符串, 而且 SUBSYSTEM 為 "button", 則執行 /etc/rc.button/ 下的 %BUTTON% 腳本來處理.

        [ "if",
                [ "and",
                        [ "has", "BUTTON" ],
                        [ "eq", "SUBSYSTEM", "button" ],
                ],
                [ "exec", "/etc/rc.button/%BUTTON%" ]
        ],

使用 export DBGLVL=10; procd -h /etc/hotplug.json 截獲一些打印信息看看:

{{"HOME":"\/","PATH":"\/sbin:\/bin:\/usr\/sbin:\/usr\/bin","SUBSYSTEM":"button","ACTION":"pressed","BUTTON":"reset","SEEN":"862","SEQNUM":"593"}}
procd: rule_handle_command(355): Command: exec
procd: rule_handle_command(357):  /etc/rc.button/reset
procd: rule_handle_command(358): 
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362):  HOME=/
procd: rule_handle_command(362):  PATH=/sbin:/bin:/usr/sbin:/usr/bin
procd: rule_handle_command(362):  SUBSYSTEM=button
procd: rule_handle_command(362):  ACTION=pressed
procd: rule_handle_command(362):  BUTTON=reset
procd: rule_handle_command(362):  SEEN=862
procd: rule_handle_command(362):  SEQNUM=593
procd: rule_handle_command(363): 

procd: rule_handle_command(355): Command: exec
procd: rule_handle_command(357):  /sbin/hotplug-call
procd: rule_handle_command(357):  button
procd: rule_handle_command(358): 
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362):  HOME=/
procd: rule_handle_command(362):  PATH=/sbin:/bin:/usr/sbin:/usr/bin
procd: rule_handle_command(362):  SUBSYSTEM=button
procd: rule_handle_command(362):  ACTION=pressed
procd: rule_handle_command(362):  BUTTON=reset
procd: rule_handle_command(362):  SEEN=862
procd: rule_handle_command(362):  SEQNUM=593
procd: rule_handle_command(363): 


{{"HOME":"\/","PATH":"\/sbin:\/bin:\/usr\/sbin:\/usr\/bin","SUBSYSTEM":"button","ACTION":"released","BUTTON":"reset","SEEN":"3","SEQNUM":"594"}}
procd: rule_handle_command(355): Command: exec
procd: rule_handle_command(357):  /etc/rc.button/reset
procd: rule_handle_command(358): 
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362):  HOME=/
procd: rule_handle_command(362):  PATH=/sbin:/bin:/usr/sbin:/usr/bin
procd: rule_handle_command(362):  SUBSYSTEM=button
procd: rule_handle_command(362):  ACTION=released
procd: rule_handle_command(362):  BUTTON=reset
procd: rule_handle_command(362):  SEEN=3
procd: rule_handle_command(362):  SEQNUM=594
procd: rule_handle_command(363): 

procd: rule_handle_command(355): Command: exec
procd: rule_handle_command(357):  /sbin/hotplug-call
procd: rule_handle_command(357):  button
procd: rule_handle_command(358): 
procd: rule_handle_command(360): Message:
procd: rule_handle_command(362):  HOME=/
procd: rule_handle_command(362):  PATH=/sbin:/bin:/usr/sbin:/usr/bin
procd: rule_handle_command(362):  SUBSYSTEM=button
procd: rule_handle_command(362):  ACTION=released
procd: rule_handle_command(362):  BUTTON=reset
procd: rule_handle_command(362):  SEEN=3
procd: rule_handle_command(362):  SEQNUM=594
procd: rule_handle_command(363): 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM