5分鐘理解udev

Udev到底是個什麼鬼?

簡單講:udev負責在用戶空間,根據用戶設置的規則,在監測到設備被插入後,在/dev/下自動創建並命名設備文件節點(實際上只能做一個已存在節點的鏈接文件),也可以自動設置設備屬性。

 

//經常會遇到這種情況,在/sys/目錄下的event0、event1、event2等文件跟/dev/input/event的設備文件對不上,不理解他們到底是如何對應的。沒錯,是udev在負責這個工作。

上面這句話的理解是錯誤的,/dev下的設備文件,大部分是在驅動程序中被創建出來的(使用device_creat函數),而udev只能添加鏈接文件和更改設備文件的相關屬性。

附上一個鏈接地址:http://www.cnblogs.com/hnrainll/archive/2011/06/24/2088577.html     這篇文章介紹了內核驅動是如何創建/dev下的設備節點的

 

2.4版本內核使用devfs來負責完成這項工作,2.6版本後這部分內容被認爲應該運行在用戶空間,且devfs也暴漏出了很多不可修復的bug,所以udev應運而生。

 

 

Devfsudev的區別主要有以下兩點:

1、devfs運行在內核空間(使用devfs_register等API在內核空間註冊設備節點);而udev運行在用戶空間、

2、當用戶訪問/dev下的某個節點時,devfs會自動加載對應的驅動;而udev則並不負責自動加載驅動的工作(2.6版本內核,驅動是在設備被插入/移除時被加載/卸載的,而不是設備被訪問時就加載驅動)。

 

Udev的工作機制是什麼?

Udev完全工作在用戶空間,當一個設備被插入或者移除時,內核會通過netlink套接字發送設備詳細信息到用戶空間,udev獲取到設備信息,根據信息內容在/dev下創建並命名設備節點。

 

既然udev創建節點的時機是設備被插入的時候,那麼就出現一個問題:

冷插拔的設備怎麼辦

由於冷插拔的設備開機時就已經存在,在udev啓動前已經被插入。針對這種情況,sysfs下的設備都存在uevent文件,向該文件寫一個“add,內核會重新發送netlink,之後udev就可以收到設備的詳細信息了,從而創建/dev下對應的設備節點。

 

Udev的規則文件

1. 配置文件
udev的配置文件位於 /etc/udev/ 和 /lib/udev/ ( # 開頭的是註釋)
udev 的主配置文件是 /etc/udev/udev.conf。 它包含一套變量,允許用戶修改 udev 默認值。可以設置的變量如下:
    udev_root    設備目錄,默認是/dev
    udev_log      日誌等級(表示嚴重程度),跟 syslog 一致,例如: err, info, debug。

2. 規則文件
udev的規則文件一般位於 /lib/udev/rules.d/,也可以位於  /etc/udev/rules.d/
規則文件是按照字母順序處理的,不管放在哪個目錄。對於相同名字的規則文件, /etc/udev/rules.d 比  /lib/udev/rules.d 優先。
規則文件必須以 .rules 作爲擴展名,否則不被當作規則文件。
規則文件的每一行都是 key=value 格式。 key 有兩個類型:1)匹配型 key   2)賦值型 key
當所有匹配型 key 都匹配時,該規則即被採用,賦值型 key就會獲得相應的值。
當規則匹配時,可以重命名網絡接口, 創建到設備節點的符號鏈或運行一個指定程序來處理該事件。
一條規則由多個key=value 組成,以英文逗號隔開。 每個key 有一個操作,取決於操作符,有效的操作符如下:
          ==      比較是否相等
          !=       比較是否不相等
          =        給一個key 賦值。表示一個列表的key會被重置,並且把這個唯一的值傳給它
          +=     將一個值增加到key中
          :=      將一個值傳給一個key,並且不允許再修改這個key。

3. 匹配型KEY

下面的 key 可以匹配設備屬性,部分 key 也可用於匹配 sysfs 中的父設備屬性,不僅僅是產生事件的那個設備。
如果在一個規則中,有多個key匹配了一個父設備,則這些 key必須匹配同一個父設備:
ACTION        匹配事件的動作名
DEVPATH    匹配事件的設備devpath
KERNEL      匹配事件的設備名
NAME           匹配網絡接口或者設備節點的名字。NAME 只有在前面的規則賦值之後纔可以使用。
SYMLINK    匹配設備節點符號鏈的名字。SYMLINK 只有在前面的規則賦值之後纔可以使用。可以有多個 symlinks,只需要匹配一個。
SUBSYSTEM    匹配設備子系統
DRIVER           匹配設備的驅動名。只對綁定到一個驅動的設備有用。
ATTR { filename }    匹配事件設備的sysfs 屬性。
KERNELS         向上搜索devpath,直到找到一個匹配的設備名
SUBSYSTEMS    向上搜索devpath,直到找到一個匹配的子系統名
DRIVERS            向上搜索devpath,直到找到一個匹配的驅動名
ATTRS{ filename }    向上搜索devpath,直到找到一個含匹配 sysfs 屬性的設備
ENV{ key }
TAG
          設備的 tag
