亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 41059 | 回復(fù): 14
打印 上一主題 下一主題

Linux設(shè)備驅(qū)動模型中的熱插拔機制及實驗 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2012-03-03 18:11 |只看該作者 |倒序瀏覽
本帖最后由 MagicBoy2010 于 2012-03-03 18:13 編輯

本人CU博客中的文章,本來是希望CU給推薦到首頁的,結(jié)果周五不知道CU博客出了啥問題,居然沒什么更新。所以我干脆把再把它放到這里,因為話題涉及設(shè)備驅(qū)動模塊自動加載,本版已經(jīng)有同學問過這方面的問題。

熱插拔(hotplug,打這個詞的時候我常常想到熱干面)不一定非要指類似U盤那樣的插入拔出,此處的熱插拔廣義上講,是指一個設(shè)備加入系統(tǒng),內(nèi)核如何通知用戶空間。舉個簡單的例子,如果你的電腦中有塊PCI網(wǎng)卡,針對該網(wǎng)卡的驅(qū)動程序以內(nèi)核模塊的形式被編譯(obj-m),那么Linux系統(tǒng)在啟動過程中是如何自動加載該網(wǎng)卡的驅(qū)動模塊呢?大家都知道現(xiàn)在udev負責干這事,其實除了udev,還可以有其他的手法,你自己就可以這樣做。

我們先討論udev,udev最關(guān)鍵的東西是當系統(tǒng)發(fā)現(xiàn)一個設(shè)備時,它要能夠被通知該事件,一旦它知道了這件事,那么余下的事情就都好說了,無非是個如何查找模塊并加載的過程。所以我們看到,這里的關(guān)鍵是熱插拔事件的通知機制。Linux的設(shè)備模型為此提供了非常完美的支持,其原理其實發(fā)源于kset這一層,對此在《深入Linux設(shè)備驅(qū)動程序內(nèi)核機制》一書中有詳細的描述,雖然這部分看起來蠻復(fù)雜,貌似挺能嚇唬住一些新手,其實說白了,要點就是通過sysfs建立關(guān)系,溝通內(nèi)核與用戶空間,然后就是uevent,也就是下面要說的熱插拔事件。

當然設(shè)備驅(qū)動程序一般不會和這些太底層的kobject/kset家伙打交道,因為更高層次的device,bus和driver把kobject/kset那一層的細節(jié)實現(xiàn)都給封裝了起來。所以設(shè)備熱插拔的uevent事件最終的源頭來自于device_add,本帖這里肯定不會討論device與driver如何綁定那一攤子事情。下面看看device_add的源碼,是如何實現(xiàn)uevent機制的:
  1.     <drivers/base/core.c>
  2.     int device_add(struct device *dev)
  3.     {
  4.           ...
  5.           kobject_uevent(&dev->kobj, KOBJ_ADD);
  6.           ...
  7.     }
復(fù)制代碼
熱插拔的核心實現(xiàn)就那一個函數(shù)調(diào)用,這里device_add對應(yīng)的是KOBJ_ADD,那么移除設(shè)備自然對應(yīng)KOBJ_REMOVE了。kobject_uevent函數(shù)最終調(diào)用的是kobject_uevent_env,后者才是真正干事的伙計。
下面給出kobject_uevent_env函數(shù)的核心框架:
  1.     int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
  2.                            char *envp_ext[])
  3.     {
  4.             ...
  5.     #if defined(CONFIG_NET)
  6.             /* send netlink message */
  7.             ...
  8.     #endif

  9.             /* call uevent_helper, usually only enabled during early boot */
  10.             if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
  11.                     char *argv [3];

  12.                     argv [0] = uevent_helper;
  13.                     argv [1] = (char *)subsystem;
  14.                     argv [2] = NULL;
  15.                     retval = add_uevent_var(env, "HOME=/");
  16.                     if (retval)
  17.                             goto exit;
  18.                     retval = add_uevent_var(env,
  19.                                             "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
  20.                     if (retval)
  21.                             goto exit;

  22.                     retval = call_usermodehelper(argv[0], argv,
  23.                                                  env->envp, UMH_WAIT_EXEC);
  24.             }

  25.             ...
  26.     }
