RH436 UNIT 3 UDEV

Introduction

Unit Goal

        Describe udev

        Describe the /sys file system

        Write custom udev rules

Unit Sections

        What is udev?

        The /sys File System

        Monitoring udev

        Writing Custom udev Rules

Hands-On Activitles

        Explore the /sys File System

        Monitoring udev

        Write a Custom udev Rule

Unit Test

        Write a Custom udev Rule for iSCSI Storage

What is udev

        在早起的unix/linux設備中,存入/dev/下面的設備文件已經成爲一組靜態文件,無法動態控制其name等屬性。如果在機器中有大量設備,我們則無法進行詳細區分。

[root@node1 ~]# ls -rlt /etc/rc.d/rc.sysinit
-rwxr-xr-x. 1 root root 19114 May 23  2012 /etc/rc.d/rc.sysinit

        udev通過一個守護進程的方式(rc.sysinit)對設備節點進行管理。管理對象則爲/dev目錄下的設備文件。

使用udev有什麼好處:

        動態管理:udev的守護進程監聽來自內核的uevent(device event),在進行添加/刪除device的操作時,udev也通過接收到的uevent來判斷刪除/dev下的設備文件。從而避免出現在/dev/產生大量的空設備文件。

        自定義命名規則:通過規則文件來強制的限定某些設備的設備文件名稱,而不是通過插拔順序成/dev/sda,/dev/sdb等等。

        設定設備的所有者以及權限:同樣可以通過規則文件來限定device 的所有者/組以及相關權限。

udev是如何實現的:

image

默認的udev範例:

[root@node1 dev]# ls -rlt |grep sr*
brw-rw----. 1 root cdrom    11,   0 Oct 25 17:22 sr0
lrwxrwxrwx. 1 root root           3 Oct 25 17:22 cdrw -> sr0
lrwxrwxrwx. 1 root root           3 Oct 25 17:22 cdrom -> sr0
lrwxrwxrwx. 1 root root           3 Oct 25 17:22 dvdrw -> sr0
lrwxrwxrwx. 1 root root           3 Oct 25 17:22 dvd –> sr0

        我們看到以上設備文件,發現cdrw,cdrom,dvdrw,dvd都是連接到sr0設備的。我們只有一個attached CD compatible optical drive(其實就是光驅)。當系統插入相關設備的時候(例如插入CD光盤),udevd就監聽到了uevent,然後在配置文件找到相關的規則文件,如下:

[root@node1 rules.d]# more 70-persistent-cd.rules
# This file was automatically generated by the /lib/udev/write_cd_rules
# program, run by the cd-aliases-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and set the $GENERATED variable.

# VMware_IDE_CDR10 (pci-0000:00:07.1-scsi-1:0:0:0)
SUBSYSTEM=="block", ENV{ID_CDROM}=="?*", ENV{ID_PATH}=="pci-0000:00:07.1-scsi-1:0:0:0", SYMLINK+="cdrom", ENV{GENERATED}="1"
SUBSYSTEM=="block", ENV{ID_CDROM}=="?*", ENV{ID_PATH}=="pci-0000:00:07.1-scsi-1:0:0:0", SYMLINK+="cdrw", ENV{GENERATED}="1"
SUBSYSTEM=="block", ENV{ID_CDROM}=="?*", ENV{ID_PATH}=="pci-0000:00:07.1-scsi-1:0:0:0", SYMLINK+="dvd", ENV{GENERATED}="1"
SUBSYSTEM=="block", ENV{ID_CDROM}=="?*", ENV{ID_PATH}=="pci-0000:00:07.1-scsi-1:0:0:0", SYMLINK+="dvdrw", ENV{GENERATED}="1"

        現在我們插入的CD光盤,那udev就匹配其中的一條rule,激活了/dev/cdrom。這樣做的目的就是便於管理。通過以下可證實,我們插入dvd光盤,其實設備文件原本應該是/dev/sr0:

