Difference between revisions of "Udev (简体中文)"

From ArchWiki
Jump to navigation Jump to search
(与英文版同步,增加“安装”章节)
Line 11: Line 11:
 
[[ru:Udev]]
 
[[ru:Udev]]
 
[[zh-TW:Udev]]
 
[[zh-TW:Udev]]
'''udev''' 代替了{{Ic|hotplug}} 和 {{Ic|hwdetect}}两个工具.
+
{{TranslationStatus (简体中文)|Udev|2015-10-07|403579}}
 +
摘自[[Wikipedia:Udev|维基百科:Udev]]:
 +
:udev 是 Linux 内核的设备管理器。总的来说,它取代了 devfs hotplug,负责管理 {{ic|/dev}} 中的设备节点。同时,udev 也处理所有用户空间发生的硬件添加、删除事件,以及某些特定设备所需的固件加载。
  
“udev是 Linux 内核的设备管理器。总的来说,它取代了 devfs 和 hotplug,负责管理 {{ic|/dev}} 中的设备节点,。这意味着 udev 要管理{{ic|/dev}}目录以及用户空间中所有的硬件添加删除操作。” 摘自: [[Wikipedia:Udev]]
+
{{ic|udev}} 取代了{{ic|hotplug}} 和 {{Ic|hwdetect}}两个工具。
  
与传统的顺序加载不同,udev 可以并行加载内核模块,具有潜在的性能优势。异步加载模块的方式也有一个天生的缺点:无法保证每次加载模块的顺序,如果机器具有多个块设备,那么它们的设备节点可能随机变化。例如如果有两个硬盘,{{ic|/dev/sda}} 可能会随机变成{{ic|/dev/sdb}}。后面有更详细的信息。
+
与传统的顺序加载相比,udev 通过并行加载内核模块提供了潜在的性能优势。异步加载模块的方式也有一个天生的缺点:无法保证每次加载模块的顺序,如果机器具有多个块设备,那么它们的设备节点可能随机变化。例如如果有两个硬盘,{{ic|/dev/sda}} 可能会随机变成{{ic|/dev/sdb}}。后面有更详细的信息。
  
 
== 安装 ==
 
== 安装 ==
Line 23: Line 25:
 
AUR 里有一个独立的 Udev 派生版:[[eudev]]。
 
AUR 里有一个独立的 Udev 派生版:[[eudev]]。
  
==udev规则==
+
== udev 规则 ==
管理员编写的 udev 的规则保存在{{ic|/etc/udev/rules.d/}},其中的文件名要以{{ic|.rules}}结尾。各种软件包提供的规则文件位于 {{ic|/lib/udev/rules.d/}}。如果两个目录中有相同名称的文件,会使用 {{ic|/etc}} 中的文件。
+
udev 规则以管理员身份编写并保存在 {{ic|/etc/udev/rules.d/}} 目录,其文件名要以 {{ic|.rules}} 结尾。各种软件包提供的规则文件位于 {{ic|/lib/udev/rules.d/}}。如果 {{ic|/usr/lib}} 和 {{ic|/etc}} 这两个目录中有同名文件,则 {{ic|/etc}} 中的文件优先。
  
要想学习写udev规则,请访问[http://www.reactivated.net/writing_udev_rules.html 编写 udev 规则]。
+
=== 编写 udev 规则 ===
  
要得到编写规则可以使用的全部属性,请使用下面的指令:
+
{{Expansion|You can workaround the FUSE errors (caused by udev killing the mount process) by using a systemd service [https://github.com/Ferk/udev-media-automount] [http://jasonwryan.com/blog/2014/01/20/udev/]}}
# udevadm info -a -p [device name]
 
  
用系统中的设备替换上面的{{ic|[device name]}},比如{{ic|/dev/sda}} 或者{{ic|/dev/ttyUSB0}}
+
{{Warning|To mount removable drives, do not call {{ic|mount}} from udev rules. In case of FUSE filesystems, you will get {{ic|Transport endpoint not connected}} errors. Instead, you could use [[udisks]] that handles automount correctly or to make mount work inside udev rules, copy {{ic|/usr/lib/systemd/system/systemd-udevd.service}} to {{ic|/etc/systemd/system/systemd-udevd.service}} and replace {{ic|1=MountFlags=slave}} to {{ic|1=MountFlags=shared}}.[http://unix.stackexchange.com/a/154318] Keep in mind though that udev is not intended to invoke long-running processes.}}
  
udev 会自动检测规则文件的修改,所以更改不需要重启 udev 就会立即生效。但是规则不会被已有设备重新触发,所以热插拔设备(如USB设备等)可能需要重新连接才会使新规则生效。
+
*要想学习写udev规则,请访问[http://www.reactivated.net/writing_udev_rules.html 编写 udev 规则]。
 +
* To see an example udev rule, follow the [http://www.reactivated.net/writing_udev_rules.html#example-printer Examples] section of the above guide.
  
== 使用技巧 ==
+
This is an example of a rule that places a symlink {{ic|/dev/video-cam1}} when a webcamera is connected. First, we have found out that this camera is connected and has loaded with the device {{ic|/dev/video2}}. The reason for writing this rule is that at the next boot the device might just as well show up under a different name like {{ic|/dev/video0}}.
  
 +
{{hc|# udevadm info -a -p $(udevadm info -q path -n /dev/video2)|<nowiki>
 +
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/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0/video4linux/video2':
 +
    KERNEL=="video2"
 +
    SUBSYSTEM=="video4linux"
 +
    ...
 +
  looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0':
 +
    KERNELS=="3-2:1.0"
 +
    SUBSYSTEMS=="usb"
 +
    ...
 +
  looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2':
 +
    KERNELS=="3-2"
 +
    SUBSYSTEMS=="usb"
 +
    ...
 +
    ATTRS{idVendor}=="05a9"
 +
    ...
 +
    ATTRS{manufacturer}=="OmniVision Technologies, Inc."
 +
    ATTRS{removable}=="unknown"
 +
    ATTRS{idProduct}=="4519"
 +
    ATTRS{bDeviceClass}=="00"
 +
    ATTRS{product}=="USB Camera"
 +
    ...
 +
</nowiki>}}
 +
 
 +
From the video4linux device we use {{ic|<nowiki>KERNEL=="video2"</nowiki>}} and {{ic|<nowiki>SUBSYSTEM=="video4linux"</nowiki>}}, then we match the webcam using vendor and product ID's from the usb parent {{ic|<nowiki>SUBSYSTEMS=="usb"</nowiki>}}, {{ic|<nowiki>ATTRS{idVendor}=="05a9"</nowiki>}} and {{ic|<nowiki>ATTRS{idProduct}=="4519"</nowiki>}}.
 +
 
 +
{{hc|/etc/udev/rules.d/83-webcam.rules|<nowiki>
 +
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1"
 +
</nowiki>}}
 +
 
 +
In the example above we create a symlink using {{ic|<nowiki>SYMLINK+="video-cam1"</nowiki>}} but we could easily set user {{ic|<nowiki>OWNER="john"</nowiki>}} or group using {{ic|<nowiki>GROUP="video"</nowiki>}} or set the permissions using {{ic|<nowiki>MODE="0660"</nowiki>}}. However, if you intend to write a rule to do something when a device is being removed, be aware that device attributes may not be accessible. In this case, you will have to work with preset device [[environment variables]]. To monitor those environment variables, execute the following command while unplugging your device:
 +
 
 +
# udevadm monitor --environment --udev
 +
 
 +
In this command's output, you will see value pairs such as ID_VENDOR_ID and ID_MODEL_ID, which match your previously used attributes "idVendor" and "idProduct". A rule that uses device environment variables may look like this:
 +
 
 +
{{hc|/etc/udev/rules.d/83-webcam-removed.rules|<nowiki>
 +
ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="05a9", ENV{ID_MODEL_ID}=="4519", RUN+="/path/to/your/script"
 +
</nowiki>}}
 +
 
 +
=== 列出设备属性 ===
 +
 
 +
To get a list of all of the attributes of a device you can use to write rules, run this command:
 +
 
 +
# udevadm info -a -n [device name]
 +
 
 +
Replace {{ic|[device name]}} with the device present in the system, such as {{ic|/dev/sda}} or {{ic|/dev/ttyUSB0}}.
 +
 
 +
If you do not know the device name you can also list all attributes of a specific system path:
 +
 
 +
# udevadm info -a -p /sys/class/backlight/acpi_video0
 +
 
 +
=== 加载前测试规则 ===
 +
 
 +
# udevadm test $(udevadm info -q path -n [device name]) 2>&1
 +
 
 +
This will not perform all actions in your new rules but it will however process symlink rules on existing devices which might come in handy if you are unable to load them otherwise. You can also directly provide the path to the device you want to test the udev rule for:
 +
 
 +
# udevadm test /sys/class/backlight/acpi_video0/
 +
 
 +
=== 加载新规则 ===
 +
 
 +
Udev 自动侦测规则文件的变化,所以修改会立即生效,无需重启 udev。但已接入设备的规则不会自动触发。像 USB 这类热插拔设备也许需要重新插拔才能使新规则生效,也可能需要卸载并重载内核的 ohci-hcd 和 ehci-hcd 模块以重新挂载所有 USB 设备。
 +
 
 +
如果规则自动重载失败
 +
 
 +
# udevadm control --reload
 +
 
 +
可以手工强制触发规则
 +
 
 +
# udevadm trigger
 +
 
 +
== Udisks ==
 +
 
 +
参阅 [[Udisks]].
 +
 
 +
== 提示与技巧 ==
 +
 
 +
=== 访问固件编程器(烧录器)和 USB 虚拟串行设备 ===
 +
 
 +
{{Accuracy|Making a device world-writable is not secure.}}
 +
{{Style|One example is enough, others can surely be found with {{ic|lsusb}}.}}
 +
 
 +
The following ruleset will allow normal users (within the "users" group) the ability to access the [http://www.ladyada.net/make/usbtinyisp/ USBtinyISP] USB programmer for AVR microcontrollers and a generic (SiLabs [http://www.silabs.com/products/interface/usbtouart CP2102]) USB to UART adapter, the [http://www.atmel.com/tools/AVRDRAGON.aspx?tab=overview Atmel AVR Dragon] programmer, and the [http://www.atmel.com/tools/AVRISPMKII.aspx Atmel AVR ISP mkII]. Adjust the permissions accordingly. Verified as of 31-10-2012.
 +
 
 +
{{hc|/etc/udev/rules.d/50-embedded_devices.rules|2=<nowiki>
 +
# USBtinyISP Programmer rules
 +
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c9f", GROUP="users", MODE="0666"
 +
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0479", GROUP="users", MODE="0666"
 +
 
 +
# USBasp Programmer rules http://www.fischl.de/usbasp/
 +
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05dc", GROUP="users", MODE="0666"
 +
 
 +
# Mdfly.com Generic (SiLabs CP2102) 3.3v/5v USB VComm adapter
 +
SUBSYSTEMS=="usb", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", GROUP="users", MODE="0666"
 +
 
 +
#Atmel AVR Dragon (dragon_isp) rules
 +
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2107", GROUP="users", MODE="0666"
 +
 
 +
#Atmel AVR JTAGICEMKII rules
 +
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2103", GROUP="users", MODE="0666"
 +
 
 +
#Atmel Corp. AVR ISP mkII
 +
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2104", GROUP="users", MODE="0666"
 +
 
 +
#Atmel Copr. JTAGICE3
 +
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2140", GROUP="users", MODE="0666"
 +
</nowiki>}}
 +
 
 +
=== USB 插入时执行规则 ===
 +
 
 +
See the [[Execute on USB insert]] article or the [http://igurublog.wordpress.com/downloads/script-devmon/ devmon wrapper script].
 +
 
 +
=== VGA 线缆接入时执行规则 ===
 +
 
 +
Create the rule {{ic|/etc/udev/rules.d/95-monitor-hotplug.rules}} with the following content to launch {{Pkg|arandr}} on plug in of a VGA monitor cable:
 +
 
 +
KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/''username''/.Xauthority", RUN+="/usr/bin/arandr"
 +
 
 +
=== 侦测新的 eSATA 设备 ===
 +
 
 +
If your eSATA drive is not detected when you plug it in, there are a few things you can try. You can reboot with the eSATA plugged in. Or you could try
 +
 
 +
# echo 0 0 0 | tee /sys/class/scsi_host/host*/scan
 +
 
 +
Or you could install {{AUR|scsiadd}} (from the AUR) and try
 +
 
 +
# scsiadd -s
 +
 
 +
Hopefully, your drive is now in {{ic|/dev}}. If it is not, you could try the above commands while running
 +
 
 +
# udevadm monitor
 +
 
 +
to see if anything is actually happening.
 +
 
 +
=== 将内置 SATA 接口标记为 eSATA ===
 +
 
 +
If you connected a eSATA bay or an other eSATA adapter the system will still recognize this disk as an internal SATA drive. [[GNOME]] and [[KDE]] will ask you for your root password all the time. The following rule will mark the specified SATA-Port as an external eSATA-Port. With that, a normal GNOME user can connect their eSATA drives to that port like a USB drive, without any root password and so on.
 +
 
 +
{{hc|/etc/udev/rules.d/10-esata.rules|2=<nowiki>
 +
DEVPATH=="/devices/pci0000:00/0000:00:1f.2/host4/*", ENV{UDISKS_SYSTEM}="0"
 +
</nowiki>}}
  
=== 屏蔽模块 ===
+
{{Note|The {{ic|DEVPATH}} can be found after connection the eSATA drive with the following commands (replace {{ic|sdb}} accordingly):
极个别情况下,udev 也会犯错或加载错误的模块。为了防止错误的发生,你可以使用模块禁用列表。只要模块加入该列表,无论是启动时,或者是运行时(如usb硬盘等)udev都不会加载这些模块。参见[[blacklisting]].
+
 
 +
# udevadm info -q path -n /dev/sdb
 +
/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb
 +
 
 +
# find /sys/devices/ -name sdb
 +
/sys/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb
 +
}}
 +
 
 +
=== 设置静态设备名 ===
  
=== 已知的硬件问题 ===
+
Because udev loads all modules asynchronously, they are initialized in a different order. This can result in devices randomly switching names. A udev rule can be added to use static device names.
==== BusLogic ====
 
  
BusLogic 设备被损坏而且导致启动时死机。这是一个内核的Bug目前还没有修正。
+
See also [[Persistent block device naming]] for block devices and [[Network configuration#Device names]] for network devices.
  
==== 一些移动设备不可移除 ====
+
==== 视频设备 ====
创建自定义 udev 规则,设置 UDISKS_SYSTEM_INTERNAL=0。参见 udisks 手册。
 
  
=== 自动加载问题 ===
+
For setting up the webcam in the first place, refer to [[Webcam setup#Webcam configuration|Webcam configuration]].
  
==== 声音问题和一些不能自动加载的模块 ====
+
Using multiple webcams, useful for example with {{pkg|motion}} (software motion detector which grabs images from video4linux devices and/or from webcams), will assign video devices as /dev/video0..n randomly on boot. The recommended solution is to create symlinks using an ''udev'' rule (as in the example in [[#Writing udev rules]]):
一些用户发现 {{ic|/etc/modprobe.d/sound.conf}} 中的遗留配置会引起这些问题,请清理配置并重试。
 
{{注意|从 {{Ic|udev>&#61;171}} 开始 OSS 模拟模块({{Ic|snd_seq_oss, snd_pcm_oss, snd_mixer_oss}}) 默认不会自动装载。}}
 
  
=== 多个同类型设备(网卡,声卡)每次启动的都不同 ===
+
{{hc|/etc/udev/rules.d/83-webcam.rules|<nowiki>
 +
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1"
 +
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="08f6", SYMLINK+="video-cam2"
 +
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="0840", SYMLINK+="video-cam3"
 +
</nowiki>}}
  
因为udev同时加载所有模块,所以一些设备可能初始化顺序不同。例如同时有两个网卡时,它们总是在<code>eth0</code>和<code>eth1</code>之间变来变去。
+
{{Note|Using names other than {{ic|/dev/video*}} will break preloading of {{ic|v4l1compat.so}} and perhaps {{ic|v4l2convert.so}}}}
  
常用的解决办法是在您的<code>rc.conf</code>文件中通过修改<code>MODULES</code>队列来指明顺序。这个队列里的模块将在udev自动加载之前由系统加载,因此您可以控制模块在启动时加载顺序。
+
==== 打印机 ====
  
<pre># 在e100之前加载8139too
+
If you use multiple printers, {{ic|/dev/lp[0-9]}} devices will be assigned randomly on boot, which will break e.g. [[CUPS]] configuration.
MODULES=(8139too e100)</pre>
 
  
另一个解决网卡的方法是使用udev-sanctified方法为每个网卡静态命名。创建文件<code>/etc/udev/rules.d/10-network.rules</code>然后将不同的网卡通过MAC地址绑定到不同的名字上:
+
You can create following rule, which will create symlinks under {{ic|/dev/lp/by-id}} and {{ic|/dev/lp/by-path}}, similar to [[Persistent block device naming]] scheme:
<pre>SUBSYSTEM=="net", ATTR{address}=="aa:bb:cc:dd:ee:ff", NAME="lan0"
 
SUBSYSTEM=="net", ATTR{address}=="ff:ee:dd:cc:bb:aa", NAME="wlan0"</pre>
 
  
同时,您需要注意以下内容:
+
{{hc|/etc/udev/rules.d/60-persistent-printer.rules|<nowiki>
* 您可以通过下面的命令获得网卡的MAC地址:: <code>udevadm info -a -p /sys/class/net/<你的网卡></code>
+
ACTION=="remove", GOTO="persistent_printer_end"
* 注意在udev规则文件中使用小写的16进制MAC地址,因为udev无法识别大写的MAC地址。
 
* 一些用户在使用旧的命名方式时出现问题,例如: eth0, eth1, 等等.  如果出现这个问题,试试使用 "lan"或者"wlan"之类的名字.
 
  
注意不要忘记修改其它使用ethX命名的配置文件。
+
# This should not be necessary
 +
#KERNEL!="lp*", GOTO="persistent_printer_end"
  
=== 自己编译内核造成的问题 ===
+
SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
==== Udev无法启动 ====
+
ENV{ID_TYPE}!="printer", GOTO="persistent_printer_end"
请确定您的内核版本大于或等于2.6.32。较早的内核没有udev自动装载所需要的 uevent 功能。
 
  
== Running HAL ==
+
ENV{ID_SERIAL}=="?*", SYMLINK+="lp/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
  
Some programs still require HAL (like Flash DRM content). Hal can be installed from {{AUR|hal}} and {{AUR|hal-info}}.
+
IMPORT{builtin}="path_id"
 +
ENV{ID_PATH}=="?*", SYMLINK+="lp/by-path/$env{ID_PATH}"
  
Using Systemd: one can start and stop the hal service using the following systemd commands:
+
LABEL="persistent_printer_end"
 +
</nowiki>}}
  
Start HAL:
+
==== USB 闪存设备 ====
{{ic|# systemctl start hal.service}}
 
  
Stop HAL:  
+
USB flash devices usually contain partitions, and partition labels are one way to have a static naming for a device. Another way is to create a udev rule for it.
{{ic|# systemctl stop hal.service}}
+
 +
Get the serial number and USB ids from the USB flash drive (if you use multiple of the same make, you might have to check the serial is indeed unique):
 +
lsusb -v | grep -A 5 Vendor
  
Alternatively, one can use the following script:
+
Create a udev rule for it by adding the following to a file in {{ic|/etc/udev/rules.d/}}, such as {{ic|8-usbstick.rules}}:
{{bc|<nowiki>
+
KERNEL=="sd*", ATTRS{serial}=="$SERIAL", ATTRS{idVendor}=="$VENDOR", ATTRS{idProduct}=="$PRODUCT" SYMLINK+="$SYMLINK%n"
#!/bin/bash
 
  
## written by Mark Lee <bluerider>
+
Replace {{ic|$SERIAL}}, {{ic|$VENDOR}}, {{ic|$PRODUCT}} from above output accordingly and {{ic|$SYMLINK}} with the desired name. {{ic|%n}} will expand to the partition number. For example, if the device has two partitions, two symlinks will be created. You do not need to go with the 'serial' attribute. If you have a custom rule of your own, you can put it in as well (e.g. using the vendor name).
## using information from <https://wiki.archlinux.org/index.php/Chromium#Google_Play_.26_Flash>
 
  
## Start and stop Hal service on command for Google Play Movie service
+
Rescan sysfs:
 +
udevadm trigger
 +
Now check the contents of {{ic|/dev}}:
 +
ls /dev
 +
It should show the device with the desired name.
  
function main () {  ## run the main insertion function
+
=== 唤醒挂起的 USB 设备 ===
    clear-cache;  ## remove adobe cache
 
    start-hal;  ## start the hal daemon
 
    read -p "Press 'enter' to stop hal";  ## pause the command line with a read line
 
    stop-hal;  ## stop the hal daemon
 
}
 
  
function clear-cache () {  ## remove adobe cache
+
First, find vendor and product ID of your device, for example
    cd ~/.adobe/Flash_Player;  ## go to Flash player user directory
 
    rm -rf NativeCache AssetCache APSPrivateData2;  ## remove cache
 
}
 
  
function start-hal () { ## start the hal daemon
+
{{hc|<nowiki># lsusb | grep Logitech</nowiki>|Bus 007 Device 002: ID 046d:c52b Logitech, Inc. Unifying Receiver}}
    sudo systemctl start hal.service && ( ## systemd : start hal daemon
 
          echo "Started hal service..."
 
) || (
 
          echo "Failed to start hal service!")
 
}
 
  
function stop-hal () { ## stop the hal daemon
+
Now change the {{ic|power/wakeup}} attribute of the device and the USB controller it is connected to, which is in this case {{ic|driver/usb7/power/wakeup}}. Use the following rule:
sudo systemctl stop hal.service && (  ## systemd : stop hal daemon
 
          echo "Stopped hal service..."
 
    ) || (
 
          echo "Failed to stop hal service!"
 
    )
 
}
 
  
main;  ## run the main insertion function
+
{{hc|/etc/udev/rules.d/50-wake-on-device.rules|<nowiki>
 +
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", ATTR{power/wakeup}="enabled", ATTR{driver/usb7/power/wakeup}="enabled"
 
</nowiki>}}
 
</nowiki>}}
 +
 +
{{Note|Also make sure the USB controller is enabled in {{ic|/proc/acpi/wakeup}}.}}
 +
 +
=== 触发事件 ===
 +
 +
{{Merge|#Testing rules before loading|similar trick}}
 +
 +
It can be useful to trigger various udev events. For example, you might want to simulate a USB device disconnect on a remote machine. In such cases, use {{ic|udevadm trigger}}:
 +
 +
# udevadm trigger -v -t subsystems -c remove -s usb -a "idVendor=abcd"
 +
 +
This command will trigger a USB remove event on all USB devices with vendor ID {{ic|abcd}}.
 +
 +
== 排错 ==
 +
 +
=== 屏蔽模块 ===
 +
极个别情况下,udev 也会犯错或加载错误的模块。为了防止错误的发生,你可以使用模块禁用列表。只要模块加入该列表,无论是启动时,或者是运行时(如usb硬盘等)udev都不会加载这些模块。参见[[blacklisting]].
 +
 +
=== udevd 引导时挂起 ===
 +
 +
After migrating to LDAP or updating an LDAP-backed system udevd can hang at boot at the message "Starting UDev Daemon". This is usually caused by udevd trying to look up a name from LDAP but failing, because the network is not up yet. The solution is to ensure that all system group names are present locally.
 +
 +
Extract the group names referenced in udev rules and the group names actually present on the system:
 +
 +
# fgrep -r GROUP /etc/udev/rules.d/ /usr/lib/udev/rules.d | perl -nle '/GROUP\s*=\s*"(.*?)"/ && print $1;' | sort | uniq > udev_groups
 +
# cut -f1 -d: /etc/gshadow /etc/group | sort | uniq > present_groups
 +
 +
To see the differences, do a side-by-side diff:
 +
 +
# diff -y present_groups udev_groups
 +
...
 +
network       <
 +
nobody       <
 +
ntp       <
 +
optical optical
 +
power       | pcscd
 +
rfkill       <
 +
root root
 +
scanner scanner
 +
smmsp       <
 +
storage storage
 +
...
 +
 +
In this case, the {{ic|pcscd}} group is for some reason not present in the system. [[Users and groups#Group management|Add the missing groups]]. Also, make sure that local resources are looked up before resorting to LDAP. {{ic|/etc/nsswitch.conf}} should contain the following line:
 +
 +
group: files ldap
 +
 +
=== BusLogic ===
 +
 +
BusLogic 设备被损坏而且导致启动时死机。这是一个内核的Bug目前还没有修正。
 +
 +
=== 一些移动设备不可移除 ===
 +
创建自定义 udev 规则,设置 UDISKS_SYSTEM_INTERNAL=0。参见 udisks 手册。
 +
 +
 +
=== 声音问题和一些不能自动加载的模块 ===
 +
一些用户发现 {{ic|/etc/modprobe.d/sound.conf}} 中的遗留配置会引起这些问题,请清理配置并重试。
 +
{{注意|从 {{Ic|udev>&#61;171}} 开始 OSS 模拟模块({{Ic|snd_seq_oss, snd_pcm_oss, snd_mixer_oss}}) 默认不会自动装载。}}
 +
 +
 +
=== IDE CD/DVD 驱动器的支持 ===
 +
 +
Starting with version 170, udev does not support CD-ROM/DVD-ROM drives that are loaded as traditional IDE drives with the {{ic|ide_cd_mod}} module and show up as {{ic|/dev/hd*}}. The drive remains usable for tools which access the hardware directly, like ''cdparanoia'', but is invisible for higher userspace programs, like KDE.
 +
 +
A cause for the loading of the ide_cd_mod module prior to others, like sr_mod, could be e.g. that you have for some reason the module piix loaded with your [[initramfs]]. In that case you can just replace it with ata_piix in your {{ic|/etc/mkinitcpio.conf}}.
 +
 +
=== 光驱被标识为磁盘 ===
 +
 +
If the group ID of your optical drive is set to {{ic|disk}} and you want to have it set to {{ic|optical}}, you have to create a custom udev rule:
 +
 +
{{hc|/etc/udev/rules.d|2=<nowiki>
 +
# permissions for IDE CD devices
 +
SUBSYSTEMS=="ide", KERNEL=="hd[a-z]", ATTR{removable}=="1", ATTRS{media}=="cdrom*", GROUP="optical"
 +
 +
# permissions for SCSI CD devices
 +
SUBSYSTEMS=="scsi", KERNEL=="s[rg][0-9]*", ATTRS{type}=="5", GROUP="optical"</nowiki>}}
 +
 +
== 参阅 ==
 +
 +
* [https://www.kernel.org/pub/linux/utils/kernel/hotplug/udev/udev.html udev 主页]
 +
* [https://www.linux.com/news/hardware/peripherals/180950-udev udev 介绍]
 +
* [http://vger.kernel.org/vger-lists.html#linux-hotplug udev 邮件列表]
 +
* [http://jasonwryan.com/blog/2014/01/20/udev/ Scripting with udev]
 +
* [http://www.reactivated.net/writing_udev_rules.html 编写 udev 规则]

Revision as of 09:02, 7 October 2015

zh-TW:Udev

翻译状态: 本文是英文页面 Udev翻译,最后翻译时间:2015-10-07,点击这里可以查看翻译后英文页面的改动。

摘自维基百科:Udev

udev 是 Linux 内核的设备管理器。总的来说,它取代了 devfs 和 hotplug,负责管理 /dev 中的设备节点。同时,udev 也处理所有用户空间发生的硬件添加、删除事件,以及某些特定设备所需的固件加载。

udev 取代了hotplughwdetect两个工具。

与传统的顺序加载相比,udev 通过并行加载内核模块提供了潜在的性能优势。异步加载模块的方式也有一个天生的缺点:无法保证每次加载模块的顺序,如果机器具有多个块设备,那么它们的设备节点可能随机变化。例如如果有两个硬盘,/dev/sda 可能会随机变成/dev/sdb。后面有更详细的信息。

安装

Udev 现在是 systemd 的组成部分,默认已安装。有关信息请查阅 systemd-udevd.service(8)手册页

AUR 里有一个独立的 Udev 派生版:eudev

udev 规则

udev 规则以管理员身份编写并保存在 /etc/udev/rules.d/ 目录,其文件名要以 .rules 结尾。各种软件包提供的规则文件位于 /lib/udev/rules.d/。如果 /usr/lib/etc 这两个目录中有同名文件,则 /etc 中的文件优先。

编写 udev 规则

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: You can workaround the FUSE errors (caused by udev killing the mount process) by using a systemd service [1] [2] (Discuss in Talk:Udev (简体中文)#)
Warning: To mount removable drives, do not call mount from udev rules. In case of FUSE filesystems, you will get Transport endpoint not connected errors. Instead, you could use udisks that handles automount correctly or to make mount work inside udev rules, copy /usr/lib/systemd/system/systemd-udevd.service to /etc/systemd/system/systemd-udevd.service and replace MountFlags=slave to MountFlags=shared.[3] Keep in mind though that udev is not intended to invoke long-running processes.
  • 要想学习写udev规则,请访问编写 udev 规则
  • To see an example udev rule, follow the Examples section of the above guide.

This is an example of a rule that places a symlink /dev/video-cam1 when a webcamera is connected. First, we have found out that this camera is connected and has loaded with the device /dev/video2. The reason for writing this rule is that at the next boot the device might just as well show up under a different name like /dev/video0.

# udevadm info -a -p $(udevadm info -q path -n /dev/video2)
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/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0/video4linux/video2':
    KERNEL=="video2"
    SUBSYSTEM=="video4linux"
    ...
  looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2/3-2:1.0':
    KERNELS=="3-2:1.0"
    SUBSYSTEMS=="usb"
    ...
  looking at parent device '/devices/pci0000:00/0000:00:04.1/usb3/3-2':
    KERNELS=="3-2"
    SUBSYSTEMS=="usb"
    ...
    ATTRS{idVendor}=="05a9"
    ...
    ATTRS{manufacturer}=="OmniVision Technologies, Inc."
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="4519"
    ATTRS{bDeviceClass}=="00"
    ATTRS{product}=="USB Camera"
    ...

From the video4linux device we use KERNEL=="video2" and SUBSYSTEM=="video4linux", then we match the webcam using vendor and product ID's from the usb parent SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9" and ATTRS{idProduct}=="4519".

/etc/udev/rules.d/83-webcam.rules
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1"

In the example above we create a symlink using SYMLINK+="video-cam1" but we could easily set user OWNER="john" or group using GROUP="video" or set the permissions using MODE="0660". However, if you intend to write a rule to do something when a device is being removed, be aware that device attributes may not be accessible. In this case, you will have to work with preset device environment variables. To monitor those environment variables, execute the following command while unplugging your device:

# udevadm monitor --environment --udev

In this command's output, you will see value pairs such as ID_VENDOR_ID and ID_MODEL_ID, which match your previously used attributes "idVendor" and "idProduct". A rule that uses device environment variables may look like this:

/etc/udev/rules.d/83-webcam-removed.rules
ACTION=="remove", SUBSYSTEM=="usb", ENV{ID_VENDOR_ID}=="05a9", ENV{ID_MODEL_ID}=="4519", RUN+="/path/to/your/script"

列出设备属性

To get a list of all of the attributes of a device you can use to write rules, run this command:

# udevadm info -a -n [device name]

Replace [device name] with the device present in the system, such as /dev/sda or /dev/ttyUSB0.

If you do not know the device name you can also list all attributes of a specific system path:

# udevadm info -a -p /sys/class/backlight/acpi_video0

加载前测试规则

# udevadm test $(udevadm info -q path -n [device name]) 2>&1

This will not perform all actions in your new rules but it will however process symlink rules on existing devices which might come in handy if you are unable to load them otherwise. You can also directly provide the path to the device you want to test the udev rule for:

# udevadm test /sys/class/backlight/acpi_video0/

加载新规则

Udev 自动侦测规则文件的变化,所以修改会立即生效,无需重启 udev。但已接入设备的规则不会自动触发。像 USB 这类热插拔设备也许需要重新插拔才能使新规则生效,也可能需要卸载并重载内核的 ohci-hcd 和 ehci-hcd 模块以重新挂载所有 USB 设备。

如果规则自动重载失败

# udevadm control --reload

可以手工强制触发规则

# udevadm trigger

Udisks

参阅 Udisks.

提示与技巧

访问固件编程器(烧录器)和 USB 虚拟串行设备

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: Making a device world-writable is not secure. (Discuss in Talk:Udev (简体中文)#)

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: One example is enough, others can surely be found with lsusb. (Discuss in Talk:Udev (简体中文)#)

The following ruleset will allow normal users (within the "users" group) the ability to access the USBtinyISP USB programmer for AVR microcontrollers and a generic (SiLabs CP2102) USB to UART adapter, the Atmel AVR Dragon programmer, and the Atmel AVR ISP mkII. Adjust the permissions accordingly. Verified as of 31-10-2012.

/etc/udev/rules.d/50-embedded_devices.rules
# USBtinyISP Programmer rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c9f", GROUP="users", MODE="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0479", GROUP="users", MODE="0666"

# USBasp Programmer rules http://www.fischl.de/usbasp/
SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05dc", GROUP="users", MODE="0666"

# Mdfly.com Generic (SiLabs CP2102) 3.3v/5v USB VComm adapter
SUBSYSTEMS=="usb", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", GROUP="users", MODE="0666"

#Atmel AVR Dragon (dragon_isp) rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2107", GROUP="users", MODE="0666"

#Atmel AVR JTAGICEMKII rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2103", GROUP="users", MODE="0666"

#Atmel Corp. AVR ISP mkII
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2104", GROUP="users", MODE="0666"

#Atmel Copr. JTAGICE3
SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2140", GROUP="users", MODE="0666"

USB 插入时执行规则

See the Execute on USB insert article or the devmon wrapper script.

VGA 线缆接入时执行规则

Create the rule /etc/udev/rules.d/95-monitor-hotplug.rules with the following content to launch arandr on plug in of a VGA monitor cable:

KERNEL=="card0", SUBSYSTEM=="drm", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/username/.Xauthority", RUN+="/usr/bin/arandr"

侦测新的 eSATA 设备

If your eSATA drive is not detected when you plug it in, there are a few things you can try. You can reboot with the eSATA plugged in. Or you could try

# echo 0 0 0 | tee /sys/class/scsi_host/host*/scan

Or you could install scsiaddAUR (from the AUR) and try

# scsiadd -s

Hopefully, your drive is now in /dev. If it is not, you could try the above commands while running

# udevadm monitor

to see if anything is actually happening.

将内置 SATA 接口标记为 eSATA

If you connected a eSATA bay or an other eSATA adapter the system will still recognize this disk as an internal SATA drive. GNOME and KDE will ask you for your root password all the time. The following rule will mark the specified SATA-Port as an external eSATA-Port. With that, a normal GNOME user can connect their eSATA drives to that port like a USB drive, without any root password and so on.

/etc/udev/rules.d/10-esata.rules
DEVPATH=="/devices/pci0000:00/0000:00:1f.2/host4/*", ENV{UDISKS_SYSTEM}="0"
Note: The DEVPATH can be found after connection the eSATA drive with the following commands (replace sdb accordingly):
# udevadm info -q path -n /dev/sdb
/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb
# find /sys/devices/ -name sdb
/sys/devices/pci0000:00/0000:00:1f.2/host4/target4:0:0/4:0:0:0/block/sdb

设置静态设备名

Because udev loads all modules asynchronously, they are initialized in a different order. This can result in devices randomly switching names. A udev rule can be added to use static device names.

See also Persistent block device naming for block devices and Network configuration#Device names for network devices.

视频设备

For setting up the webcam in the first place, refer to Webcam configuration.

Using multiple webcams, useful for example with motion (software motion detector which grabs images from video4linux devices and/or from webcams), will assign video devices as /dev/video0..n randomly on boot. The recommended solution is to create symlinks using an udev rule (as in the example in #Writing udev rules):

/etc/udev/rules.d/83-webcam.rules
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="4519", SYMLINK+="video-cam1"
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="08f6", SYMLINK+="video-cam2"
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="0840", SYMLINK+="video-cam3"
Note: Using names other than /dev/video* will break preloading of v4l1compat.so and perhaps v4l2convert.so

打印机

If you use multiple printers, /dev/lp[0-9] devices will be assigned randomly on boot, which will break e.g. CUPS configuration.

You can create following rule, which will create symlinks under /dev/lp/by-id and /dev/lp/by-path, similar to Persistent block device naming scheme:

/etc/udev/rules.d/60-persistent-printer.rules
ACTION=="remove", GOTO="persistent_printer_end"

# This should not be necessary
#KERNEL!="lp*", GOTO="persistent_printer_end"

SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
ENV{ID_TYPE}!="printer", GOTO="persistent_printer_end"

ENV{ID_SERIAL}=="?*", SYMLINK+="lp/by-id/$env{ID_BUS}-$env{ID_SERIAL}"

IMPORT{builtin}="path_id"
ENV{ID_PATH}=="?*", SYMLINK+="lp/by-path/$env{ID_PATH}"

LABEL="persistent_printer_end"

USB 闪存设备

USB flash devices usually contain partitions, and partition labels are one way to have a static naming for a device. Another way is to create a udev rule for it.

Get the serial number and USB ids from the USB flash drive (if you use multiple of the same make, you might have to check the serial is indeed unique):

lsusb -v | grep -A 5 Vendor

Create a udev rule for it by adding the following to a file in /etc/udev/rules.d/, such as 8-usbstick.rules:

KERNEL=="sd*", ATTRS{serial}=="$SERIAL", ATTRS{idVendor}=="$VENDOR", ATTRS{idProduct}=="$PRODUCT" SYMLINK+="$SYMLINK%n"

Replace $SERIAL, $VENDOR, $PRODUCT from above output accordingly and $SYMLINK with the desired name. %n will expand to the partition number. For example, if the device has two partitions, two symlinks will be created. You do not need to go with the 'serial' attribute. If you have a custom rule of your own, you can put it in as well (e.g. using the vendor name).

Rescan sysfs:

udevadm trigger

Now check the contents of /dev:

ls /dev

It should show the device with the desired name.

唤醒挂起的 USB 设备

First, find vendor and product ID of your device, for example

# lsusb | grep Logitech
Bus 007 Device 002: ID 046d:c52b Logitech, Inc. Unifying Receiver

Now change the power/wakeup attribute of the device and the USB controller it is connected to, which is in this case driver/usb7/power/wakeup. Use the following rule:

/etc/udev/rules.d/50-wake-on-device.rules
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", ATTR{power/wakeup}="enabled", ATTR{driver/usb7/power/wakeup}="enabled"
Note: Also make sure the USB controller is enabled in /proc/acpi/wakeup.

触发事件

Merge-arrows-2.pngThis article or section is a candidate for merging with #Testing rules before loading.Merge-arrows-2.png

Notes: similar trick (Discuss in Talk:Udev (简体中文)#)

It can be useful to trigger various udev events. For example, you might want to simulate a USB device disconnect on a remote machine. In such cases, use udevadm trigger:

# udevadm trigger -v -t subsystems -c remove -s usb -a "idVendor=abcd"

This command will trigger a USB remove event on all USB devices with vendor ID abcd.

排错

屏蔽模块

极个别情况下,udev 也会犯错或加载错误的模块。为了防止错误的发生,你可以使用模块禁用列表。只要模块加入该列表,无论是启动时,或者是运行时(如usb硬盘等)udev都不会加载这些模块。参见blacklisting.

udevd 引导时挂起

After migrating to LDAP or updating an LDAP-backed system udevd can hang at boot at the message "Starting UDev Daemon". This is usually caused by udevd trying to look up a name from LDAP but failing, because the network is not up yet. The solution is to ensure that all system group names are present locally.

Extract the group names referenced in udev rules and the group names actually present on the system:

# fgrep -r GROUP /etc/udev/rules.d/ /usr/lib/udev/rules.d | perl -nle '/GROUP\s*=\s*"(.*?)"/ && print $1;' | sort | uniq > udev_groups
# cut -f1 -d: /etc/gshadow /etc/group | sort | uniq > present_groups

To see the differences, do a side-by-side diff:

# diff -y present_groups udev_groups
...
network							      <
nobody							      <
ntp							      <
optical								optical
power							      |	pcscd
rfkill							      <
root								root
scanner								scanner
smmsp							      <
storage								storage
...

In this case, the pcscd group is for some reason not present in the system. Add the missing groups. Also, make sure that local resources are looked up before resorting to LDAP. /etc/nsswitch.conf should contain the following line:

group: files ldap

BusLogic

BusLogic 设备被损坏而且导致启动时死机。这是一个内核的Bug目前还没有修正。

一些移动设备不可移除

创建自定义 udev 规则,设置 UDISKS_SYSTEM_INTERNAL=0。参见 udisks 手册。


声音问题和一些不能自动加载的模块

一些用户发现 /etc/modprobe.d/sound.conf 中的遗留配置会引起这些问题,请清理配置并重试。

注意: udev>=171 开始 OSS 模拟模块(snd_seq_oss, snd_pcm_oss, snd_mixer_oss) 默认不会自动装载。


IDE CD/DVD 驱动器的支持

Starting with version 170, udev does not support CD-ROM/DVD-ROM drives that are loaded as traditional IDE drives with the ide_cd_mod module and show up as /dev/hd*. The drive remains usable for tools which access the hardware directly, like cdparanoia, but is invisible for higher userspace programs, like KDE.

A cause for the loading of the ide_cd_mod module prior to others, like sr_mod, could be e.g. that you have for some reason the module piix loaded with your initramfs. In that case you can just replace it with ata_piix in your /etc/mkinitcpio.conf.

光驱被标识为磁盘

If the group ID of your optical drive is set to disk and you want to have it set to optical, you have to create a custom udev rule:

/etc/udev/rules.d
# permissions for IDE CD devices
SUBSYSTEMS=="ide", KERNEL=="hd[a-z]", ATTR{removable}=="1", ATTRS{media}=="cdrom*", GROUP="optical"

# permissions for SCSI CD devices
SUBSYSTEMS=="scsi", KERNEL=="s[rg][0-9]*", ATTRS{type}=="5", GROUP="optical"

参阅