復(fù)制代碼
怎么樣,夠簡潔吧,其實看實際的代碼比這要郁悶地多,不過骨架清晰就行了。代碼中的netlink message就不用多說了吧,給udev發(fā)通知用(有時間的話可以分析分析udev的代碼)。本帖重點討論后半段的if (uevent_helper[0] && !kobj_usermode_filter(kobj))代碼,這里的核心調(diào)用是call_usermodehelper,這個函數(shù)最有意思的地方就在于在內(nèi)核空間調(diào)用用戶空間的程序,它的詳細實現(xiàn)機制在書中已經(jīng)講得很多,這里就不再贅述了。call_usermodehelper在kobject_uevent_env函數(shù)中要調(diào)用的用戶空間程序由uevent_helper[0]來指定,所以如果我們能控制這個uevent_helper[0],就能接收到設(shè)備加入系統(tǒng)移出系統(tǒng)等事件。那個if中的kobj_usermode_filter條件一般都會滿足(除非這是個特別注意個人隱私的設(shè)備,那就不好說了,人家偷偷加入系統(tǒng)就是不想讓你知道你也沒有辦法,但是udev還是能知道的)。

下面看看uevent_helper[0]來自何處:
  1.     <lib/kobject_uevent.c>
  2.     char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
復(fù)制代碼
貌似要通過內(nèi)核配置來指定,我看了一下我系統(tǒng)中Linux目錄下的.config文件,找到了下面這行:
  1. <linux-3.1.6/.config>
  2. #
  3. # Generic Driver Options
  4. #
  5. CONFIG_UEVENT_HELPER_PATH=""
復(fù)制代碼
丫的,居然沒指定,那么uevent_helper[0]="",這樣的話我們在kobject_uevent_env函數(shù)中的那個if語句就沒法滿足了,看來要重新配置再編譯內(nèi)核了。不過想想sysfs這么強大,內(nèi)核開發(fā)的那幫人好歹給留個用戶空間的接口出來吧,一查看還真有:

<kernel/ksysfs.c>
  1.     static ssize_t uevent_helper_store(struct kobject *kobj,
  2.                                        struct kobj_attribute *attr,
  3.                                        const char *buf, size_t count)
  4.     {
  5.             if (count+1 > UEVENT_HELPER_PATH_LEN)
  6.                     return -ENOENT;
  7.             memcpy(uevent_helper, buf, count);
  8.             uevent_helper[count] = '\0';
  9.             if (count && uevent_helper[count-1] == '\n')
  10.                     uevent_helper[count-1] = '\0';
  11.             return count;
  12.     }
復(fù)制代碼
尼瑪,爽得簡直是一塌糊涂,雖然俺那臺馬力強勁的機器編個全新的內(nèi)核不過幾分鐘的事情,但是哪里有上面這個方法爽啊。馬上進入到/sys/kernel目錄下ls一把,截屏如下(點擊放大):



有個uevent_helper文件不是?那么我們現(xiàn)在可以把我們用戶空間的程序給打進去了,我打算做個最簡單的腳本/sbin/myhotplug,這個腳本只干一件事,在/home/dennis目錄下生成一個hotplug文件:

</sbin/myhotplug>
  1.     #!/bin/sh
  2.     cd /home/dennis
  3.     touch hotplug
復(fù)制代碼
然后把這個腳本程序的文件名給打入到內(nèi)核空間的uevent_helper[0]上:
  1.     root@build-server:/sys/kernel# echo "/sbin/myhotplug" > uevent_helper
  2.     root@build-server:/sys/kernel# cat uevent_helper
  3.     /sbin/myhotplug
復(fù)制代碼
好了,現(xiàn)在檢查一下你的/home/dennis目錄下面有沒有hotplug這個文件,有的話就刪掉,否則怎么知道是新生成的呢,F(xiàn)在,找個U盤插到你的電腦里,然后再看一下/home/dennis目錄,有個hotplug文件對吧?如果你現(xiàn)在刪除這個文件,再把U盤給拔了,你會再次發(fā)現(xiàn)這個文件。這意味著什么,意味著你可以輕而易舉地捕捉到設(shè)備加入/移出系統(tǒng)等事件,如果你的腳本足夠智能,那么你就會想到很多很有創(chuàng)意的玩法對吧?

最后,對于PCI設(shè)備而言,Linux系統(tǒng)在啟動過程中會掃描系統(tǒng)中所有PCI設(shè)備,對發(fā)現(xiàn)的每一個設(shè)備都會調(diào)用device_add函數(shù),正如你前面看到的那樣,udev將會被通知,它負責找到對應(yīng)的驅(qū)動模塊并加載。當然,如果你愿意,你也可以去捕捉這些事件。

