利用UDEV機制固定儲存裝置的名稱
阿新 • • 發佈:2018-12-31
什麼是udev
udev為一些實際的裝置提供了一個動態的裝置目錄,這些目錄裡包含這些實際裝置所對應的檔案。它建立或移除在/dev目錄裡的裝置節點檔案,或者重新命名網路介面。
通常udev執行udevd,如果一個裝置增加進系統或者從系統中移除,它就會直接從核心中接受到這個udev的事件。
如果udev接受到一個裝置事件,它就會從它的配置(或是規則)檔案(有三個位置/etc/udev/rules.d、/dev/.udev/rules.d、/lib/udev/rules.d)中去匹配從sysfs中得到的裝置屬性來辨識這個裝置。這些rules配置檔案會去比較所提供的附加(新增加進來的)的裝置的資訊或者指定一個裝置節點名並操作符號連結名來指示udev執行附加的程式來作為裝置事件的處理。
udev的組成
udev由namedev、libsysfs和udev三部分組成。其中,namedev是裝置命名子系統;libsysfs提供訪問sysfs檔案系統,並從中獲取資訊的標準介面;udev提供/dev裝置節點檔案的動態建立和刪除策略。udev程式負責namedev和libsysfs庫互動的任務,當/sbin/hotplug程式被核心呼叫時,udev將執行。
udev有很多以.rules為字尾的規則檔案,以行為單位,除去以“#”開頭的代表註釋的行外,每一行代表一個規則。每個規則分成一個或多個匹配和賦值部分。匹配部分用匹配專用的關鍵字來表示,相應的賦值部分用專用的關鍵字來表示。
udev的工作原理
裝置節點的建立,是通過sysfs介面分析dev規則檔案取得裝置節點號。udevd通過netlink socket通訊機制在核心和使用者空間之間傳遞資訊,來得知核心裡模組的變化情況,通過hotplug機制得知裝置的插入移除情況。
核心呼叫kobject_uevent函式傳送netlink message給使用者空間,這部分工作通常無需驅動去自己處理,在統一裝置模型裡面,在子系統這一層面,已將這部分程式碼處理好了,包括在裝置對應的特定的Kobject建立和移除的時候都會發送相應add和remove訊息,當然前提是您在核心中配置了hotplug的支援。
Netlink socket作為一種核心和使用者空間的通訊方式,不僅用在hotplug機制中,同樣還應用在其他很多真正和網路相關的核心子系統中。Udevd通過標準的socket機制,建立socket連線來獲取核心廣播的uevent事件並解析這些uevent事件。
應用
要使用udev自定義裝置名,就需要獲取到裝置的相關且唯一的資訊,用於書寫udev規則:
在rhel5,可以使用udevinfo -a -p $(udevinfo -q path -n /dev/sdb)來獲取裝置資訊,在rhel6,使用udevadm info -a -n /dev/sdb來獲取裝置資訊。
針對iscsi裝置,使用udevadm info -a -n /dev/sdb可能獲取不到類似序列號之類的資訊,可以使用udevadm info -q all -n /dev/sdb試試,但是通常我們會這麼去使用,在rhel5, scsi_id -g -s $(udevinfo -q path -n /dev/sdc)獲取資訊,在rhel6,scsi_id --whitelisted --replace-whitespace /dev/sdc獲取資訊,用作書寫udev規則。
下面看看例子:
例一:
如我們rhel6系統插入了一個u盤,自動識別為/dev/sdb,而我們希望將其固定為/dev/MyUsbDisk。
則我們可以使用udevadm info -a -n /dev/sdb獲取到ATTRS{serial}=="AC681DEB"資訊,書寫如下規則即可。
KERNEL=="sd*", SUBSYSTEMS=="usb",ATTRS{serial}=="AC681DEB",NAME="MyUsbDisk"
例二:
rhel6下,已經掛載一個iscsi target端匯出的儲存,沒寫udev規則之前,自動識別為sdc,我們想將這個iscsi儲存的節點固定為叫做Idisk,如果做了分割槽,則sdc1固定為Idisk1。
我們書寫一個udev規則
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM="/sbin/scsi_id --whitelisted --replace-whitespace /dev/$name", RESULT=="1IET_00010001",NAME="Idisk%n"
核心檢測資訊是sd*,子系統資訊為塊裝置,執行程式scsi_id --whitelisted --replace-whitespace /dev/$name,結果為1IET_00010001,則重新命名節點為Idisk%n, $name為核心檢測出資訊是sdb則$name=sdb,%n為核心檢測資訊為sdb,則%n為空,檢測資訊為sdb1,則%n為1,這麼寫的作用在於掛載iscsi匯出的一個lun後,我們對這個lun進行分割槽的情況,如果一個lun為一個分割槽,則無需寫上%n。
擴充套件:
用如下規則之一也可實現上條規則的效果,只是上條規則在iscsi裝置login時能觸發,如下兩條規則必須由udev觸發,如手動start_udev。所以通常應使用上述規則較好。
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM="/sbin/udevadm info -q all -n /dev/$name", RESULT=="*beaf11*", NAME="Idisk%n"
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM="/sbin/udevadm info -q all -p %p", RESULT=="*beaf11*", NAME="Idisk%n"
關於udev的除錯:
udevadm trigger是udev觸發器,執行此指令也是觸發rules規則,執行結果同start_udev。
udevadm test /block/sdc可以看到udev規則執行流程,顯示出來的資訊較多,需要從中提取需要的資訊,達到除錯的目的。
udev為一些實際的裝置提供了一個動態的裝置目錄,這些目錄裡包含這些實際裝置所對應的檔案。它建立或移除在/dev目錄裡的裝置節點檔案,或者重新命名網路介面。
通常udev執行udevd,如果一個裝置增加進系統或者從系統中移除,它就會直接從核心中接受到這個udev的事件。
如果udev接受到一個裝置事件,它就會從它的配置(或是規則)檔案(有三個位置/etc/udev/rules.d、/dev/.udev/rules.d、/lib/udev/rules.d)中去匹配從sysfs中得到的裝置屬性來辨識這個裝置。這些rules配置檔案會去比較所提供的附加(新增加進來的)的裝置的資訊或者指定一個裝置節點名並操作符號連結名來指示udev執行附加的程式來作為裝置事件的處理。
udev的組成
udev由namedev、libsysfs和udev三部分組成。其中,namedev是裝置命名子系統;libsysfs提供訪問sysfs檔案系統,並從中獲取資訊的標準介面;udev提供/dev裝置節點檔案的動態建立和刪除策略。udev程式負責namedev和libsysfs庫互動的任務,當/sbin/hotplug程式被核心呼叫時,udev將執行。
udev有很多以.rules為字尾的規則檔案,以行為單位,除去以“#”開頭的代表註釋的行外,每一行代表一個規則。每個規則分成一個或多個匹配和賦值部分。匹配部分用匹配專用的關鍵字來表示,相應的賦值部分用專用的關鍵字來表示。
udev的工作原理
裝置節點的建立,是通過sysfs介面分析dev規則檔案取得裝置節點號。udevd通過netlink socket通訊機制在核心和使用者空間之間傳遞資訊,來得知核心裡模組的變化情況,通過hotplug機制得知裝置的插入移除情況。
核心呼叫kobject_uevent函式傳送netlink message給使用者空間,這部分工作通常無需驅動去自己處理,在統一裝置模型裡面,在子系統這一層面,已將這部分程式碼處理好了,包括在裝置對應的特定的Kobject建立和移除的時候都會發送相應add和remove訊息,當然前提是您在核心中配置了hotplug的支援。
Netlink socket作為一種核心和使用者空間的通訊方式,不僅用在hotplug機制中,同樣還應用在其他很多真正和網路相關的核心子系統中。Udevd通過標準的socket機制,建立socket連線來獲取核心廣播的uevent事件並解析這些uevent事件。
應用
要使用udev自定義裝置名,就需要獲取到裝置的相關且唯一的資訊,用於書寫udev規則:
在rhel5,可以使用udevinfo -a -p $(udevinfo -q path -n /dev/sdb)來獲取裝置資訊,在rhel6,使用udevadm info -a -n /dev/sdb來獲取裝置資訊。
針對iscsi裝置,使用udevadm info -a -n /dev/sdb可能獲取不到類似序列號之類的資訊,可以使用udevadm info -q all -n /dev/sdb試試,但是通常我們會這麼去使用,在rhel5, scsi_id -g -s $(udevinfo -q path -n /dev/sdc)獲取資訊,在rhel6,scsi_id --whitelisted --replace-whitespace /dev/sdc獲取資訊,用作書寫udev規則。
下面看看例子:
例一:
如我們rhel6系統插入了一個u盤,自動識別為/dev/sdb,而我們希望將其固定為/dev/MyUsbDisk。
則我們可以使用udevadm info -a -n /dev/sdb獲取到ATTRS{serial}=="AC681DEB"資訊,書寫如下規則即可。
KERNEL=="sd*", SUBSYSTEMS=="usb",ATTRS{serial}=="AC681DEB",NAME="MyUsbDisk"
例二:
rhel6下,已經掛載一個iscsi target端匯出的儲存,沒寫udev規則之前,自動識別為sdc,我們想將這個iscsi儲存的節點固定為叫做Idisk,如果做了分割槽,則sdc1固定為Idisk1。
我們書寫一個udev規則
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM="/sbin/scsi_id --whitelisted --replace-whitespace /dev/$name", RESULT=="1IET_00010001",NAME="Idisk%n"
核心檢測資訊是sd*,子系統資訊為塊裝置,執行程式scsi_id --whitelisted --replace-whitespace /dev/$name,結果為1IET_00010001,則重新命名節點為Idisk%n, $name為核心檢測出資訊是sdb則$name=sdb,%n為核心檢測資訊為sdb,則%n為空,檢測資訊為sdb1,則%n為1,這麼寫的作用在於掛載iscsi匯出的一個lun後,我們對這個lun進行分割槽的情況,如果一個lun為一個分割槽,則無需寫上%n。
擴充套件:
用如下規則之一也可實現上條規則的效果,只是上條規則在iscsi裝置login時能觸發,如下兩條規則必須由udev觸發,如手動start_udev。所以通常應使用上述規則較好。
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM="/sbin/udevadm info -q all -n /dev/$name", RESULT=="*beaf11*", NAME="Idisk%n"
KERNEL=="sd*", SUBSYSTEM=="block", PROGRAM="/sbin/udevadm info -q all -p %p", RESULT=="*beaf11*", NAME="Idisk%n"
關於udev的除錯:
udevadm trigger是udev觸發器,執行此指令也是觸發rules規則,執行結果同start_udev。
udevadm test /block/sdc可以看到udev規則執行流程,顯示出來的資訊較多,需要從中提取需要的資訊,達到除錯的目的。