• udev简述


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

    udev是systemd的组成部分,默认已安装,有关信息可查阅systemd-udevd.service的手册页。

    udev和devfs比较

    1.devfs运行在内核空间(使用devfs_register等API在内核空间注册设备节点);而udev运行在用户空间。

    2.当用户访问/dev下的某个节点时,devfs会自动加载对应的驱动;而udev则并不负责自动加载驱动的工作(2.6版本内核,驱动是在设备被插入/移除时被加载/卸载的,而不是设备被访问时就加载驱动)。采用devfs,当一个并不存在的/dev节点被打开时,devfs能自动加载对应的驱动,而udev则不会。这是因为udev的设计者认为linux应该在设备被发现的时候加载驱动模块,而不是当被访问的时候。udev的设计者认为devfs所提供的打开/dev节点时自动加载驱动的功能对于一个配置正确的计算机是多余的。系统中所有的设备都应该产生热插拔事件并加载恰当的驱动,而udev能注意到这点并且为它创建对应的设备节点。

    udev完全在用户态工作,利用设备加入或移除时内核所发送的热插拔事件(hotplug event)来工作。在热插拔时,设备的详细信息都会由内核输出到位于/sys的sysfs文件系统。udev的设备命名策略、权限控制和事件处理都是在用户态完成的,它利用sysfs中的信息来进行创建设备文件节点等工作。

    由于udev根据系统中硬件设备的状态动态更新设备文件,进行设备文件的创建和删除等,因此,在使用udev后,/dev目录下就会只包含系统中真正存在的设备了。

    udev的组成

    udev的主页位于https://mirrors.edge.kernel.org/pub/linux/utils/kernel/hotplug/udev/udev.html

    udev以3个分割的子计划发展:namedev、libsysfs和udev。namedev为设备命名子系统,libsysfs提供访问sysfs文件系统从中获取信息的标准接口,udev提供/dev设备节点文件的动态创建和删除策略。udev程序承担与namedev和libsysfs库交互的任务,当/sbin/hotplug程序被内核调用时,udev将被运行。

    udev的工作过程如下:

    1)  当内核检测到在系统中出现了新设备后,内核会在sysfs文件系统中为该新设备生成新的记录并导出一些设备特定的信息及所发生的事件。

    2)  udev获取内核导出的信息,它调用namedev决定应该给设备指定的名称,如果是新插入设备,udev将调用libsysfs决定应该为该设备的设备文件指定的主次设备号,并用分析获得的设备名称和主次设备号创建/dev/中的设备文件;如果是设备移除,则将已经创建的/dev文件被删除。

    另一种解释:

    Udev完全工作在用户空间,当一个设备被插入或者移除时,内核会通过netlink套接字发送设备详细信息到用户空间,udev获取到设备信息,根据信息内容在/dev下创建并命名设备节点。

    既然udev创建节点的时机是设备被插入的时候,那么就出现一个问题:

    冷插拔的设备怎么办

    由于冷插拔的设备开机时就已经存在,在udev启动前已经被插入。针对这种情况,sysfs下的设备都存在uevent文件,向该文件写一个“add”,内核会重新发送netlink,之后udev就可以收到设备的详细信息了,从而创建/dev下对应的设备节点。

    udev确定设备名:

     

    udev的配置文件是/etc/udev/udev.conf,可能包含#开头的注释,然后有几行选项:

    udev_root="/dev/"
    
    #udev_log="err"
    
    udev_rules="/etc/udev/rules.d/"

    第一行配置udev的log级别,可以为err,info和debug。用于控制将哪些消息发送到系统日志。

    第二行配置udev规则存储目录,一般采用默认值。

    udev规则

    udev规则以管理员身份编写并保存在/etc/udev/rules.d/目录,其文件名必须以.rules结尾。各种软件包提供的规则文件位于/lib/udev/rules.d/。如果/lib和/etc这两个目录中有同名文件,则/etc中的文件优先。规则文件的文件名通常是两个数字开头,它表示系统应用该规则的顺序。

    udev规则文件以行为单位,以“#”开头的行代表注释行,其余的每一行代表一个规则。规则有一系列的键值对组成,键值对之间用逗号分隔。每个规则分成一个或多个匹配和赋值部分。匹配部分用匹配专用的关键字来表示,赋值部分用赋值专用的关键字来表示。匹配键确定规则是否被应用,而赋值键表示分配某值给该键

    1.  udev 规则的所有操作符

    “==”  比较键、值,若等于,则该条件满足;

    “!=”   比较键、值,若不等于,则该条件满足;

    “=”    对一个键赋值;

    “+=”  为一个表示多个条目的键赋值。

    “:=”  对一个键赋值,并拒绝之后所有对该键的改动。目的是防止后面的规则文件对该键赋值。

    2.  udev 规则的匹配键

    NAME:     匹配事件设备名。

    ACTION  事件 (uevent) 的行为,例如:add( 添加设备 )、remove( 删除设备 )。

    KERNEL  内核设备名称,例如:sda, cdrom。

    DEVPATH  设备的 devpath 路径。

    SUBSYSTEM 设备的子系统名称,例如:sda 的子系统为 block。

    BUS    设备在 devpath 里的总线名称,例如:usb。

    DRIVER  设备在 devpath 里的设备驱动名称,例如:ide-cdrom。

    ATTR{filename}设备的 devpath 路径下,设备的属性文件“filename”里的内容。例如:SYSFS{model}==“ST936701SS”表示:如果设备的型号为 ST936701SS,则该设备匹配该匹配键。在一条规则中,可以设定最多五条ATTRS的匹配键。属性文件在/sys目录下。

    ATTRS{filename}:设备的父(向上)的devpath路径下设备属性文件filename里的内容。在一条规则中,可以设定最多五条ATTRS的匹配键。若有多个ATTRS,则多个ATTRS应指向同一个父设备(父设备目录)。属性文件在/sys目录下。

    ENV{key} 环境变量,这里指除上述专有系统执行匹配键外uevent输出的键值对中的键,如idVendor设备厂商号,用ATTR(S)则为ATTR{idVendor}或ATTRS{idVendor}(在/sys目录下devpath下有文件idVendor),而应用ENV则应为ENV(ID_VENDOR_ID)(udevadm monitor -k -p -u显示设备插入时显示的uevent)。ENV在一条规则中,可以设定最多五条环境变量的匹配键。

    PROGRAM  调用外部命令。

    RESULT  外部命令 PROGRAM 的返回结果。

    3.  udev 的重要赋值键 

    NAME在 /dev下产生的设备文件名。只有第一次对某个设备的 NAME 的赋值行为生效。之后匹配的规则再对该设备的 NAME 赋值行为将被忽略。如果没有任何规则对设备的 NAME 赋值,udev 将使用内核设备名称来产生设备文件。一般系统下设备节点name不能被udev改变,只能增加symlinks。

    SYMLINK为/dev/下的设备文件产生符号链接。由于udev只能为某个设备产生一个设备文件,所以为了不覆盖系统默认的udev规则所产生的文件,推荐使用符号链接。

    OWNER, GROUP, MODE  为设备设定权限。

    ATTR{key}值应该写入事件设备的sysfs属性文件中。

    ENV{key}设置设备属性值,以“.”开头的属性不会存储到database,也不会导出到events或外部工具。

    RUN{type}:增加可执行程序到event设备,当所有规则匹配时。type可取program(默认)或builtin。程序名与参数用空格分隔,可用单引号指定包含空格的参数。

    udev仅仅可运行短时间的任务,长时间的任务会阻塞udev后续event,且event处理完后程序会被强制退出(kill)或超时(默认180s)强制退出。

    4.  udev 的值和可调用的替换操作符 

    Linux 用户可以随意地定制 udev 规则文件的值。例如:my_root_disk, my_printer。同时也可以引用下面的替换操作符:

    $kernel, %k:       设备的内核设备名称,例如:sda、cdrom。

    $number, %n       设备的内核号码,例如:sda3 的内核号码是 3。

    $devpath, %p       设备的 devpath路径。

    $id, %b         设备在 devpath里的 ID 号。

    $sysfs{file}, %s{file}  设备的 sysfs里 file 的内容。其实就是设备的属性值。$env{key}, %E{key}:    一个环境变量的值。

    $major, %M        设备的 major 号。

    $minor %m        设备的 minor 号。

    $result, %c       PROGRAM 返回的结果。

    $parent, %P        父设备的设备文件名。

    $root, %r        udev_root的值,默认是 /dev/。

    $tempnode, %N      临时设备名。

    $name:                         当前设备名。

    %%            符号 % 本身。

    $$            符号 $ 本身。

    SUBSYSTEM=="tty", ACTION=="add", ENV{ID_VENDOR_ID}=="067b", ENV{ID_MODEL_ID}=="2303", MODE="0664", GROUP="plugdev", SYMLINK+="zigbee", RUN+="/bin/systemctl restart usb_detect"
    SUBSYSTEM=="tty", ACTION=="remove", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", RUN+="/bin/systemctl stop usb_detect"
    
    SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="0664", GROUP="plugdev", RUN+="/bin/systemctl restart testusb"
    SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_interface", ENV{PRODUCT}=="403/6010/700", RUN+="/bin/systemctl stop testusb"

    udev命令udevadm

    udevadm是udev管理工具。udevadm expects a command and command specific options. It controls the runtime behavior of systemd-udevd, requests kernel events, manages the event queue, and provides simple debugging mechanisms. udevadm 后接一个命令和命令指定选项。它控制了udev运行的行为,处理内核事件,控制事件队列,并且提供简单的调试机制。

    --debug 打印错误信息

    --version 打印版本信息

    --help 帮助文档

    udevadm info [options] [devpath|file|unit…]

    查询udev数据库中的设备信息。也可以从sysfs文件系统中查询到设备的属性以辅助创建udev规则。位置参数应该指定一个设备名(/dev开头),或一个syspath(以/sys/开头),或systemd device单元(以.device结尾)。

    --query=type              从数据库中查询指定类型的设备。需要--path和--name来指定设备。合法的查询文件是:设备名,链接,路径,属性

    --path=devpath          设备的路径

    --name=file                 设备节点或者链接

    --attribute-walk           打印指定设备的所有sysfs记录的属性,以用来udev规则匹配特殊的设备。该选项打印链上的所有设备信息,最大可能到sys目录。

    --device-id-of-file=file 打印主/从设备号

    --export-db                 输出udev数据库中的内容

    常用:

    udevadm info -a -n /dev/sda ;列出设备属性

    udevadm info -a -p /sys/class/backlight/acpi_video0   ;列出某个系统路径的属性

    udevadm trigger [options] [devpath|file|unit…]

    接收内核发送来的设备事件。主要用于重放(replay)coldplug事件信息。

    (内核在启动时已经检测到了系统的硬件设备,并把硬件设备信息通过sysfs内核虚拟文件系统导出。udev扫描sysfs文件系统,根据硬件设备信息生成热插拔(hotplug)事件,udev再读取这些事件,生成对应的硬件设备文件。由于没有实际的硬件插拔动作,所以这一过程被称为coldplug。)

    --verbose             输出将要被触发的设备列表。

    --dry-run              不真的触发事件

    --type=type         触发一个特殊的设备。合法的类型:devices/subsystem/failed.默认是devices

    --action=action    被触发的事件,默认是change

    --subsystem-match=subsystem       触发匹配子系统的设备事件。这个选项可以被多次指定,并且支持shell模式匹配。

    --attr-match=attribute=value   触发匹配sysfs属性的设备事件。如果属性值和属性一起指定,属性的值可以使用shell模式匹配。如果没有指定值,会重新确认现有属性。这个选项可以被多次指定。

    --attr-nomatch=attribute=value   不要触发匹配属性的设备事件。如果可以使用模式匹配。也可以多次指定

    --property-match=property=value 匹配属性吻合的设备。可以多次指定支持模式匹配

    --tag-match=property               匹配标签吻合的设备。可以多次指定。

    --sysname-match=name           匹配sys设备名相同的设备。可以多次指定支持模式匹配。

    一般systemd-udev-trigger.service中应用udevadm trigger回放coldplug:

    ExecStart=/bin/udevadm trigger --type=subsystems --action=add ; /bin/udevadm trigger --type=devices --action=add

    udevadm settle [options]

    查看udev事件队列,如果所有事件全部处理完就退出。

    --timeout=seconds             等待事件队列空的最大时间。默认是180秒。如果是0则立即退出。

    --seq-start=seqnum           只等待到给定的顺序号。

    --seq-end=seqnum            只等待到给定顺序号之前。

    --exit-if-exists=file             如果文件存在就退出

    --quiet                  不输出任何信息

    udevadm monitor [options]

    监听内核事件和udev发送的events事件。打印事件发出的设备。可以通过比较内核或者udev事件的时间戳来分析事件时序。

    -k, --kernel         输出内核事件

    -u, --udev           输出udev规则执行时的udev事件

    -p, --property     输出事件的属性

    --subsystem-match=string        通过子系统或者设备类型过滤事件。只有匹配了子系统值的udev设备事件通过。

    --tag-match=string            通过属性过滤事件,只有匹配了标签的udev事件通过。

    一般常用udevadm monitor -k -p -u监控uevent事件

    udevadm control command

    修改运行的udev守护进程的内部状态。

    udevadm test [options] devpath

    模拟一个udev事件,打印出debug信息。

    常用:

    udevadm test $(udevadm info -q path -n /dev/sda) 2>&1  ;加载前测试设备规则

    udevadm test /sys/class/block/sda    ;也可指定设备路径,加载前测试设备规则

    udevadm test-builtin [options] [command] devpath

    对设备devpath运行内置command并打印debug信息。

    参考:

    1. udev archlinux百科
    2. LINUX下 Udev详解
    3. 内核驱动模块如何在/dev文件下自动创建设备
    4. Writing udev rules
    5. udevadm命令详解
    6. Udev: Introduction to Device Management In Modern Linux System
    7. udev规则以及编写  mount.sh 自动挂载U盘
  • 相关阅读:
    紫书 例题8-18 UVa 1442 (扫描法)
    紫书 例题8-17 UVa 1609 (构造法)(详细注释)
    紫书 例题8-16 UVa 1608 (递归)
    紫书 例题8-15 UVa 12174 (滑动窗口)
    紫书 例题8-14 UVa 1607 (二分)
    紫书 例题8-13 UVa 11093 (反证法)
    紫书 例题8-12 UVa 12627 (找规律 + 递归)
    Codeforces Round #441 (Div. 2, by Moscow Team Olympiad)
    CodeForces
    CodeForces 444C 线段树
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/10349041.html
Copyright © 2020-2023  润新知