[root@node1 rules.d]# mount /dev/sr0 /media/dvd
mount: block device /dev/sr0 is write-protected, mounting read-only
[root@node1 rules.d]# cd /media/dvd/
[root@node1 dvd]# ls
EFI               Packages                  RELEASE-NOTES-gu-IN.html  RELEASE-NOTES-or-IN.html  RELEASE-NOTES-zh-TW.html
EULA              README                    RELEASE-NOTES-hi-IN.html  RELEASE-NOTES-pa-IN.html  repodata
GPL               RELEASE-NOTES-as-IN.html  RELEASE-NOTES-it-IT.html  RELEASE-NOTES-pt-BR.html  ResilientStorage
HighAvailability  RELEASE-NOTES-bn-IN.html  RELEASE-NOTES-ja-JP.html  RELEASE-NOTES-ru-RU.html  RPM-GPG-KEY-redhat-beta
images            RELEASE-NOTES-de-DE.html  RELEASE-NOTES-kn-IN.html  RELEASE-NOTES-si-LK.html  RPM-GPG-KEY-redhat-release
isolinux          RELEASE-NOTES-en-US.html  RELEASE-NOTES-ko-KR.html  RELEASE-NOTES-ta-IN.html  ScalableFileSystem
LoadBalancer      RELEASE-NOTES-es-ES.html  RELEASE-NOTES-ml-IN.html  RELEASE-NOTES-te-IN.html  Server
media.repo        RELEASE-NOTES-fr-FR.html  RELEASE-NOTES-mr-IN.html  RELEASE-NOTES-zh-CN.html  TRANS.TBL
[root@node1 dvd]#

        在進行分區的時候可能會提示你/dev/sr0 read only ,是因爲你掛載了cdrom ,而分區系統並沒有提示你/dev/cdrom read only ,原因可想而知。

Getting to Know Udev

1. udev and it’s associated daemon processes are started by:  B

a. Runlevel3 and 5 only

b. By the rc.sysinit script

c. by chkconfig

d. a service sript in /etc/init.d

2. Which of the following statements is false about udev?   D

a. udev creates device files or nodes.

b. udev can create symbolic links that point to device files.

c. udev users deamon processes called udevd

d. You can not change how udev creates or maintains device files.

3. True or False, udev can create device files with a specific user owner?  A

a. True

b. False

The /sys File System

        sysfs(/sys file system)是一個kernel維護文件系統,類似於 /proc。相同的地方是與/proc一樣,/sys也不會持續變化。但是相比/proc,/sys導出內核數據的方式更爲統一,並且組織的更好。/sys下面所包含的信息,由內核提供,主要爲連接到系統的設備信息。例如/sys/block下面存放着塊設備信息,/sys/block/sda下面放着第一塊scsi硬盤的設置與信息。

        /sys下面的信息,有些是可以修改的,有些是read only。例如/sys/block/sda/device/model 或者 /sys/block/sda/size 是隻讀不可修改的。而/sys/block/sda/queue是可以修改的。又比如/sys/block/sda/queue/scheduler 通過此文件就可以修改sda的IO調度器。

        那麼sysfs又是怎麼跟udev交互工作的呢?在文章前部分的圖解裏面有說udevd通過uevent中的內容進行調度工作,這個uevent文件保存於/sys/block/sda下面。通過sys與udev的交互決定了/dev/下面的內容。

Block目錄:包含所有的塊設備
Devices目錄:包含系統所有的設備,並根據設備掛接的總線類型組織成層次結構
Bus目錄:包含系統中所有的總線類型
Drivers目錄:包括內核中所有已註冊的設備驅動程序
Class目錄:系統中的設備類型(如網卡設備,聲卡設備等)

        /sys/block和/sys/dev/block的區別:都是通過連接到設備文件,/sys/block下面存儲的設備名,而/sys/dev/block裏面存儲的設備號。

Monitoring udev

        當kernel識別到一個設備,恰將觸發以下事件:

1. kernel會在/sys下面填充關於設備的架構。

2. kernel將發送uevent給udev

3. udev接收到uevent之後,查找/etc/udev/rules.d/下面的規則文件,查找到所匹配的規則,然後根據規則創建一個新的device node。

        可以使用udevadm命令與udev進行互動。下圖中,我們使用udevadm monitor監控udevent,然後連接到已經做好的iscsi上。

^C[root@node1 ~]# udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[1382973390.161443] add      /devices/platform/host3 (scsi)
KERNEL[1382973390.161793] add      /devices/platform/host3/scsi_host/host3 (scsi_host)
KERNEL[1382973390.161802] add      /devices/platform/host3/iscsi_host/host3 (iscsi_host)
KERNEL[1382973390.161813] add      /devices/platform/host3/session1/iscsi_session/session1 (iscsi_session)
KERNEL[1382973390.161822] add      /devices/platform/host3/session1/connection1:0/iscsi_connection/connection1:0 (iscsi_connection)
UDEV  [1382973390.163582] add      /devices/platform/host3 (scsi)
UDEV  [1382973390.167747] add      /devices/platform/host3/iscsi_host/host3 (iscsi_host)
UDEV  [1382973390.169998] add      /devices/platform/host3/scsi_host/host3 (scsi_host)
UDEV  [1382973390.171241] add      /devices/platform/host3/session1/iscsi_session/session1 (iscsi_session)
UDEV  [1382973390.171317] add      /devices/platform/host3/session1/connection1:0/iscsi_connection/connection1:0 (iscsi_connection)
KERNEL[1382973390.414694] add      /devices/platform/host3/session1/target3:0:0 (scsi)
UDEV  [1382973390.415049] add      /devices/platform/host3/session1/target3:0:0 (scsi)
KERNEL[1382973390.415213] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0 (scsi)
KERNEL[1382973390.418277] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
KERNEL[1382973390.422508] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0/scsi_generic/sg2 (scsi_generic)
KERNEL[1382973390.423154] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
KERNEL[1382973390.424946] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1 (scsi)
KERNEL[1382973390.425341] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/scsi_disk/3:0:0:1 (scsi_disk)
KERNEL[1382973390.425831] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/scsi_device/3:0:0:1 (scsi_device)
KERNEL[1382973390.425951] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/scsi_generic/sg3 (scsi_generic)
KERNEL[1382973390.426038] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/bsg/3:0:0:1 (bsg)
KERNEL[1382973390.443417] add      /devices/virtual/bdi/8:16 (bdi)
UDEV  [1382973390.444402] add      /devices/virtual/bdi/8:16 (bdi)
UDEV  [1382973390.461691] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0 (scsi)
UDEV  [1382973390.469917] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0/scsi_device/3:0:0:0 (scsi_device)
KERNEL[1382973390.472915] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/block/sdb (block)
KERNEL[1382973390.472996] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/block/sdb/sdb1 (block)
UDEV  [1382973390.481391] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1 (scsi)
UDEV  [1382973390.482262] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/scsi_disk/3:0:0:1 (scsi_disk)
UDEV  [1382973390.485659] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/scsi_device/3:0:0:1 (scsi_device)
UDEV  [1382973390.511379] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0/bsg/3:0:0:0 (bsg)
UDEV  [1382973390.515498] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/bsg/3:0:0:1 (bsg)
UDEV  [1382973390.521762] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/scsi_generic/sg3 (scsi_generic)
UDEV  [1382973390.523266] add      /devices/platform/host3/session1/target3:0:0/3:0:0:0/scsi_generic/sg2 (scsi_generic)
UDEV  [1382973390.649027] add      /devices/platform/host3/session1/target3:0:0/3:0:0:1/block/sdb (block)

        從KERNEL行以下打印出的就是當login iscsi設備時的uevent信息。注意,uevent中是以/sys作爲根目錄的,例如/devices目錄其實/sys/devices目錄。udev收到uevent之後,通過計算判斷出iscsi device的架構,從而created block device files。從上圖可以看出,新添加進的硬盤位 sdb。

        udevadm的一個特性就是可以很方便的查找關於device的信息,就像剛纔所使用的udevadm monitor,可以收集到當新設備被kernel識別後所發出的uevent,udev接收後創建塊設備文件的一系列過程。udevadm info 可以在udev database中查看關於設備更多的信息。例如:

[root@node1 ~]# udevadm info --attribute-walk --name=sdb

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/platform/host4/session2/target4:0:0/4:0:0:1/block/sdb':
    KERNEL=="sdb"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{range}=="16"
    ATTR{ext_range}=="256"
    ATTR{removable}=="0"
    ATTR{ro}=="0"
    ATTR{size}=="2097152"
    ATTR{alignment_offset}=="0"
    ATTR{discard_alignment}=="0"
    ATTR{capability}=="52"
    ATTR{stat}=="     172       13     1480       62        0        0        0        0        0       62       62"
    ATTR{inflight}=="       0        0"

  looking at parent device '/devices/platform/host4/session2/target4:0:0/4:0:0:1':
    KERNELS=="4:0:0:1"
    SUBSYSTEMS=="scsi"
    DRIVERS=="sd"
    ATTRS{device_blocked}=="0"
    ATTRS{type}=="0"
    ATTRS{scsi_level}=="6"
    ATTRS{vendor}=="IET     "
    ATTRS{model}=="VIRTUAL-DISK    "
    ATTRS{rev}=="0001"
    ATTRS{state}=="running"
    ATTRS{timeout}=="30"
    ATTRS{iocounterbits}=="32"
    ATTRS{iorequest_cnt}=="0xcb"
    ATTRS{iodone_cnt}=="0xcb"
    ATTRS{ioerr_cnt}=="0x1"
    ATTRS{modalias}=="scsi:t-0x00"
    ATTRS{evt_media_change}=="0"
    ATTRS{dh_state}=="detached"
    ATTRS{queue_depth}=="32"
    ATTRS{queue_ramp_up_period}=="120000"
    ATTRS{queue_type}=="none"

  looking at parent device '/devices/platform/host4/session2/target4:0:0':
    KERNELS=="target4:0:0"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/platform/host4/session2':
    KERNELS=="session2"
    SUBSYSTEMS==""
    DRIVERS==""

  looking at parent device '/devices/platform/host4':
    KERNELS=="host4"
    SUBSYSTEMS=="scsi"
    DRIVERS==""

  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""

--attribute-walk
    Print all sysfs properties of the specified device that can be used in udev rules to match the specified
    device. It prints all devices along the chain, up to the root of sysfs that can be used in udev rules.

        在以上的輸出中我們可以看到設備的相關信息,如size,model,manufacturer,serial number,kernel module,power information或更多。注意查看looking at parent device,上圖排出了多個目錄,每個目錄都是上層目錄的父目錄。這些目錄都是在/sys下的。

        使用udevadm info 需要指定一些參數 --name=sdb 表明我們要查詢的設備時/dev/sdb。—attribute-walk 表示將輸出sdb相關層次的屬性信息。另外—attribute-walk中輸出的屬性可以用來我們寫udev rules時使用。

Writing Custom udev Rules

          編寫udev rule在/etc/udev/rules.d/下面添加rule file,當kernel識別到device的時候,將在這裏(和/lib/udev/rules.d)查找相關匹配的規則。規則文件命名最好按照命名規範,two-digits-function.rules 只有.rules後綴才能被內核解析。

        inotify:它是一個內核用於通知用戶空間程序文件系統變化的機制。

        udevd使用inotify來監控udev rule文件的變化並直接應用,不需要我們手動進行加載。如果希望確保更改的udev rule生效,可以使用udevadm control –reload-rules 進行重新加載。

--reload-rules
           Signal udevd to reload the rules files. The udev daemon detects changes automatically, this option is
           usually not needed. Reloading rules does not apply any changes to already existing devices.  (注:reloading rule不會對已存在的devices生效)

Writing a Custom Rule

        定製udev規則分兩部分,前一部分用於測試匹配,匹配內容包括設備類型,串口號,配置信息等;後一部分用於賦值,如符號鏈接,權限,配置信息等。前提是所有測試匹配都通過。

        udev rule的基本語法爲逗號隔開每一個條件,使用運算符號來進行匹配賦值,常用運算符號的內容如下:

==        匹配符,相等

!=         匹配符,不等

=          賦值,只分配單一值

+=        賦值,值可以爲一個list

:=         賦值並鎖定,防止以後被修改。