TEST{octal mode mask}   測試一個文件是否存在,可以指定一個8進制的模式掩碼。
PROGRAM         執行一個程序。如果程序成功返回, key 爲 true。設備的屬性被放在被執行進程的環境變量中,該程序的輸出爲 stdout, 可以從 RESULT 這個 key 讀取。
RESULT      匹配最近一次PROGRAM 調用的返回字符串。它應該在 PROGRAM 之後使用

支持一些shell的通配符:   * (代表[ 0 個到無窮多個 ]任意字符    
                                               ? (代表[一定有一個]任意字符)    
                                               [ ] (代表[一定有一個在括號內]的字符(非任意字符))

4. 賦值型KEY

下面的key 是賦值型 key:
NAME
SYMLINK
OWNER, GROUP, MODE
ATTR { key }
ENV { key }
TAG
 RUN                 
LABEL
              GOTO 可以跳到的地方
GOTO               跳到下一個帶有匹配名字的 LABEL 處。
IMPORT { type }
WAIT_FOR
OPTIONS

NAME,  SYMLINK,   PROGRAM,   OWNER,  GROUP、MODE 和 RUN 這些 field 支持一個簡單的、類似於 printf 函數的格式字符串替換。可用的字符替換如下:
$kernel,  %k : 該設備的內核名字(%k 替換$kernel)
$number,  %n:該設備的內核號碼。例如 sda3 的內核號碼是 3。
$devpath, %p: 該設備的 devpath
$id,   %b:當向上搜索devpath,尋找 SUBSYSTEMS, KERNELS, DRIVERS 和 ATTRS 時,被匹配的設備名字
$driver: 當向上搜索devpath,尋找 SUBSYSTEMS, KERNELS, DRIVERS 和 ATTRS 時,被匹配的驅動名字
$attr { file }, %s { file }: 一個被發現的設備的sysfs 屬性的值。如果該設備沒有該屬性,且前面的 KERNELS,  SUBSYSTEMS,  DRIVERS或 ATTRS 測試選擇的是一個父設備,那麼就用父設備的屬性。如果屬性是一個符號鏈,符號鏈的最後一個元素作爲返回值。
$env { key }, %E { key }: 一個設備屬性值
$major, %M: 該設備的內核主號碼
$minor, %m: 該設備的內核次號碼
$result, %c: 由 PROGRAM 調用的外部程序返回的字符串。如果這個字符串包含空格,可以用 %c{N} 選中第N個字段。如果這個數字N,後面有一個 + 字符, 則表示選中從這個字段開始的所有後面的字符串 %c { N + }
$parent, %p:父設備的節點名字
$name:設備節點的名字,用一個空格作爲分隔符。該值只有在前面的規則賦值之後才存在,或者是remove事件。
$links:當前符號鏈的列表,用空格隔開。該值只有在前面的規則賦值之後才存在,或者是remove事件。
$root, %r:udev_root 的值
$sys, %S:sysfs 掛載點
$tempnode, %N:在真正的設備節點創建之前,創建的一個臨時的設備節點的名字,這個臨時設備節點供外部程序使用。
$$:                     '$'字符自己
%%:                  '%' 字符自己

 

編寫規則文件時可以參考sysfs下設備已經存在的信息,使用udevadm命令可查看內核上送的設備詳細信息。

比如:udevadm info–a –p /sys/devices/soc0/fb.25/graphics/fb0

就可以查看ttyS0的詳細信息,然後根據已經存在信息,重新設置規則文件,上面命令的輸出如下:

Udevadm info starts with the device specified by the devpath and then

walks up the chain of parent devices. It prints for every device

found, all possible attributes in the udev rules key format.

A rule to match, can be composed by the attributes of the device

and the attributes from one single parent device.

 

  looking at device'/devices/soc0/fb.25/graphics/fb0':

    KERNEL=="fb0"

    SUBSYSTEM=="graphics"

    DRIVER==""

    ATTR{pan}=="0,0"

    ATTR{name}=="DISP4BG"

   ATTR{mode}=="U:1024x768p-59"

    ATTR{console}==""

    ATTR{blank}==""

   ATTR{modes}=="U:1024x768p-59"

    ATTR{state}=="0"

   ATTR{fsl_disp_property}=="2-layer-fb-bg"

    ATTR{bits_per_pixel}=="16"

    ATTR{cursor}==""

    ATTR{rotate}=="0"

    ATTR{stride}=="2048"

   ATTR{fsl_disp_dev_property}=="ldb"

   ATTR{virtual_size}=="1024,768"

 

  looking at parent device'/devices/soc0/fb.25':

    KERNELS=="fb.25"

   SUBSYSTEMS=="platform"

   DRIVERS=="mxc_sdc_fb"

 

  looking at parent device'/devices/soc0':

    KERNELS=="soc0"

    SUBSYSTEMS=="soc"

    DRIVERS==""

   ATTRS{revision}=="1.5"

    ATTRS{machine}=="ReciFreescale i.MX6 Quad SABRE Smart Device Board"

    ATTRS{family}=="Freescalei.MX"

   ATTRS{soc_id}=="i.MX6Q"

發佈了23 篇原創文章 · 獲贊 16 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章