Linux設備模型
發布時間:2009-12-14 17:00
發布者:linux_Ultra
Linux設備驅動程序學習(15) -Linux設備模型(熱插拔、mdev 與 firmware) 熱插拔 有 2 個不同角度來看待熱插拔: 從內核角度看,熱插拔是在硬件、內核和內核驅動之間的交互。 從用戶角度看,熱插拔是內核和用戶空間之間,通過調用用戶空間程序(如hotplug、udev 和 mdev)的交互。 當需要通知用戶內核發生了某種熱插拔事件時,內核才調用這個用戶空間程序。 現在的計算機系統,要求 Linux 內核能夠在硬件從系統中增刪時,可靠穩定地運行。這就對設備驅動作者增加了壓力,因為在他們必須處理一個毫無征兆地突然出現或消失的設備。 熱插拔工具 當用戶向系統添加或刪除設備時,內核會產生一個熱插拔事件,并在 /proc/sys/kernel/hotplug 文件里查找處理設備連接的用戶空間程序。這個用戶空間程序主要有 hotplug:這個程序是一個典型的 bash 腳本,只傳遞執行權給一系列位于 /etc/hot-plug.d/ 目錄樹的程序。hotplug 腳本搜索所有的有 .hotplug后綴的可能對這個事件進行處理的程序并調用它們, 并傳遞給它們許多不同的已經被內核設置的環境變量。(基本已被淘汰,具體內容請參閱《LDD3》) udev :用于linux2.6.13或更高版本的內核上,為用戶空間提供使用固定設備名的動態/dev目錄的解決方案。它通過在 sysfs 的 /class/ 和/block/ 目錄樹中查找一個稱為 dev的文件,以確定所創建的設備節點文件的主次設備號。所以要使用udev,驅動必須為設備在sysfs中創建類接口及其dev屬性文件,方法和sculld模塊中創建dev屬性相同。 udev的資料網上十分豐富,我就不在這廢話了,給出以下鏈接有興趣的自己研究: 《UDEV Primer》(英文),地址: http://webpages.charter.net/decibelshelp/LinuxHelp_UDEVPrimer.html 《udev規則編寫》(luofuchong翻譯),地址: http://www.cnitblog.com/luofuchong/archive/2007/12/18/37831.html 《什么是udev》地址: http://blog.csdn.net/steganography/archive/2006/04/10/657620.aspx 《udev-FAQ 中文翻譯》地址: http://gnawux.bokee.com/3225765.html 《udev輕松上路》地址: http://www.blog.edu.cn/user1/3313/archives/2007/1635169.shtml 《Udev (簡體中文)》地址: http://wiki.archlinux.org/index.php/Udev_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87 ) Udev官方主頁: http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html 下載地址: http://www.kernel.org/pub/linux/utils/kernel/hotplug/ 在《LFS》中也有介紹udev的使用,很值得參考!下載地址: http://lfs.osuosl.org/lfs/downloads/stable/ mdev:一個簡化版的udev,是busybox所帶的程序,十分適合嵌入式系統。 因為hotplug現在也在被慢慢地淘汰,udev不再依賴hotplug了,所以這里不再介紹; udev較mdev復雜,不太適合嵌入式使用。(本人也有做udev的實驗,交叉編譯是通過了,但是使用上有問題,沒有實現其功能。也許是我的文件系統沒做好,以后有時間再研究和寫記錄。有成功高人的通知一聲,交流一下經驗。^_^謝謝。; mdev簡單易用,比較適合嵌入式系統,實驗成功。以下詳細介紹mdev的使用。 mdev 在一開始建立根文件系統時,我根據 WeiBing 的博客上《UDEV on embeded Linux-2.6.19.2》(地址: http://weibing.blogbus.com/logs/4485453.html )這篇文章的提示,開始使用mdev,但是當時只是啟動時mdev -s一下,并沒有深究,F在在學習了Linux設備模型之后,對于Linux中/dev目錄的動態管理有了更深的認識,并認真的看了一下busybox中的mdev.txt文檔并翻譯了一下,做成了PDF(下載地址: http://blogimg.chinaunix.net/blog/upfile2/080111091002.pdf ),在看下面的內容時請先看看這篇文檔。 先聲明一個要點:要實現設備節點文件的自動、動態的增刪,必須在你自己的驅動源碼中實現 類 接口,并在類設備的目錄中添加包含設備號的名為“dev”的屬性文件。 mdev原理及bug 要使用mdev,適當知道一下原理是必不可少的(能完整地研究mdev源碼是最好的)。說實話起初我并沒有想看mdev的源碼,是在使用時發現了問題后才去研究了一下mdev的源碼,F在簡單介紹一下mdev的原理: 執行mdev -s:以‘-s’為參數調用位于/sbin目錄寫的mdev(其實是個鏈接,作用是傳遞參數給/bin目錄下的busybox程序并調用它),mdev掃描 /sys/class 和/sys/block中所有的類設備目錄,如果在目錄中含有名為“dev”的文件,且文件中包含的是設備號,則mdev就利用這些信息為這個設備在/dev下創建設備節點文件。一般只在啟動時才執行一次 “mdev -s”。 熱插拔事件:由于啟動時運行了命令:echo /sbin/mdev > /proc/sys/kernel/hotplug,那么當有熱插拔事件產生時,內核就會調用位于 /sbin目錄的mdev。這時mdev通過環境變量中的 ACTION 和DEVPATH,來確定此次熱插拔事件的動作以及影響了/sys中的那個目錄。接著會看看這個目錄中是否有“dev”的屬性文件,如果有就利用這些信息為這個設備在/dev 下創建設備節點文件。 源碼的bug(個人意見):由于mdev是通過判斷“dev”屬性文件的路徑字符串中的第6個字符是否為‘c’,來決定設備是字符設備還是塊設備【type = (path[5] == 'c' ? S_IFCHR : S_IFBLK);例如path = "/sys/class/ldd/sculld*/"為字符設備,而/sys/devices/ldd0/sculld*/就會被誤判為塊設備】,那么如果你在非 /sys/class 和 /sys/block目錄下建立了“dev”屬性文件且內容是設備號(像sculld中就這樣做了),那么mdev也會在/dev下創建設備節點文件。這樣可能所創建的設備節點文件是錯的。 以我實驗為例,我以上一篇的文章中的sculld為基礎,加上了類接口(這樣在/sys/devices/ldd0/sculld*/和 /sys/class/ldd/sculld* 中都有內容為設備號的“dev”屬性文件)。在運行時發現一直會將有的sculld*創建為塊設備節點文件。郁悶死了,難道我的驅動有錯???最后研究了mdev源碼之后發現,只要在/sys中建立了“dev”屬性文件且內容是設備號,mdev就會以所在的目錄為名在/dev下創建設備節點文件。像sculld模塊,mdev會為一個設備創建兩次設備文件,由于文件名一樣,第二次的文件會覆蓋第一次的。如果第二次是因為/sys/devices/ldd0/sculld*/dev 產生的設備節點文件,那么設備節點文件就會被錯誤地創建為塊設備。 我認為這個bug的解決辦法有如下兩種: (1)在你寫驅動的時候,只在/sys/class 和 /sys/block 中的類設備目錄中存在包含設備號的“dev”屬性文件。(你無法保證被人的驅動會這么做) (2)修正mdev源碼: 修改/busybox-1.9.0/util-linux/mdev.c文件的第328行: if (!strcmp(action, "remove")) make_device(temp, 1); else if (!strcmp(action, "add")) { if (env_path[2]=='l') make_device(temp,0); //tekkamanninja if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) load_firmware(getenv("FIRMWARE"), temp); } 也就是在增加設備節點文件之前檢查/sys/目錄下的路徑是否為/class和/block(通過檢查路徑字符串的第3個字符是否為‘l’)。 本人推薦第二種做法! mdev使用 mdev的使用在busybox中的mdev.txt文檔已經將得很詳細了。但作為例子,我簡單講講我的使用過程: (1)在編譯時加上對mdev的支持(我是使用的是busybox1.9.0): Linux System Utilities --->
|
網友評論