Examples       

        SUBSYSTEM==”block”, KERNEL==”sd*” ,SYMLINK+=”mydisks/%k”

        在這個範例中,如果新加入設備的信息符合 SUBSYSTEM==”block”, KERNEL==”sd*” ,則在創建symbolic links時賦值SYMLINK+=”mydisks/%k” 。在編寫udev rule時可以用到通配符,這些通配符的使用方式如bash shell的一樣(例如*,? and [])。

常用的變量通配符:

$kernel, %k
    The kernel name for this device.

$number, %n
    The kernel number for this device. For example, ′sda3′ has kernel number of ′3′

$devpath, %p
    The devpath of the device.

全部通配符的說明在udev的man手冊可以找到。

       這些變量的通配符取自device的attribute,例如範例中的%k ,在udevadm info –attribute-walk –name=sda 的結果中,可以找到kernel=”sda”,而這裏賦值SYMLINK+=“mydisks/%k” 會在/dev/下創建符號鏈接 /dev/mydisks/sda 這裏的sda則爲變量在屬性中取到的kernel。

在以下的例子中將用到下面的變量

PROGRAM
    Execute a program. The key is true, if the program returns successfully. The device properties are made
    available to the executed program in the environment. The program′s output printed to stdout, is available
    in the RESULT key.

RESULT
    Match the returned string of the last PROGRAM call. This key can be used in the same or in any later rule
    after a PROGRAM call.

        這兩個變量成對出現,PROGRAM中的命令將在可用的shell中執行,執行結果與RESULT的值進行匹配。

例如,我們先選取我們所用的PROGRAM:

[root@node1 rules.d]# scsi_id --whitelisted --replace-whitespace --device /dev/sdb
1IET_00010001

scsi_id是用來檢索或者生成device唯一標示的工具。

        所得到的結果就是我們需要匹配的PROGRAM。然後在編寫策略。

SUBSYSTEM=="block", PROGRAM=="scsi_id --whitelisted --replace-whitespace --device $tempnode", RESULT=="1IET_00010001", SYMLINK+="customdisks/customlink%n"

        寫好之後,重新logon in sdb設備。然後在dev下面查看,就可以看到SYMLINK所設定的值了。

[root@node1 dev]# ls customdisks/customlink
customdisks/customlink

SUBSYSTEM=="block", PROGRAM=="scsi_id --whitelisted --replace-whitespace --device $tempnode", RESULT=="1IET_00010001", RUN+="/usr/bin/wall New disk %k"

        這個例子與上個例子相似,不過不是創建符號鏈接了,而是在匹配成功後,使用RUN變量執行一個wall的命令。 RUN跟PROGRAM都是執行命令,主要區別在於udev不會等待RUN的命令完成,所以RUN中只能寫執行時間相對較短的命令。以下爲RUN的解釋:

RUN
    Add a program to the list of programs to be executed for a specific device. This can only be used for very
    short running tasks. Running an event process for a long period of time may block all further events for
    this or a dependent device. Long running tasks need to be immediately detached from the event process
    itself. If the option RUN{fail_event_on_error} is specified, and the executed program returns non-zero, the
    event will be marked as failed for a possible later handling.

[root@node1 rules.d]# iscsiadm -m node -T iqn.2008-09.com.example:server.target10 -l
Logging in to [iface: default, target: iqn.2008-09.com.example:server.target10, portal: 192.168.1.4,3260] (multiple)
Login to [iface: default, target: iqn.2008-09.com.example:server.target10, portal: 192.168.1.4,3260] successful.
[root@node1 rules.d]#
Broadcast message from [email protected] (Thu Oct 31 01:02:07 2013):

New disk sdb

        打開兩個會話,在重新Login target的時候,每個會話都會執行wall命令,彈出New disk sdb。

SUBSYSTEM=="block", KERNEL=="sdb*", OWNER="student", GROUP="disk", MODE="0640"

        通過以上範例,在創建分區的時候,例如sdb1,sdb2,屬主,屬組和權限都會響應說設置,同樣,我們重新login target

[root@node1 dev]# ls -rlt sdb*
brw-r-----. 1 root disk 8, 16 Oct 31 01:14 sdb
brw-r-----. 1 root disk 8, 17 Oct 31 01:14 sdb1
brw-r-----. 1 root disk 8, 19 Oct 31 01:14 sdb3

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