(原文首發(fā):http://www.embexperts.com/forum.php?mod=viewthread&tid=551&page=1&extra=#pid4649,略有改動)

論壇徽章:
0
2 [報告]
發(fā)表于 2012-03-03 18:17 |只看該作者
免責聲明:本人對按照上述實驗進行導(dǎo)致的U盤數(shù)據(jù)丟失、損壞等不負任何責任。如果實驗現(xiàn)象沒有達到預(yù)期,請想本版其他網(wǎng)友提問。

論壇徽章:
1
CU十二周年紀念徽章
日期:2013-10-24 15:41:34
3 [報告]
發(fā)表于 2012-03-03 22:15 |只看該作者
好文好文,
PS:深入Linux設(shè)備驅(qū)動程序內(nèi)核機制,講的是哪個內(nèi)核版本呢?

弄明白一版內(nèi)核的某些模塊,新版內(nèi)核很可能又發(fā)生了變化,不知道您是怎么跟上這個步伐的?

論壇徽章:
0
4 [報告]
發(fā)表于 2012-03-04 12:47 |只看該作者
好文好文,
PS:深入Linux設(shè)備驅(qū)動程序內(nèi)核機制,講的是哪個內(nèi)核版本呢?

弄明白一版內(nèi)核的某些模塊,新版內(nèi)核很可能又發(fā)生了變化,不知道您是怎么跟上這個步伐的?

================================

很榮幸樓上的仁兄把你在CU上的處女貼給了我,
PS:書剛開始寫時,基于2.6.35,到中晚期時,更新到了2.6.39,我也努力地把之前寫好的文字及代碼做了更新。但是肯定會有某些遺漏不周的地方。。。
我最熟悉的是2.4的內(nèi)核,但是很明顯到了2.6變化很大,我無法跟上這個步伐,但是之前的積累可以讓我在遇到新的問題時可以很快速地定位到特定的代碼中,比如語感。

論壇徽章:
0
5 [報告]
發(fā)表于 2012-03-06 10:23 |只看該作者
支持阿,另外,我決定了,樓主大人幫我解決這個問題我就買你的書
http://72891.cn/thread-2041616-1-2.html

我是windows coder,linux用的少,內(nèi)核調(diào)試環(huán)境搭不起來,感覺就沒法搞了,真是個悲劇阿!

論壇徽章:
0
6 [報告]
發(fā)表于 2012-03-06 11:53 |只看該作者
支持阿,另外,我決定了,樓主大人幫我解決這個問題我就買你的書
http://72891.cn/thread-2041616-1-2.html

我是windows coder,linux用的少,內(nèi)核調(diào)試環(huán)境搭不起來,感覺就沒法搞了,真是個悲劇阿!

==================================

不帶這么討價還價的,樓主還有別的事要做 ,你那個虛擬機的玩意我一看就比較棘手,我平時幾乎不用虛擬機和硬件模擬器這些東西。你直接搞個真實的環(huán)境吧。書還是要買滴,哈哈

論壇徽章:
0
7 [報告]
發(fā)表于 2012-03-06 11:54 |只看該作者
感謝千里馬同學,終于讓我有了一個精華的主題,真想讓5樓去擁抱你一下,呵呵

論壇徽章:
36
IT運維版塊每日發(fā)帖之星
日期:2016-04-10 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-16 06:20:0015-16賽季CBA聯(lián)賽之廣東
日期:2016-04-16 19:59:32IT運維版塊每日發(fā)帖之星
日期:2016-04-18 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-19 06:20:00每日論壇發(fā)貼之星
日期:2016-04-19 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-04-25 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-06 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-08 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-13 06:20:00IT運維版塊每日發(fā)帖之星
日期:2016-05-28 06:20:00每日論壇發(fā)貼之星
日期:2016-05-28 06:20:00
8 [報告]
發(fā)表于 2012-03-06 12:07 |只看該作者
本帖最后由 Godbach 于 2012-03-06 12:08 編輯
MagicBoy2010 發(fā)表于 2012-03-06 11:54
感謝千里馬同學,終于讓我有了一個精華的主題,真想讓5樓去擁抱你一下,呵呵



呵呵,客氣了。是 MagicBoy2010 兄的文章精彩啊。

最近論壇在線的時間都沒有保證,沒能更好的為大家服務(wù),真的很慚愧啊。

論壇徽章:
0
9 [報告]
發(fā)表于 2012-03-07 17:35 |只看該作者
Godbach 發(fā)表于 2012-03-06 12:07
呵呵,客氣了。是 MagicBoy2010 兄的文章精彩啊。

最近論壇在線的時間都沒有保證,沒能更好的為大 ...

千里馬同學辛苦,大家平時都比較忙,可以理解,呵呵

論壇徽章:
0
10 [報告]
發(fā)表于 2012-07-10 08:25 |只看該作者
:wink::wink::wink::wink:
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP