devfs、sysfs、udev介紹

devfssysfsudev介紹

一、devfs

linux下有專門的文件系統用來對設備進行管理,devfssysfs就是其中兩種。在2.6內核以前一直使用的是devfsdevfs掛載於/dev目錄下,提供了一種類似於文件的方法來管理位於/dev目錄下的所有設備,我們知道/dev目錄下的每一個文件都對應的是一個設備,至於當前該設備存在與否先且不論,而且這些特殊文件是位於根文件系統上的,在製作文件系統的時候我們就已經建立了這些設備文件,因此通過操作這些特殊文件,可以實現與內核進行交互。但是devfs文件系統有一些缺點,例如:不確定的設備映射,有時一個設備映射的設備文件可能不同,例如我的U盤可能對應sda有可能對應sdb;沒有足夠的主/輔設備號,當設備過多的時候,顯然這會成爲一個問題;/dev目錄下文件太多而且不能表示當前系統上的實際設備;命名不夠靈活,不能任意指定等等。

 

二、sysfs

正因爲上述這些問題的存在,在linux2.6內核以後,引入了一個新的文件系統sysfs,它掛載於/sys目錄下,跟devfs一樣它也是一個虛擬文件系統,也是用來對系統的設備進行管理的,它把實際連接到系統上的設備和總線組織成一個分級的文件,用戶空間的程序同樣可以利用這些信息以實現和內核的交互,該文件系統是當前系統上實際設備樹的一個直觀反應,它是通過kobject子系統來建立這個信息的,當一個kobject被創建的時候,對應的文件和目錄也就被創建了,位於/sys下的相關目錄下,既然每個設備在sysfs中都有唯一對應的目錄,那麼也就可以被用戶空間讀寫了。用戶空間的工具udev就是利用了sysfs提供的信息來實現所有devfs的功能的,但不同的是udev運行在用戶空間中,而devfs卻運行在內核空間,而且udev不存在devfs那些先天的缺陷。很顯然,sysfs將是未來發展的方向。

The top level sysfs directory looks like:
block/
bus/
class/
devices/
firmware/
net/
fs/

devices/  contains a filesystem representation of the device tree. It maps directly to the internal kernel device tree, which is a hierarchy of struct device.
bus/ contains flat directory layout of the various bus types in the kernel. Each bus's directory contains two subdirectories:
devices/
drivers/
devices/ contains symlinks for each device discovered in the system that point to the device's directory under root/.

drivers/ contains a directory for each device driver that is loaded for devices on that particular bus (this assumes that drivers do not span multiple bus types).

fs/ contains a directory for some filesystems. Currently each filesystem wanting to export attributes must create its own hierarchy below fs/ (see ./fuse.txt for an example).

三、udev
    udev
是一種工具,它能夠根據系統中的硬件設備的狀況動態更新設備文件,包括設備文件的創建,刪除等。設備文件通常放在/dev目錄下,使用udev,/dev下面只包含系統中真實存在的設備。它於硬件平臺無關的,位於用戶空間,需要內核sysfstmpfs的支持,sysfsudev提供設備入口和uevent通道,tmpfsudev設備文件提供存放空間。

 

 

 

本文檔遵循 GPL 2 及以後版本發佈,修改、發佈請保持許可證不變


: udev是什麼? 它的目的何在?
: 看看那篇 OLS 2003 上的有關 udev 的文章吧,可以在 docs 目錄裏找到,也能在這裏找到:

 

: udev devfs 是什麼關係
: udev 完全在用戶態 (userspace) 工作,利用設備加入或移除時內核所發送的hotplug 事件 (event) 來工作。關於設備的詳細信息是由內核輸出 (export) 到位於 /sys sysfs 文件系統的。所有的設備命名策略、權限控制和事件處理都是在用戶態下完成的。與此相反,devfs 是作爲內核的一部分工作的。

: 如果 udev 不能完成所有 devfs 的工作的話,爲什麼把 devfs 標記爲OBSOLETE/removed?
: 引用 Al Viro (Linux VFS 內核維護者):
- devfs
所做的工作被確信可以在用戶態來完成。
- devfs
被加入內核之時,大家寄望它的質量可以迎頭趕上。
- devfs
被發現了一些可修復和無法修復的 bug
-
對於可修復的 bug,幾個月前就已經被修復了,其維護者認爲一切良好。
-
對於後者,同樣是相當常一段時間以來沒有改觀了。

devfs 的維護者和作者對它感到失望並且已經停止了對代碼的維護工作。

 

: 但是當一個並不存在的 /dev 節點被打開的時候,udev 並不能如 devfs 一樣自動加載驅動程序。
: 的確如此,但 Linux 的設計是在設備被發現的時候加載模塊,而不是當它被訪問的時候。

: 不過等等,我確實希望 udev 可以在不存在的節點被打開的時候自動加載驅動。這是我使用 devfs 的唯一原因了。給 udev 增加這個功能吧。
: 不,udev 是用來管理 /dev 的,不是用來加載內核驅動的。

: 嗨,求你們了。這不難做到的。
: 這麼個功能對於一個配置正確的計算機是多餘的。系統中所有的設備都應該產生hotplug 事件、加載恰當的驅動,而 udev 將會注意到這點並且爲它創建對應的設備節點。如果你不想讓所有的設備驅動停留在內存之中,應該使用其它東西來管理你的模塊 (如腳本, modules.conf, 等等) 這不是 udev 的工作。

: 但是我真的喜歡那個功能,還是加上吧
: devfs 用的方法導致了大量無用的 modprobe 嘗試,以此程序探測設備是否存在。每個試探性探測都新建一個運行 modprobe 的進程,而幾乎所有這些都是無用的。

: 我喜歡 devfs 的設備文件命名方式,udev 可以這樣命名麼?
: 可以,udev 可以使用 /dev 的命名策略來創建節點。通過一個配置文件,可以把內核缺省的名字映射到 devfs 的名字。可以看看 udev 中帶的 udev.rules.devfs 文件。
注意: devfs 的命名方式是不被建議並且不被官方支持的,因爲它所用的簡單枚舉設備的方式在設備可能被隨時加入或刪除的情況下確實是一個比較笨的方法。這些編號代給你的將只有麻煩,而並不能用來確定設備。看看那個永久性磁盤 (persistentdisk) 的規則就知道如何在用戶態下正確的做這件事,而不是傻傻地列出設備。

: udev 可以爲哪些設備創建節點?
: 所有在 sysfs 中顯示的設備都可以由 udev 來創建節點。如果內核中增加了其它設備的支持,udev 也就自動地可以爲它們工作了。現在所有的塊設備都在被支持之列,大部分的主字符設備也是被支持的。內核開發者們正致力於讓所有的字符設備都被支持。可以到 linux-kernel 郵件列表上尋找補丁或是查看補丁的狀態。

: udev 是否會去掉匿名設備數量的限制?
: udev 完全工作於用戶態。如果內核支持了更多的匿名設備,udev 就會支持。

: udev 是否會支持符號鏈接?
: udev 現在就支持符號鏈接,每個設備節點擁有多個符號鏈接也是被支持的。

: udev 如何處理 /dev 文件系統?
: 建議使用一個每次啓動系統的時候重新創建的 tmpfs 作爲 /dev 的文件系統。不過實際上 udev 並不關心那種文件系統在被使用。

: init 運行之前,udev 如何處理設備?
: udev 可以被放入 initramfs 之中,並在每個設備被發現的時候運行。也可以讓udev 工作在一個真的根分區被加載之後根據 /sys 的內容創建的初始 /dev 目錄之中。

: 我是否可以利用 udev 在一個 USB 設備被加載的時候自動加載上這個設備?
: 技術上講是可以的,但是 udev 不是用於這個工作的。所有的主流發佈版 (distro)都包含了 HAL (http://freedesktop.org/wiki/Software_2fhal) 用於這個工作,它也是專門用於監視設備變更的,並且集成進入了桌面軟件。換個角度說,這可以簡單的通過 fstab 來實現:
/dev/disk/by-label/PENDRIVE /media/PENDRIVE vfat user,noauto 0 0

這樣,用戶可以用如下命令來訪問設備:
$mount /media/PENDRIVE
同樣不需要管理員權限,但卻擁有了設備的全部訪問權限。使用永久性磁盤鏈接 (label, uuid) 將可以指定同一設備,無論其實際上的內核名字是什麼。

: 有什麼我需要注意的安全問題麼?
: 當使用動態設備編號的時候,一個給定的主/從設備號可能在不同時間對應不同的設備,如果一個用戶擁有對這個節點的訪問權限,並且可以創建一個到這個節點的硬鏈接,他就可以如此得到一個這個設備節點的拷貝。當設備被移除之後,udev 刪除了設備節點,但硬鏈接依然存在。如果這個設備節點之後被重新使用不同的訪問權限被創建的時候,其硬鏈接仍然可以使用先前的訪問權限來訪問。 (同樣的問題也存在在使用 PAM 改變訪問權限的 login 上。)

簡單的解決方案就是通過把 /dev 放在 tmpfs 這樣的單獨的文件系統之上來防止建立硬鏈接。

: 我有其他的關於 udev 的問題,我應該問誰?
: linux-hotplug-devel 正是問這些的地方。郵件列表的地址是
[email protected]
加入郵件列表的相關信息可以在如下地址找到
<
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel>
郵件列表的上的既往討論記錄可以在下面地址找到
<
http://marc.theaimsgroup.com/?l=linux-hotplug-devel

 

 

理解和認識udev

http://www.cublog.cn/opera/showart.php?blogid=6006&id=65174               
               
   
因爲本身從事存儲行業,在工作中多次碰到用戶有這樣的要求:我的linux系統中原來有一塊SCSI硬盤,系統分配的設備文件是/dev/sda。現在新增加了一個外置的磁盤陣列,通過SCSI卡連接。但接上這個磁盤陣列後,/dev/sda變成了磁盤陣列的硬盤了,原來內置的SCSI硬盤變成了/dev/sdb,我希望將設備文件固定下來。
   
過去,我總是對用戶說,這個比較麻煩,因爲/dev/sda等文件都是linux內核自動分配的。很難固定下來,除非你更改加載SCSI卡驅動程序的順序,讓內置硬盤連接的SCSI卡比外接磁盤陣列連接的SCSI卡的驅動模塊先加載到內核,這樣就能保證/dev/sda總是指向內置的硬盤。但這種解決方法畢竟不太完美,而且對於其他的即插即用設備,如USB設備等都不適用。
   
近來,通過安裝和升級linux-2.6內核,發現這個問題已經可以通過2.6內核新的sysfs文件系統和udev程序得到解決。下面就是我在學習了udev配置後的一點心得。我喜歡用FAQ的形式來說明。

問:什麼是udev?
答:udev是一種工具,它能夠根據系統中的硬件設備的狀態動態更新設備文件,包括設備文件的創建,刪除等。設備文件通常放在/dev目錄下。使用udev後,在/dev目錄下就只包含系統中真正存在的設備。

問:udev支持什麼內核?
答:udev只支持linux-2.6內核,因爲udev嚴重依賴於sysfs文件系統提供的信息,而sysfs文件系統只在linux-2.6內核中才有。

問:udev是一個內核程序還是用戶程序?
答:udev是一個用戶程序(user-mode daemon)。

問:udevdevfs有什麼差別?
答:udev能夠實現所有devfs實現的功能。但udev運行在用戶模式中,而devfs運行在內核中。據稱:devfs具有一些不太容易解決的先天缺陷。

問:udev的配置文件放在哪裏?
答:udev是一個用戶模式程序。它的配置文件是/etc/udev/udev.conf。這個文件一般缺省有這樣幾項:
udev_root="/dev" ; udev
產生的設備文件的根目錄是/devudev_db="/dev/.udevdb" ; 通過udev產生的設備文件形成的數據庫udev_rules="/etc/udev/rules.d" ;用於指導udev工作的規則所在目錄。

udev_log="err" ;當出現錯誤時,用syslog記錄錯誤信息。

問:udev的工作過程是怎樣的?
答:由於沒有研究過udev的源程序,不敢貿然就說udev的工作過程。我只是通過一些網上的資料和udev的說明文檔,大致猜測它的工作過程可能是這樣的。
  
當內核檢測到在系統中出現了新設備後,內核會在sysfs文件系統中爲該新設備生成一項新的記錄,一般sysfs文件系統會被mount/sys目錄中。新記錄是以一個或多個文件或目錄的方式來表示。每個文件都包含有特定的信息。(信息是如何表述的,還要另外研究?)
  udev
在系統中是以守護進程的方式udevd在運行,它通過某種途徑(到底什麼途徑,目前還沒搞懂。)檢測到新設備的出現,通過查找設備對應的sysfs中的記錄得到設備的一些信息。
  udev
會根據/etc/udev/udev.conf文件中的udev_rules指定的目錄,逐個檢查該目錄下的文件,這個目錄下的文件都是針對某類或某個設備應該施行什麼措施的規則文件。udev讀取文件是按照文件名的ASCII字母順序來讀取的,如果udev一旦找到了與新加入的設備匹配的規則,udev就會根據規則定義的措施對新設備進行配置。同時不再讀後續的規則文件。

問:udev的規則文件的語法是怎樣的?
答:udev的規則文件以行爲單位,以"#"開頭的行代表註釋行。其餘的每一行代表一個規則。每個規則分成一個或多個匹配賦值部分。匹配部分用匹配專用的關鍵字來表示,相應的賦值部分用賦值專用的關鍵字來表示。匹配關鍵字包括:ACTIONKERNELBUSSYSFS等等,賦值關鍵字包括:NAMESYMLINKOWNER等等。具體詳細的描述可以閱讀udevman文檔。

   
下面舉個例子來說明一下,有這樣一條規則:SUBSYSTEM=="net", ACTION=="add", SYSFS{address}=="00:0d:87:f6:59:f3", IMPORT="/sbin/rename_netiface %k eth0"
   
這個規則中的匹配部分有三項,分別是SUBSYSTEMACTIONSYSFS。而"賦值"部分有一項,是IMPORT。這個規則就是說,當系統中出現的新硬件屬於net子系統範疇,系統對該硬件採取的動作是加入這個硬件,且這個硬件在SYSFS文件系統中的“address”信息等於“000d..."時,對這個硬件在udev層次施行的動作是調用外部程序/sbin/rename_netiface,傳遞的參數有兩個,一個是“%k”,代表內核對該新設備定義的名稱。另一個是”eth0“    從上面這個例子中可以看出,udev的規則的寫法比較靈活的,尤其在匹配部分中,可以通過諸如”*“, ”?“,[a-c],[1-9]shell通配符來靈活匹配多個匹配項。具體的語法可以參考udevman文檔。

問:udev怎樣做到不管設備連接的順序而維持一個統一的設備名?
答:實際上,udev是通過對內核產生的設備名增加別名的方式來達到上述目的的。前面說過,udev是用戶模式程序,不會更改內核的行爲。因此,內核依然會我行我素地產生設備名如sda,sdb等。但是,udev可以根據設備的其他信息如總線(bus),生產商(vendor)等不同來區分不同的設備,併產生設備文件。udev只要爲這個設備文件取一個固定的文件名就可以解決這個問題。在後續對設備的操作中,只要引用新的設備名就可以了。但爲了保證最大限度的兼容,一般來說,新設備名總是作爲一個對內核自動產生的設備名的符號鏈接(link)來使用的。

 
例如:內核產生了sda設備名,而根據信息,這個設備對應於是我的內置硬盤,那我就可以制定udev規則,讓udev除了產生/dev/sda設備文件外,另外創建一個符號鏈接叫/dev/internalHD。這樣,我在fstab文件中,就可以用/dev/internalHD來代替原來的/dev/sda了。下次,由於某些原因,這個硬盤在內核中變成了sdb設備名了,那也不用着急,udev還會自動產生/dev/internalHD這個鏈接,並指向正確的/dev/sdb設備。所有其他的文件像fstab等都不用修改。

問:怎樣才能找到這些設備信息,並把他們放到udev的規則文件中來匹配呢?
答:這個問題比較難,網上資料不多,我只找到一篇文章來介紹如何寫udev的規則。他的基本方法是通過udevinfo這個實用程序來找到那些可以作爲規則文件裏的匹配項的項目。有這樣兩種情況可以使用這個工具:
   
第一種情況是,當你把設備插入系統後,系統爲設備產生了設備名(如/dev/sda)。那樣的
話,你先用udevinfo -q path -n/dev/sda,命令會產生一個該設備名對應的在sysfs下的路徑,如/block/sda。然後,你再用udevinfo -a -p/sys/block/sda,這個命令會顯示一堆信息,信息分成很多塊。這些信息實際來自於操作系統維護的sysfs鏈表,不同的塊對應不同的路徑。你就可以用這些信息來作爲udev規則文件中的匹配項。但需要注意的是,同一個規則只能使用同一塊中顯示的信息,不能跨塊書寫規則。
   
第二種情況是,不知道系統產生的設備名,那就只有到/sys目錄下去逐個目錄查找了,反覆用udevinfo
-a -p/sys/path...
這個命令看信息,如果對應的信息是這個設備的,那就恭喜你。否則就再換個目錄。當然,在這種情況下,成功的可能性比較小。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章