Linux設(shè)備驅(qū)動程序?qū)W習(xí)(15) -Linux設(shè)備模型(熱插拔、mdev 與 firmware) 熱插拔 有 2 個不同角度來看待熱插拔: 從內(nèi)核角度看,熱插拔是在硬件、內(nèi)核和內(nèi)核驅(qū)動之間的交互。 從用戶角度看,熱插拔是內(nèi)核和用戶空間之間,通過調(diào)用用戶空間程序(如hotplug、udev 和 mdev)的交互。 當(dāng)需要通知用戶內(nèi)核發(fā)生了某種熱插拔事件時,內(nèi)核才調(diào)用這個用戶空間程序。 現(xiàn)在的計算機系統(tǒng),要求 Linux 內(nèi)核能夠在硬件從系統(tǒng)中增刪時,可靠穩(wěn)定地運行。這就對設(shè)備驅(qū)動作者增加了壓力,因為在他們必須處理一個毫無征兆地突然出現(xiàn)或消失的設(shè)備。 熱插拔工具 當(dāng)用戶向系統(tǒng)添加或刪除設(shè)備時,內(nèi)核會產(chǎn)生一個熱插拔事件,并在 /proc/sys/kernel/hotplug 文件里查找處理設(shè)備連接的用戶空間程序。這個用戶空間程序主要有 hotplug:這個程序是一個典型的 bash 腳本,只傳遞執(zhí)行權(quán)給一系列位于 /etc/hot-plug.d/ 目錄樹的程序。hotplug 腳本搜索所有的有 .hotplug后綴的可能對這個事件進行處理的程序并調(diào)用它們, 并傳遞給它們許多不同的已經(jīng)被內(nèi)核設(shè)置的環(huán)境變量。(基本已被淘汰,具體內(nèi)容請參閱《LDD3》) udev :用于linux2.6.13或更高版本的內(nèi)核上,為用戶空間提供使用固定設(shè)備名的動態(tài)/dev目錄的解決方案。它通過在 sysfs 的 /class/ 和/block/ 目錄樹中查找一個稱為 dev的文件,以確定所創(chuàng)建的設(shè)備節(jié)點文件的主次設(shè)備號。所以要使用udev,驅(qū)動必須為設(shè)備在sysfs中創(chuàng)建類接口及其dev屬性文件,方法和sculld模塊中創(chuàng)建dev屬性相同。 udev的資料網(wǎng)上十分豐富,我就不在這廢話了,給出以下鏈接有興趣的自己研究: 《UDEV Primer》(英文),地址: http://webpages.charter.net/decibelshelp/LinuxHelp_UDEVPrimer.html 《udev規(guī)則編寫》(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所帶的程序,十分適合嵌入式系統(tǒng)。 因為hotplug現(xiàn)在也在被慢慢地淘汰,udev不再依賴hotplug了,所以這里不再介紹; udev較mdev復(fù)雜,不太適合嵌入式使用。(本人也有做udev的實驗,交叉編譯是通過了,但是使用上有問題,沒有實現(xiàn)其功能。也許是我的文件系統(tǒng)沒做好,以后有時間再研究和寫記錄。有成功高人的通知一聲,交流一下經(jīng)驗。^_^謝謝。 mdev簡單易用,比較適合嵌入式系統(tǒng),實驗成功。以下詳細(xì)介紹mdev的使用。 mdev 在一開始建立根文件系統(tǒng)時,我根據(jù) WeiBing 的博客上《UDEV on embeded Linux-2.6.19.2》(地址: http://weibing.blogbus.com/logs/4485453.html )這篇文章的提示,開始使用mdev,但是當(dāng)時只是啟動時mdev -s一下,并沒有深究,F(xiàn)在在學(xué)習(xí)了Linux設(shè)備模型之后,對于Linux中/dev目錄的動態(tài)管理有了更深的認(rèn)識,并認(rèn)真的看了一下busybox中的mdev.txt文檔并翻譯了一下,做成了PDF(下載地址: http://blogimg.chinaunix.net/blog/upfile2/080111091002.pdf ),在看下面的內(nèi)容時請先看看這篇文檔。 先聲明一個要點:要實現(xiàn)設(shè)備節(jié)點文件的自動、動態(tài)的增刪,必須在你自己的驅(qū)動源碼中實現(xiàn) 類 接口,并在類設(shè)備的目錄中添加包含設(shè)備號的名為“dev”的屬性文件。 mdev原理及bug 要使用mdev,適當(dāng)知道一下原理是必不可少的(能完整地研究mdev源碼是最好的)。說實話起初我并沒有想看mdev的源碼,是在使用時發(fā)現(xiàn)了問題后才去研究了一下mdev的源碼。現(xiàn)在簡單介紹一下mdev的原理: 執(zhí)行mdev -s:以‘-s’為參數(shù)調(diào)用位于/sbin目錄寫的mdev(其實是個鏈接,作用是傳遞參數(shù)給/bin目錄下的busybox程序并調(diào)用它),mdev掃描 /sys/class 和/sys/block中所有的類設(shè)備目錄,如果在目錄中含有名為“dev”的文件,且文件中包含的是設(shè)備號,則mdev就利用這些信息為這個設(shè)備在/dev下創(chuàng)建設(shè)備節(jié)點文件。一般只在啟動時才執(zhí)行一次 “mdev -s”。 熱插拔事件:由于啟動時運行了命令:echo /sbin/mdev > /proc/sys/kernel/hotplug,那么當(dāng)有熱插拔事件產(chǎn)生時,內(nèi)核就會調(diào)用位于 /sbin目錄的mdev。這時mdev通過環(huán)境變量中的 ACTION 和DEVPATH,來確定此次熱插拔事件的動作以及影響了/sys中的那個目錄。接著會看看這個目錄中是否有“dev”的屬性文件,如果有就利用這些信息為這個設(shè)備在/dev 下創(chuàng)建設(shè)備節(jié)點文件。 源碼的bug(個人意見):由于mdev是通過判斷“dev”屬性文件的路徑字符串中的第6個字符是否為‘c’,來決定設(shè)備是字符設(shè)備還是塊設(shè)備【type = (path[5] == 'c' ? S_IFCHR : S_IFBLK);例如path = "/sys/class/ldd/sculld*/"為字符設(shè)備,而/sys/devices/ldd0/sculld*/就會被誤判為塊設(shè)備】,那么如果你在非 /sys/class 和 /sys/block目錄下建立了“dev”屬性文件且內(nèi)容是設(shè)備號(像sculld中就這樣做了),那么mdev也會在/dev下創(chuàng)建設(shè)備節(jié)點文件。這樣可能所創(chuàng)建的設(shè)備節(jié)點文件是錯的。 以我實驗為例,我以上一篇的文章中的sculld為基礎(chǔ),加上了類接口(這樣在/sys/devices/ldd0/sculld*/和 /sys/class/ldd/sculld* 中都有內(nèi)容為設(shè)備號的“dev”屬性文件)。在運行時發(fā)現(xiàn)一直會將有的sculld*創(chuàng)建為塊設(shè)備節(jié)點文件。郁悶死了,難道我的驅(qū)動有錯???最后研究了mdev源碼之后發(fā)現(xiàn),只要在/sys中建立了“dev”屬性文件且內(nèi)容是設(shè)備號,mdev就會以所在的目錄為名在/dev下創(chuàng)建設(shè)備節(jié)點文件。像sculld模塊,mdev會為一個設(shè)備創(chuàng)建兩次設(shè)備文件,由于文件名一樣,第二次的文件會覆蓋第一次的。如果第二次是因為/sys/devices/ldd0/sculld*/dev 產(chǎn)生的設(shè)備節(jié)點文件,那么設(shè)備節(jié)點文件就會被錯誤地創(chuàng)建為塊設(shè)備。 我認(rèn)為這個bug的解決辦法有如下兩種: (1)在你寫驅(qū)動的時候,只在/sys/class 和 /sys/block 中的類設(shè)備目錄中存在包含設(shè)備號的“dev”屬性文件。(你無法保證被人的驅(qū)動會這么做) (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); } 也就是在增加設(shè)備節(jié)點文件之前檢查/sys/目錄下的路徑是否為/class和/block(通過檢查路徑字符串的第3個字符是否為‘l’)。 本人推薦第二種做法! mdev使用 mdev的使用在busybox中的mdev.txt文檔已經(jīng)將得很詳細(xì)了。但作為例子,我簡單講講我的使用過程: (1)在編譯時加上對mdev的支持(我是使用的是busybox1.9.0): Linux System Utilities --->
|
udev實現(xiàn)原理 轉(zhuǎn)載時請注明出處和作者聯(lián)系方式:http://blog.csdn.net/absurd 作者聯(lián)系方式:李先靜 更新時間:2007-4-29 相對于linux來說,udev還是一個新事物。然而,盡管它03年才出現(xiàn),盡管它很低調(diào)(J),但它無疑已經(jīng)成為linux下不可或缺的組件了。udev是什么?它是如何實現(xiàn)的?最近研究Linux設(shè)備管理時,花了一些時間去研究udev的實現(xiàn)。 udev是什么?u 是指user space,dev是指device,udev是用戶空間的設(shè)備驅(qū)動程序嗎?最初我也這樣認(rèn)為,調(diào)試內(nèi)核空間的程序要比調(diào)試用戶空間的程序復(fù)雜得多,內(nèi)核空間的程序的BUG所引起的后果也嚴(yán)重得多,device driver是內(nèi)核空間中所占比較最大的代碼,如果把這些device driver中硬件無關(guān)的代碼,從內(nèi)核空間移動到用戶空間,自然是一個不錯的想法。 但我的想法并不正確,udev的文檔是這樣說的, 1. dynamic replacement for /dev。作為devfs的替代者,傳統(tǒng)的devfs不能動態(tài)分配major和minor的值,而major和minor非常有限,很快就會用完了。udev能夠像DHCP動態(tài)分配IP地址一樣去動態(tài)分配major和minor。 2. device naming。提供設(shè)備命名持久化的機制。傳統(tǒng)設(shè)備命名方式不具直觀性,像/dev/hda1這樣的名字肯定沒有boot_disk這樣的名字直觀。udev能夠像DNS解析域名一樣去給設(shè)備指定一個有意義的名稱。 3. API to access info about current system devices 。提供了一組易用的API去操作sysfs,避免重復(fù)實現(xiàn)同樣的代碼,這沒有什么好說的。 我們知道,用戶空間的程序與設(shè)備通信的方法,主要有以下幾種方式, 1. 通過ioperm獲取操作IO端口的權(quán)限,然后用inb/inw/ inl/ outb/outw/outl等函數(shù),避開設(shè)備驅(qū)動程序,直接去操作IO端口。(沒有用過) 2. 用ioctl函數(shù)去操作/dev目錄下對應(yīng)的設(shè)備,這是設(shè)備驅(qū)動程序提供的接口。像鍵盤、鼠標(biāo)和觸摸屏等輸入設(shè)備一般都是這樣做的。 3. 用write/read/mmap去操作/dev目錄下對應(yīng)的設(shè)備,這也是設(shè)備驅(qū)動程序提供的接口。像framebuffer等都是這樣做的。 上面的方法在大多數(shù)情況下,都可以正常工作,但是對于熱插撥(hotplug)的設(shè)備,比如像U盤,就有點困難了,因為你不知道:什么時候設(shè)備插上了,什么時候設(shè)備拔掉了。這就是所謂的hotplug問題了。 處理hotplug傳統(tǒng)的方法是,在內(nèi)核中執(zhí)行一個稱為hotplug的程序,相關(guān)參數(shù)通過環(huán)境變量傳遞過來,再由hotplug通知其它關(guān)注hotplug事件的應(yīng)用程序。這樣做不但效率低下,而且感覺也不那么優(yōu)雅。新的方法是采用NETLINK實現(xiàn)的,這是一種特殊類型的socket,專門用于內(nèi)核空間與用戶空間的異步通信。下面的這個簡單的例子,可以監(jiān)聽來自內(nèi)核hotplug的事件。 #include #include #include #include #include #include #include #include #include #include static int init_hotplug_sock(void) { struct sockaddr_nl snl; const int buffersize = 16 * 1024 * 1024; int retval; memset(&snl, 0x00, sizeof(struct sockaddr_nl)); snl.nl_family = AF_NETLINK; snl.nl_pid = getpid(); snl.nl_groups = 1; int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (hotplug_sock == -1) { printf("error getting socket: %s", strerror(errno)); return -1; } /* set receive buffersize */ setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize)); retval = bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl)); if (retval < 0) { printf("bind failed: %s", strerror(errno)); close(hotplug_sock); hotplug_sock = -1; return -1; } return hotplug_sock; } #define UEVENT_BUFFER_SIZE 2048 int main(int argc, char* argv[]) { int hotplug_sock = init_hotplug_sock(); while(1) { char buf[UEVENT_BUFFER_SIZE*2] = {0}; recv(hotplug_sock, &buf, sizeof(buf), 0); printf("%s\n", buf); } return 0; } 編譯: gcc -g hotplug.c -o hotplug_monitor 運行后插/拔U盤,可以看到: add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1 add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/usbdev2.2_ep00 add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0 add@/class/scsi_host/host2 add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep81 add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep02 add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep83 add@/class/usb_device/usbdev2.2 add@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host2/target2:0:0/2:0:0:0 add@/class/scsi_disk/2:0:0:0 add@/block/sda add@/block/sda/sda1 add@/class/scsi_device/2:0:0:0 add@/class/scsi_generic/sg0 remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep81 remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep02 remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/usbdev2.2_ep83 remove@/class/scsi_generic/sg0 remove@/class/scsi_device/2:0:0:0 remove@/class/scsi_disk/2:0:0:0 remove@/block/sda/sda1 remove@/block/sda remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0/host2/target2:0:0/2:0:0:0 remove@/class/scsi_host/host2 remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/2-1:1.0 remove@/class/usb_device/usbdev2.2 remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1/usbdev2.2_ep00 remove@/devices/pci0000:00/0000:00:1d.1/usb2/2-1 udev的主體部分在udevd.c文件中,它主要監(jiān)控來自4個文件描述符的事件/消息,并做出處理: 1. 來自客戶端的控制消息。這通常由udevcontrol命令通過地址為/org/kernel/udev/udevd的本地socket,向udevd發(fā)送的控制消息。其中消息類型有: l UDEVD_CTRL_STOP_EXEC_QUEUE 停止處理消息隊列。 l UDEVD_CTRL_START_EXEC_QUEUE 開始處理消息隊列。 l UDEVD_CTRL_SET_LOG_LEVEL 設(shè)置LOG的級別。 l UDEVD_CTRL_SET_MAX_CHILDS 設(shè)置最大子進程數(shù)限制。好像沒有用。 l UDEVD_CTRL_SET_MAX_CHILDS_RUNNING 設(shè)置最大運行子進程數(shù)限制(遍歷proc目錄下所有進程,根據(jù)session的值判斷)。 l UDEVD_CTRL_RELOAD_RULES 重新加載配置文件。 2. 來自內(nèi)核的hotplug事件。如果有事件來源于hotplug,它讀取該事件,創(chuàng)建一個udevd_uevent_msg對象,記錄當(dāng)前的消息序列號,設(shè)置消息的狀態(tài)為EVENT_QUEUED,然后并放入running_list和exec_list兩個隊列中,稍后再進行處理。 3. 來自signal handler中的事件。signal handler是異步執(zhí)行的,即使有signal產(chǎn)生,主進程的select并不會喚醒,為了喚醒主進程的select,它建立了一個管道,在signal handler中,向該管道寫入長度為1個子節(jié)的數(shù)據(jù),這樣就可以喚醒主進程的select了。 4. 來自配置文件變化的事件。udev通過文件系統(tǒng)inotify功能,監(jiān)控其配置文件目錄/etc/udev/rules.d,一旦該目錄中文件有變化,它就重新加載配置文件。 其中最主要的事件,當(dāng)然是來自內(nèi)核的hotplug事件,如何處理這些事件是udev的關(guān)鍵。udev本身并不知道如何處理這些事件,也沒有必要知道,因為它只實現(xiàn)機制,而不實現(xiàn)策略。事件的處理是由配置文件決定的,這些配置文件即所謂的rule。 關(guān)于rule的編寫方法可以參考《writing_udev_rules》,udev_rules.c實現(xiàn)了對規(guī)則的解析。 在規(guī)則中,可以讓外部應(yīng)用程序處理某個事件,這有兩種方式,一種是直接執(zhí)行命令,通常是讓modprobe去加載驅(qū)動程序,或者讓mount去加載分區(qū)。另外一種是通過本地socket發(fā)送消息給某個應(yīng)用程序。 在udevd.c:udev_event_process函數(shù)中,我們可以看到,如果RUN參數(shù)以”socket:”開頭則認(rèn)為是發(fā)到socket,否則認(rèn)為是執(zhí)行指定的程序。 下面的規(guī)則是執(zhí)行指定程序: 60-pcmcia.rules: RUN+="/sbin/modprobe pcmcia" 下面的規(guī)則是通過socket發(fā)送消息: 90-hal.rules:RUN+="socket:/org/freedesktop/hal/udev_event" hal正是我們下一步要關(guān)心的,接下來我會分析HAL的實現(xiàn)原理。 ~~end~~ |
第一、什么是udev? 這篇文章UDEV Primer給我們娓娓道來,花點時間預(yù)習(xí)一下是值得的。當(dāng)然,不知道udev是什么也沒關(guān)系, 把它當(dāng)個助記符好了,有了下面的上路指南,可以節(jié)省很多時間。我們只需要樹立一個信念:udev很簡單! 嵌入式的udev應(yīng)用尤其簡單。 第二、為什么udev要取代devfs? 這是生產(chǎn)關(guān)系適應(yīng)生產(chǎn)力的需要,udev好,devfs壞,用好的不用壞的。 udev是硬件平臺無關(guān)的,屬于user space的進程,它脫離驅(qū)動層的關(guān)聯(lián)而建立在操作系統(tǒng)之上,基于這種設(shè) 計實現(xiàn),我們可以隨時修改及刪除/dev下的設(shè)備文件名稱和指向,隨心所欲地按照我們的愿望安排和管理設(shè) 備文件系統(tǒng),而完成如此靈活的功能只需要簡單地修改udev的配置文件即可,無需重新啟動操作系統(tǒng)。udev 已經(jīng)使得我們對設(shè)備的管理如探囊取物般輕松自如。 第三、如何得到udev? udev的主頁在這里:http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html 我們按照下面的步驟來生成udev的工具程序,以arm-linux為例: 1、wget http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/udev-100.tar.bz2 2、tar xjf udev-100.tar.bz2 3、cd udev-100 編輯Makefile,查找CROSS_COMPILE,修改CROSS_COMPILE ?= arm-linux- 4、make 沒有什么意外的話當(dāng)前目錄下生成udev,udevcontrol,udevd,udevinfo,udevmonitor,udevsettle,udevstart, udevtest,udevtrigger九個工具程序,在嵌入式系統(tǒng)里,我們只需要udevd和udevstart就能使udev工作得很好, 其他工具則幫助我們完成udev的信息察看、事件捕捉或者更高級的操作。 另外一個方法是直接使用debian提供的已編譯好的二進制包,美中不足的是版本老了一些。 1、wget http://ftp.us.debian.org/debian/pool/main/u/udev/udev_0.056-3_arm.deb 2、ar -xf udev_0.056-3_arm.deb 3、tar xzf data.tar.gz 在sbin目錄里就有我們需要的udevd和udevstart工具程序。 建議大家采用第一種方式生成的udevd和udevstart。為什么要用最新udev呢?新的強,舊的弱,用強的不用弱的。 第四、如何配置udev? 首先,udev需要內(nèi)核sysfs和tmpfs的支持,sysfs為udev提供設(shè)備入口和uevent通道,tmpfs為udev設(shè)備文件提 供存放空間,也就是說,在上電之前系統(tǒng)上是沒有足夠的設(shè)備文件可用的,我們需要一些技巧讓kernel先引導(dǎo) 起來。 由于在kernel啟動未完成以前我們的設(shè)備文件不可用,如果使用mtd設(shè)備作為rootfs的掛載點,這個時候/dev/mtdblock 是不存在的,我們無法讓kernel找到rootfs,kernel只好停在那里驚慌。 這個問題我們可以通過給kernel傳遞設(shè)備號的方式來解決,在linux系統(tǒng)中,mtdblock的主設(shè)備號是31,part號 從0開始,那么以前的/dev/mtdblock/3就等同于31:03,以次類推,所以我們只需要修改bootloader傳給kernel 的cmd line參數(shù),使root=31:03,就可以讓kernel在udevd未起來之前成功的找到rootfs。 O.K.下一個問題。 其次,需要做的工作就是重新生成rootfs,把udevd和udevstart復(fù)制到/sbin目錄。然后我們需要在/etc/下為udev 建立設(shè)備規(guī)則,這可以說是udev最為復(fù)雜的一步。這篇文章提供了最完整的指導(dǎo):Writing udev rules 文中描述的復(fù)雜規(guī)則我們可以暫時不用去理會,上路指南將帶領(lǐng)我們輕松穿過這片迷霧。這里提供一個由簡入 繁的方法,對于嵌入式系統(tǒng),這樣做可以一勞永逸。 1、在前面用到的udev-100目錄里,有一個etc目錄,里面放著的udev目錄包含了udev設(shè)備規(guī)則的詳細(xì)樣例文 本。為了簡單而又簡潔,我們只需要用到etc/udev/udev.conf這個文件,在我們的rootfs/etc下建立一個udev目 錄,把它復(fù)制過去,這個文件很簡單,除了注釋只有一行,是用來配置日志信息的,嵌入式系統(tǒng)也許用不上 日志,但是udevd需要檢查這個文件。 2、在rootfs/etc/udev下建立一個rules.d目錄,生成一個空的配置文件touch etc/udev/rules.d/udev.conf。然后 我們來編輯這個文件并向它寫入以下配置項: ############################################### # vc devices KERNEL=="tty[0-9]*", NAME="vc/%n" # block devices KERNEL=="loop[0-9]*", NAME="loop/%n" # mtd devices KERNEL=="mtd[0-9]*", NAME="mtd/%n" KERNEL=="mtdblock*", NAME="mtdblock/%n" # input devices KERNEL=="mice" NAME="input/%k" KERNEL=="mouse[0-9]*", NAME="input/%k" KERNEL=="ts[0-9]*", NAME="input/%k" KERNEL=="event[0-9]*", NAME="input/%k" # misc devices KERNEL=="apm_bios", NAME="misc/%k" KERNEL=="rtc", NAME="misc/%k" ################################################ 保存它,我們的設(shè)備文件系統(tǒng)基本上就可以了,udevd和udevstart會自動分析這個文件。 3、為了使udevd在kernel起來后能夠自動運行,我們在rootfs/etc/init.d/rcS中增加以下幾行: ################################## /bin/mount -t tmpfs tmpfs /dev echo "Starting udevd..." /sbin/udevd --daemon /sbin/udevstart ################################## 4、重新生成rootfs,燒寫到flash指定的rootfs part中。 5、如果需要動態(tài)改變設(shè)備規(guī)則,可以把etc/udev放到j(luò)ffs或yaffs part,以備修改,根據(jù)需求而定,可以隨時擴 充udev.conf中的配置項。 |
Udev (簡體中文) From ArchWiki Jump to: navigation, search i18n English Русский 繁體中文 簡體中文 注意: 如果您是從DevFS升級到Udev, 請查看 DevFS to Udev. 這篇文檔將介紹udev的一些新的變化。從084版開始,udev能夠代替hotplug和coldplug的所有功能。正因為這樣,hotplug包已經(jīng)從Arch倉庫中去掉了。 Contents [hide] * 1 重要提示 * 2 基本需求 * 3 最近更新 * 4 模塊禁用列表 * 5 load_modules: 有用的啟動參數(shù) * 6 已知的硬件問題 * 7 自動加載帶來的一些問題 o 7.1 CPUFreq模塊 o 7.2 聲音問題和一些不能自動加載的模塊 o 7.3 多個同類型設(shè)備(網(wǎng)卡,聲卡)每次啟動的都不同 * 8 自己編譯內(nèi)核造成的一些已知問題 o 8.1 Udev無法啟動 o 8.2 CD/DVD符號和權(quán)限錯誤 * 9 Udev小竅門 o 9.1 自動加載usb設(shè)備 重要提示 ...切記,在使用udev加載任何modules(內(nèi)核模塊)之前(無論是否是啟動時自動加載),您必須在/etc/rc.conf將MOD_AUTOLOAD選項設(shè)置為yes ,否則您必須手動加載這些modules。您可以修改rc.conf中的MODULES或者使用modprobe命令來手動加載您所需要的modules。另一種方法是用hwdetect --modules生成系統(tǒng)硬件的modules列表,然后將這個列表添加到rc.conf中讓系統(tǒng)啟動時自動加載這些modules。 基本需求 * 內(nèi)核: 2.6.15或更高版本。 * 您將無法在fstab和bootloader設(shè)置中再使用DevFS格式的設(shè)備名稱! 更多相關(guān)內(nèi)容請查看DevFS to Udev。 最近更新 * startudev程序被取出。如果需要重新加載udev規(guī)則請使用 /etc/start_udev。 * Udev代替了hotplug和hwdetect的功能。同時我們保存了hwdetect,并且只在 mkinitrd程序生成initrd的時候用到。 * Udev可以同時加載多個模塊,這樣可以加快啟動速度,然而,這樣做的結(jié)果是她不能保證每次加載的順序,所以當(dāng)你使用多聲卡或網(wǎng)卡的時候就會出現(xiàn)問題,這個問題下面將會再討論。 模塊禁用列表 udev也會犯錯或加載錯誤的模塊。為了防止錯誤的發(fā)生,你可以使用模塊禁用列表 。一旦加入該列表的模塊,無論是啟動時,或者是運行時(如usb硬盤等)udev都不會加載這些模塊。 只需在您在 rc.conf的MODULES中對應(yīng)模塊前加上感嘆號(!)就可禁用該模塊。 例如, MODULES=(!moduleA !moduleB) load_modules: 有用的啟動參數(shù) 如果您在內(nèi)核啟動參數(shù)中加入load_modules=off,那么udev會停止任何自動加載工作. 如果系統(tǒng)出現(xiàn)問題時,這個功能會十分有用。如果udev加載了有問題的模塊導(dǎo)致系統(tǒng)掛起或者其它嚴(yán)重的問題時,你可以使用這個參數(shù)來禁用自動加載,以此來防止加載有問題的模塊。 已知的硬件問題 - BusLogic設(shè)備被損壞而且導(dǎo)致啟動時死機。 這是一個內(nèi)核的Bug目前還沒有修正。 - PCMCIA讀卡器被認(rèn)為是可移除設(shè)備. 把它們加入到/etc/pmount.allow中,使用hal的pmount來讀取 自動加載帶來的一些問題 CPUFreq模塊 我門還沒有找到一個很好的方法加載不同的CPUFreq控制器,所以我們把從自動加載進程里把它去掉了。如果您需要測量CPU頻率,你必須在rc.conf的MODULES隊列中顯式的加入合適的模塊。 聲音問題和一些不能自動加載的模塊 一些用戶跟蹤發(fā)現(xiàn)問題出在/etc/modprobe.conf中一些舊的部分,試著去掉這些舊的部分再試試看。 多個同類型設(shè)備(網(wǎng)卡,聲卡)每次啟動的都不同 因為udev同時加載所有模塊,所以一些設(shè)備可能初始化順序不同。例如同時有兩個網(wǎng)卡時,它們總是在eth0和eth1之間變來變?nèi)ァ?br /> 常用的解決辦法是在您的rc.conf文件中通過修改MODULES隊列來指明順序。這個隊列里的模塊將在udev自動加載之前由系統(tǒng)加載,因此您可以控制模塊在啟動時加載順序。 # 在e100之前加載8139too MODULES=(8139too e100) 另一個解決網(wǎng)卡的方法是使用udev-sanctified方法為每個網(wǎng)卡靜態(tài)命名。創(chuàng)建文件/etc/udev/rules.d/10-network.rules然后將不同的網(wǎng)卡通過MAC地址綁定到不同的名字上: SUBSYSTEM=="net", SYSFS{address}=="aa:bb:cc:dd:ee:ff", NAME="lan0" SUBSYSTEM=="net", SYSFS{address}=="ff:ee:dd:cc:bb:aa", NAME="wlan0" 同時,您需要注意以下內(nèi)容: * 您可以通過下面的命令獲得網(wǎng)卡的MAC地址:: udevinfo -a -p /sys/class/net/<你的網(wǎng)卡> * 注意在udev規(guī)則文件中使用小寫的16進制MAC地址,因為udev無法識別大寫的MAC地址。 * 一些用戶在使用舊的命名方式時出現(xiàn)問題,例如: eth0, eth1, 等等. 如果出現(xiàn)這個問題,試試使用 "lan"或者"wlan"之類的名字. 注意不要忘記修改您的/dec/rc.conf和其它使用ethX命名的配置文件。 自己編譯內(nèi)核造成的一些已知問題 Udev無法啟動 請確定您的內(nèi)核版本大于或等于2.6.15。較早的內(nèi)核沒有udev自動裝載所需要的uevent功能。 CD/DVD符號和權(quán)限錯誤 如果您使用2.6.15的內(nèi)核的話,您需要安裝ABS的uevent補。ㄋ鼜2.6.16內(nèi)核中抽取了一些uevent功能)。您可以使用abs命令來同步ABS樹,然后您就可以在/var/abs/kernels/kernel26/下找到abs補丁。 Udev小竅門 自動加載usb設(shè)備 KERNEL=="sd[a-z]", NAME="%k", SYMLINK+="usb%m", GROUP="users", OPTIONS="last_rule" ACTION=="add", KERNEL=="sd[a-z][0-9]", SYMLINK+="usb%n", GROUP="users", NAME="%k" ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mkdir -p /mnt/usb%n" ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="vfat", RUN+="/bin/mount -t vfat -o rw,noauto,sync,dirsync,noexec,nodev,noatime,dmask=000,fmask=111 /dev/%k /mnt/usb%n", OPTIONS="last_rule" ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mount -t auto -o rw,noauto,sync,dirsync,noexec,nodev,noatime /dev/%k /mnt/usb%n", OPTIONS="last_rule" ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/umount -l /mnt/usb%n" ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rmdir /mnt/usb%n", OPTIONS="last_rule" 把這些udev規(guī)則放到/etc/udev/rules.d/下任何一個文件名以.rules結(jié)尾的文件中,例如/etc/udev/rules.d/sda.rules。 如果想同時建立/media到/mnt符號連接,可以使用下面的版本: KERNEL=="sd[a-z]", NAME="%k", SYMLINK+="usbhd-%k", GROUP="users", OPTIONS="last_rule" ACTION=="add", KERNEL=="sd[a-z][0-9]", SYMLINK+="usbhd-%k", GROUP="users", NAME="%k" ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mkdir -p /media/usbhd-%k" ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/ln -s /media/usbhd-%k /mnt/usbhd-%k" ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="vfat", RUN+="/bin/mount -t vfat -o rw,noauto,sync,dirsync,noexec,nodev,noatime,dmask=000,fmask=111 /dev/%k /media/usbhd-%k", OPTIONS="last_rule" ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mount -t auto -o rw,noauto,sync,dirsync,noexec,nodev,noatime /dev/%k /media/usbhd-%k", OPTIONS="last_rule" ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rm -f /mnt/usbhd-%k" ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/umount -l /media/usbhd-%k" ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rmdir /media/usbhd-%k", OPTIONS="last_rule" 注意!如果你是用的其它的固定設(shè)備(例如SATA的硬盤,您可以從/etc/fstab中查看)被識別為/dev/sdX,您必須從sd[a-z] 中去掉你的那個sdX。例如,如果您的SATA硬盤被是識別為/dev/sda,您就需要把所有的“sd[a-z]”替換成“sd[b-z]”。在規(guī)則文件的文件名前加上數(shù)字(如:010.udev.rules)是個很好的主意,這樣udev在讀取標(biāo)準(zhǔn)規(guī)則前,將會讀取這個規(guī)則文件。這些規(guī)則設(shè)置后不需要修改/etc/fstab文件。請查看mount命令的參數(shù)來修改權(quán)限等特性(您可以從論壇搜索查看mount命令的參數(shù),然后根據(jù)您的需要修改它們)。 |
udev 是Linux kernel 2.6系列的設(shè)備管理器。它主要的功能是管理/dev目錄底下的設(shè)備節(jié)點。它同時也是用來接替devfs及hotplug的功能,這意味著它要在添加/刪除硬件時處理/dev目錄以及所有用戶空間的行為,包括加載firmware時。 udev的最新版本依賴于升級后的Linux kernel 2.6.13的uevent接口的最新版本。使用新版本udev的系統(tǒng)不能在2.6.13以下版本啟動,除非使用noudev參數(shù)來禁用udev并使用傳統(tǒng)的/dev來進行設(shè)備讀取。 目錄 [隱藏] * 1 概要 * 2 運行方式 * 3 系統(tǒng)架構(gòu) * 4 作者 * 5 外部鏈接 * 6 參考文獻 [編輯] 概要 在傳統(tǒng)的Linux系統(tǒng)中,/dev目錄下的設(shè)備節(jié)點為一系列靜態(tài)存在的文件,而udev則動態(tài)提供了在系統(tǒng)中實際存在的設(shè)備節(jié)點。雖然devfs提供了類似功能,udev的支持者也給出了很多udev實現(xiàn)比devfs好的理由[1]: * udev支持設(shè)備的固定命名,而并不依賴于設(shè)備插入系統(tǒng)的順序。默認(rèn)的udev設(shè)置提供了存儲設(shè)備的固定命名。任何硬盤都根據(jù)其唯一的文件系統(tǒng)id、磁盤名稱及硬件連接的物理位置來進行識別。 * udev完全在用戶空間執(zhí)行,而不是像devfs在內(nèi)核空間一樣執(zhí)行。結(jié)果就是udev將命名策略從內(nèi)核中移走,并可以在節(jié)點創(chuàng)建前用任意程序在設(shè)備屬性中為設(shè)備命名。 [編輯] 運行方式 udev是一個通用的內(nèi)核設(shè)備管理器。它以守護進程的方式運行于Linux系統(tǒng),并監(jiān)聽在新設(shè)備初始化或設(shè)備從系統(tǒng)中移除時內(nèi)核(通過netlink socket)發(fā)出的uevent。 系統(tǒng)提供了一套規(guī)則用于匹配可發(fā)現(xiàn)的設(shè)備事件和屬性的導(dǎo)出值。匹配規(guī)則可能命名并創(chuàng)建設(shè)備節(jié)點,并運行配置程序來對設(shè)備進行設(shè)置。udev規(guī)則可以匹配像內(nèi)核子系統(tǒng)、內(nèi)核設(shè)備名稱、設(shè)備的物理等屬性,或設(shè)備序列號的屬性。規(guī)則也可以請求外部程序提供信息來命名設(shè)備,或指定一個永遠一樣的自定義名稱來命名設(shè)備,而不管設(shè)備什么時候被系統(tǒng)發(fā)現(xiàn)。 [編輯] 系統(tǒng)架構(gòu) Ambox outdated serious.svg 當(dāng)前條目或章節(jié)需要更新。 請更新本文以反映近況和新增內(nèi)容。完成修改時,請移除本模板。 udev系統(tǒng)可以分為三個部分: * namedev函數(shù)庫,處理設(shè)備的命名。 * libsysfs函數(shù)庫,進行設(shè)備信息的讀。080版本后廢棄) * 守護進程udevd,處于用戶空間,用于創(chuàng)建虛擬/dev 系統(tǒng)獲取內(nèi)核通過netlink socket發(fā)出的信息。早期的版本使用hotplug,并在/etc/hotplug.d/default添加一個鏈接到自身來達到目的。 [編輯] 作者 udev由Greg Kroah-Hartman和Kay Sievers共同開發(fā),并得到Dan Stekloff等人的幫助。 [編輯] 外部鏈接 * (英文)udev在kernel.org的主頁 * (英文)Kay Sievers寫的udev最近動態(tài) * (英文)如何編寫udev規(guī)則 * (英文)udev問答集 * (英文)Gentoo的udev指南 * (英文)udev和devfs的對比 * (英文)Linux1394常見問題:在不同驅(qū)動器上創(chuàng)建設(shè)備節(jié)點要如何設(shè)置udev規(guī)則 * (英文)udev教程 [編輯] 參考文獻 1. ^ (英文)udev and devfs - The final word(2003年12月30日).於2008年1月13日查閱. |
頂 |
非常感謝樓主提供這么精彩的文章! |
樓主,我在板子上運行udevd后,插入U盤,內(nèi)核有打印信息,并且在/sys/block下有sdb,sdb1以及里面的dev和uevent,但是udevd卻捕獲不到uevent事件,導(dǎo)致無法創(chuàng)建節(jié)點,規(guī)則文件無法運行,U盤也無法掛載。如果我運行udevstart,節(jié)點就可以被創(chuàng)建,規(guī)則文件就能被執(zhí)行,實現(xiàn)U盤掛載,這說明dev,uevent事件是有效的,只是udevd無法自動進行捕獲處理,你知道這會是什么原因嗎? |
相當(dāng)詳細(xì)的文章哦,非常感謝樓主分享! |
謝謝分享 |