<source : unsplash>

一、前言

Udev 是一個 Linux 裝置管理器,主要功能是管理 /dev 目錄下的設備節點,像是創造與移除硬體裝置節點。簡言之,若你的機器人也是 /dev裝置下的某個節點,udev可以幫助你的電腦更容易找到。

在預設條件上,硬體裝置掛載的權限屬於Root使用者。也就是說,一般使用者權限是無法執行任何程式(像是ROS節點)。裝置將僅依據插入的順序,裝置被到像是 "ttyACMx" 和 "ttyUSBx" 的名稱,使用者很難得知同一類型的裝置名稱。因此,使用  "udev" 將可以更高效、動態地管理Linux裝置文件。 

在你的電腦中,可能至少已經存在一個以上的 "udev rule",來解決網路裝置的命名問題。你可以在檢視 "/etc/udev/rules.d/ "路徑中的資料夾 - 可能會看到一個名為 "70-persistent-net.rules." 的文件。

一些驅動程式/軟體 套件包已經提供你能使用的 "udev rules"。確認一下 "/etc/udev/rules.d/"這個資料夾,看看是否安裝了任何東西。若套件包並未幫你安裝udev rule,你可以輸入以下指令自行安裝 :
 
sudo cp <rule file> /etc/udev/rules.d/>


二、如何撰寫新的 UDEV RULE

若你仍需自行撰寫規則來命名和給予裝置權限,規則將會變的非常複雜。而以下的寫法已經涵蓋了99% 的ROS應用狀況。接下以ROS中的"urg_nodedriver "為例,進行檢視。

SUBSYSTEMS=="usb", KERNEL=="ttyACM[0-9]*", ACTION=="add", ATTRS{idVendor}=="15d1", ATTRS{idProduct}=="0000", MODE="666", PROGRAM="/opt/ros/kinetic/lib/urg_node/getID /dev/%k q", SYMLINK+="sensors/hokuyo_%c", GROUP="dialout"


如上所示,"udev rule"是由一連串的逗號來區分這些標籤。標籤主要分成 2 個部分 : matching(匹配) 和 configuration(設置),然而它們卻可以任意順序被寫入。


matching(匹配) 

matching 的功能就是讓 udev 裝置管理員和你指定裝置的規則進行匹配。裝置管理員會試著去匹配那些新插入的裝置,所以規則必須夠特定,才能抓到你尋找的裝置是非常重要的,否則最終將以到 IMU 的 " /dev/hokuyo "符號連結結束。

有許多潛在的匹配標籤,而其中挑選最有用的方法是直接從 udev 取得所有裝置屬性。

執行以下指令,嵌入如 "/dev/ttyACM0" 的 <devpath>

udevadm info -a -p $(udevadm info -q path -n <devpath>)

你會得到連結到 udev 的所有可視屬性,看看這 "/dev/ttyACM0"


KERNEL=="ttyACM0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '...':
KERNELS=="3-3:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="cdc_acm"
ATTRS{bInterfaceClass}=="02"
ATTRS{bInterfaceNumber}=="00"
looking at parent device '...':
...
ATTRS{idVendor}=="0483"
ATTRS{idProduct}=="5740"
...

每一個裝置屬性都是一個潛在標籤。你可以使用第一部分的來自原裝置的任何標籤去過濾。使用 regex (正規表達式)來讓匹配更彈性。 (舉例 :[0-9] 可匹配任何數字, * 可匹配任何東西 )

SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", ...

由於在這個方式下,udev是被設計的,你只需沿用原裝置標籤。在上例,就可以使用 "KERNEL" 和 "SUBSYSTEM" 在自己的 udev 規則,但是不能一同使用 DRIVERS 和 ATTRS{idVendor}  來進行匹配。而這通常不是問題,因為 "idVendor" 和 "idProduct" 總是以當前狀態為主,且能清楚辨別大部份裝置的型式。

你也可以加入 "Action" 標籤,通常使用 "add"。當使用的裝置拔掉後,會使用"remove"。

..., ACTION=="add", ...

configuration(設置)


Tag

Usage

MODE=”0666”

Set permissions to allow any user read/write access to the device.

SYMLINK+=”hokuyo”

Create a symlink in /dev/ for this device.

RUN+=”/bin/echo ‘hello world’

Execute an arbitrary command. For advanced usage

確定每個符號連結對於每個裝置都是唯一的是非常好的練習。如果你的許多裝置具有共同型態 (舉例,2 Hokuyos)。或如果你有許多使用通用USB-to-Serial 轉換器的裝置 (舉例,FTDI)。即使 udev 將會以相同的圖像連匹配所有正在匹配的裝置,一個基本的 idVendor 和 idProduct 規則將無法區別這些裝置。以下提供了幾種方法 :

1.直接經由裝置屬性

若你的裝置有唯一的識別碼,像是序列號、自身屬性編碼,你可以直接為每一個裝置創建一個唯一圖像連結 :
..., SYMLINK+=”device_$attr{serial}”, ...

若原裝置有序列號,你可以用環境變數搭配以下技巧。為原裝置創建一個 udev 規則來儲存環境變數 :
..., <match parent device>..., ENV{SERIAL_NUMBER}="$attr{serial_number}"

為子裝置添加一個在圖像連結中使用變數的規則 :
..., <match child device>..., SYMLINK+="device_$env{SERIAL_NUMBER}"

2.經由外部程式

在裝置屬性中,若唯一的識別碼沒來揭露,可以使用 PROGRAM 標籤來執行一個外部指令 :
PROGRAM="/bin/device_namer %k", SYMLINK+="%c"

不像已被拆開的 RUN 標籤,這個指令將會被阻斷 (必須在規則完整進行前被執行),所以它必定快速回傳。 如下列指令,使用此標籤的 "urg_node" 驅動程式來執行ROS binary檔案。
PROGRAM="/opt/ros/kinetic/lib/urg_node/getID /dev/%k q", SYMLINK+="sensors/hokuyo_%c"

替代參數 %k 作為 /dev/ 相關的裝置路徑的參考。%c 作為 PROGRAM 標籤的輸出的參考。

執行一個新的 udev 規則

一旦你將新規則複製 (sudo cp) 到 /etc/udev/rules.d/ 資料夾,可以裝置來測試。執行以下指令來讓 udev 辨識新規則 :
sudo udevadm control --reload-rules && sudo service udev restart && sudo udevadm trigger
 
執行後,應能在 /dev/ 找到一個圖像連結,連向所有裝置路徑(例如 :  /dev/ttyACM0)。且裝置路徑權限應可被所有使用者讀/寫。若你的權限尚未被設定,且圖像連結未如預期般建立在 /dev/,可藉由執行內含適當路徑的指令,試著模擬 udev運作的規則,參考如下 :
udevadm test $(udevadm info -q path -n /dev/ttyACM0)

三、還有幾件事要牢記心中

  • 確認新規則是否遵照約定成俗的方式 - <priority>-<device name>.rules. 。技術上,可對同一個裝置擁有許多規則,且數字決定他們被執行的順序。既然我們撰寫添加的規則,使用前99個數字是安全的。
  • 在一個有著換行的檔案中,你可以有許多規則。確保每個個別規則都在一行中。
  • 確認所有的標籤 (匹配和設置) 都是以逗號作區隔。
  • 確認你的規則都有作換行。
  • 確認你的規則權限是屬於 root (最高權限管理者) - " ll /etc/udev/rules.d/ " 應該顯示此規則檔案的 "root root"

---
參考資料 :
#udev

0 留言