linux下熱插拔事件的產生是怎樣通知到使用者空間,kobject_uevent_env之uevent

來源:互聯網
上載者:User
1.kobject, ktype, kset

kobject代表sysfs中的目錄。

ktype代表kobject的類型,主要包含release函數和attr的讀寫函數。比如,所有的bus都有同一個bus_type;所有的class都有同一個class_type。

kset包含了subsystem概念,kset本身也是一個kobject,所以裡麵包含了一個kobject對象。另外,kset中包含kset_uevent_ops,裡面主要定義了三個函數

       int (*filter)(struct kset *kset, struct kobject *kobj);

       const char *(*name)(struct kset *kset, struct kobject *kobj);

       int (*uevent)(struct kset *kset, struct kobject *kobj, struct kobj_uevent_env *env);

這三個函數都與uevent相關。filter用於判斷uevent是否要發出去。name用於得到subsystem的名字。uevent用於填充env變數。

2.uevent核心部分

uevent是sysfs向使用者空間發出的訊息。比如,device_add函數中,會調用kobject_uevent(&dev->kobj, KOBJ_ADD); 這裡kobj是發訊息的kobj,KOBJ_ADD是發出的事件。uevent的事件在kobject_action中定義:

enum kobject_action {

       KOBJ_ADD,

       KOBJ_REMOVE,

       KOBJ_CHANGE,

       KOBJ_MOVE,

       KOBJ_ONLINE,

       KOBJ_OFFLINE,

       KOBJ_MAX

};

 

int kobject_uevent(struct kobject *kobj, enum kobject_action action)

{

       return kobject_uevent_env(kobj, action, NULL);

}

 

kobject_uevent_env:

       由kobject的parent向上尋找,直到找到一個kobject包含kset。

       如果kset中有filter函數,調用filter函數,看看是否需要過濾uevent訊息。

       如果kset中有name函數,調用name函數得到subsystem的名字;否則,subsystem的名字是kset中kobject的名字。

       分配一個kobj_uevent_env,並開始填充env環境變數:

       增加環境變數ACTION=<action name>

       增加環境變數DEVPATH=<kobj’s path>

       增加環境變數SUBSYSTEM=<subsystem name>

       增加環境變數kobject_uevent_env中參數envp_ext指定的環境變數。

       調用kset的uevent函數,這個函數會繼續填充環境變數。

       增加環境變數SEQNUM=<seq>,這裡seq是靜態變數,每次累加。

       調用netlink發送uevent訊息。

       調用uevent_helper,最終轉換成對使用者空間sbin/mdev的調用。

3.uevent使用者空間部分

uevent的使用者空間程式有兩個,一個是udev,一個是mdev。

udev通過netlink監聽uevent訊息,它能完成兩個功能:

       1.自動載入模組

       2.根據uevent訊息在dev目錄下添加、刪除裝置節點。

另一個是mdev,mdev在busybox的程式碼封裝中能找到,它通過上節提到的uevent_helper函數被調用。

 

下面簡要介紹udev的模組自動載入過程:

etc目錄下有一個uevent規則檔案/etc/udev/rules.d/50-udev.rules

udev程式收到uevent訊息後,在這個規則檔案裡匹配,如果匹配成功,則執行這個匹配定義的shell命令。例如,規則檔案裡有這麼一行:

ACTION=="add", SUBSYSTEM=="?*", ENV{MODALIAS}=="?*", RUN+="/sbin/modprobe $env{MODALIAS}"

所以,當收到uevent的add事件後,shell能自動載入在MODALIAS中定義的模組。

 

mdev的模組自動載入過程與之類似,它的設定檔在/etc/mdev.conf中。例如:

$MODALIAS=.* 0:0 660 @modprobe "$MODALIAS"

這條規則指的是:當收到的環境變數中含有MODALIAS,那麼載入MODALIAS代表的模組。

mdev的詳細說明在busybox的docs/mdev.txt中。

4.uevent在裝置驅動模型中的應用

在sys目錄下有一個子目錄devices,代表一個kset。

建立裝置時,調用的device_initialize函數中,預設會把kset設定成devices_kset,即devices子目錄代表的kset。

devices_kset中設定了uevent操作集device_uevent_ops。

static struct kset_uevent_ops device_uevent_ops = {

       .filter =    dev_uevent_filter,

       .name =   dev_uevent_name,

       .uevent = dev_uevent,

};

 

dev_uevent_filter中,主要是規定了要想發送uevent,dev必須有class或者bus。

dev_uevent_name中,返回dev的class或者bus的名字。

dev_uevent函數:

       如果dev有裝置號,添加環境變數MAJOR與MINOR。

       如果dev->type有值,設定DEVTYPE=<dev->type->name>。

       如果dev->driver,設定DRIVER=<dev->driver->name>。

       如果有bus,調用bus的uevent函數。

       如果有class,調用class的uevent函數。

如果有dev->type,調用dev->type->uevent函數。

 

一般在bus的uevent函數中,都會添加MODALIAS環境變數,設定成dev的名字。這樣,uevent傳到使用者空間後,就可以通過對MODALIAS的匹配自動載入模組。這樣的bus例子有platform和I2C等等。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.