OpenWrt系統處理USB設備插入的流程


內核檢測到USB設備的插入之后,需要通知用戶空間進程來處理。目前有2種通知方式:

 

1.內核調用call_usermodehelper_setup()/call_usermodehelper_exec()從而運行用戶空間進程來處理。可以通過/sys/kernel/uevent_helper或者/proc/sys/kernel/hotplug來配置,指定用戶空間可執行程序的路徑。。

2.調用netlink_broadcast_filtered(),通過netlink的方式,將事件發送到用戶空間進程。

 

對於openwrt來說,他采用的是第二種方式。那么是哪個進程在監聽這類事件呢?是procd這個進程。關於procd進程的啟動,可以參照以下文章:

https://blog.csdn.net/angan4532/article/details/102303089

 

那么procd進程啟動時,就會創建一個NETLINK_KOBJECT_UEVENT類型的netlink的socket連接到內核。當內核檢測到事件后,就通過這個netlink socket 將uevent消息發送到procd.

 

那么procd收到uevent消息之后,對不同的消息會根據用戶設定的規則進行不同的處理。這個規則是由/etc/hotplug.json指定的。

 

下面看一下這個配置文件的內容:

[router] /etc # cat hotplug.json
[
        [ "case", "ACTION", {
                "add": [
                        [ "if",
                                [ "and",
                                        [ "has", "MAJOR" ],
                                        [ "has", "MINOR" ],
                                ],
                                [
                                        [ "if",
                                                [ "or",
                                                        [ "eq", "DEVNAME",
                                                                [ "null", "full", "ptmx", "zero" ],
                                                        ],
                                                        [ "regex", "DEVNAME",
                                                                [ "^gpio", "^hvc" ],
                                                        ],
                                                ],
                                                [
                                                        [ "makedev", "/dev/%DEVNAME%", "0666" ],
                                                        [ "return" ],
                                                ]
                                        ],
                                        [ "if",
                                                [ "or",
                                                        [ "eq", "DEVNAME", "mapper/control" ],
                                                        [ "regex", "DEVPATH", "^ppp" ],
                                                ],
                                                [
                                                        [ "makedev", "/dev/%DEVNAME%", "0600" ],
                                                        [ "return" ],
                                                ],
                                        ],
                                        [ "if",
                                                [ "has", "DEVNAME" ],
                                                [ "makedev", "/dev/%DEVNAME%", "0644" ],
                                        ],
                                ],
                        ],
                        [ "if",
                                [ "has", "FIRMWARE" ],
                                [
                                        [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ],
                                        [ "load-firmware", "/lib/firmware" ],
                                        [ "return" ]
                                ]
                        ],
                ],
                "remove" : [
                        [ "if",
                                [ "and",
                                        [ "has", "DEVNAME" ],
                                        [ "has", "MAJOR" ],
                                        [ "has", "MINOR" ],
                                ],
                                [ "rm", "/dev/%DEVNAME%" ]
                        ]
                ]
        } ],
        [ "if",
                [ "eq", "SUBSYSTEM", "platform" ],
                [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ]
        ],
        [ "if",
                [ "and",
                        [ "has", "BUTTON" ],
                        [ "eq", "SUBSYSTEM", "button" ],
                ],
                [ "exec", "/etc/rc.button/%BUTTON%" ]
        ],
        [ "if",
                [ "eq", "SUBSYSTEM",
                        [ "net", "input", "usb", "usbmisc", "ieee1394", "block", "atm", "zaptel", "tty", "button", "dump" ]
                ],
                [ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ]
        ],
        [ "if",
                [ "and",
                        [ "eq", "SUBSYSTEM", "usb-serial" ],
                        [ "regex", "DEVNAME",
                                [ "^ttyUSB", "^ttyACM" ]
                        ],
                ],
                [ "exec", "/sbin/hotplug-call", "tty" ]
        ],
]
[router] /etc #

  

可以看到,這個規則文件里面,對於不同類型的uevent都指定了不同的處理方式。比方說對於usb存儲設備,他首先會用mkdev來創建device,然后會調用/sbin/hotplug-call,並傳入一個參數SUBSYSTEM。

 

/sbin/hotplug-call是一個腳本程序:

[router] /etc # cat /sbin/hotplug-call
#!/bin/sh
# Copyright (C) 2006-2010 OpenWrt.org

export HOTPLUG_TYPE="$1"

. /lib/functions.sh

PATH=/usr/sbin:/usr/bin:/sbin:/bin
LOGNAME=root
USER=root
export PATH LOGNAME USER
export DEVICENAME="${DEVPATH##*/}"

[ \! -z "$1" -a -d /etc/hotplug.d/$1 ] && {
        for script in $(ls /etc/hotplug.d/$1/* 2>&-); do (
                [ -f $script ] && . $script
        ); done
}
[router] /etc #

 

這個腳本會調用/etc/hotplug.d/$SUBSYSTEM下面的所有腳本。這個腳本用戶可以自己指定。那么對於USB存儲設備來說,我們可能需要將這個設備mount到文件系統。

 


免責聲明!

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



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