Linux udev 的原理、功能、使用和维护

linux udev详解 Linux 2.6以后的内核引入了sysfs文件系统,sysfs被看成是与proc、devfs和devpty同类别的文件系统,该文件系统是一个虚拟的文件系统,它可以产生一个包括所有系统硬件的层级视图,与提供进程和状态信息的proc文件系统十分类似。sysfs把连接在系统上的设备和总线组织成为一个分级的文件,它们可以由用户空间存取,向用户空间导出内核数据结构以及它们的属性。 阅读详情

如果你使用Linux比较长时间了,那你就知道,在对待设备文件这块,Linux改变了几次策略。在Linux早期,设备文件仅仅是是一些带有适当 的属性集的普通文件,它由mknod命令创建,文件存放在/dev目录下。后来,采用了devfs, 一个基于内核的动态设备文件系统,他首次出现在2.3.46内核中。Mandrake,Gentoo等Linux分发版本采用了这种方式。devfs创建 的设备文件是动态的。但是devfs有一些严重的限制,从2.6.13版本后移走了。目前取代他的便是文本要提到的udev--一个用户空间程序。

目前很多的Linux分发版本采纳了udev的方式,因为它在Linux设备访问,特别是那些对设备有极端需求的站点(比如需要控制上千个硬盘)和热插拔设备(比如USB摄像头和MP3播放器)上解决了几个问题。下面我我们来看看如何管理udev设备。

实际上,对于那些为磁盘,终端设备等准备的标准配置文件而言,你不需要修改什么。但是,你需要了解udev配置来使用新的或者外来设备,如果不修改 配置, 这些设备可能无法访问,或者说Linux可能会采用不恰当的名字,属组或权限来创建这些设备文件。你可能也想知道如何修改RS-232串口,音频设备等文 件的属组或者权限。这点在实际的Linux实施中是会遇到的。

为什么使用udev

在此之前的设备文件管理方法(静态文件和devfs)有几个缺点:

*不确定的设备映射。特别是那些动态设备,比如USB设备,设备文件到实际设备的映射并不可靠和确定。举一个例子:如果你有两个USB打印机。一个 可能称 为/dev/usb/lp0,另外一个便是/dev/usb/lp1。但是到底哪个是哪个并不清楚,lp0,lp1和实际的设备没有一一对应的关系,因为 他可能因为发现设备的顺序,打印机本身关闭等原因而导致这种映射并不确定。理想的方式应该是:两个打印机应该采用基于他们的序列号或者其他标识信息的唯一 设备文件来映射。但是静态文件和devfs都无法做到这点。

*没有足够的主/辅设备号。我们知道,每一个设备文件是有两个8位的数字:一个是主设备号 ,另外一个是辅设备号来分配的。这两个8位的数字加上设备类型(块设备或者字符设备)来唯一标识一个设备。不幸的是,关联这些身边的的数字并不足够。

*/dev目录下文件太多。一个系统采用静态设备文件关联的方式,那么这个目录下的文件必然是足够多。而同时你又不知道在你的系统上到底有那些设备文件是激活的。

*命名不够灵活。尽管devfs解决了以前的一些问题,但是它自身又带来了一些问题。其中一个就是命名不够灵活;你别想非常简单的就能修改设备文件的名字。缺省的devfs命令机制本身也很奇怪,他需要修改大量的配置文件和程序。

*内核内存使用,devfs特有的另外一个问题是,作为内核驱动模块,devfs需要消耗大量的内存,特别当系统上有大量的设备时(比如上面我们提到的系统一个上有好几千磁盘时)

udev的目标是想解决上面提到的这些问题,他通采用用户空间(user-space)工具来管理/dev/目录树,他和文件系统分开。知道如何改变缺省配置能让你之大如何定制自己的系统,比如创建设备字符连接,改变设备文件属组,权限等。

udev配置文件

主要的udev配置文件是/etc/udev/udev.conf。这个文件通常很短,他可能只是包含几行#开头的注释,然后有几行选项:

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

上面的第二行非常重要,因为他表示udev规则存储的目录,这个目录存储的是以.rules结束的文件。每一个文件处理一系列规则来帮助udev分配名字给设备文件以保证能被内核识别。
你的/etc/udev/rules.d下面可能有好几个udev规则文件,这些文件一部分是udev包安装的,另外一部分则是可能是别的硬件或者软件包 生成的。比如在Fedora Core 5系统上,sane-backends包就会安装60-libsane.rules文件,另外initscripts包会安装60-net.rules文 件。这些规则文件的文件名通常是两个数字开头,它表示系统应用该规则的顺序。

规则文件里的规则有一系列的键/值对组成,键/值对之间用逗号(,)分割。每一个键或者是用户匹配键,或者是一个赋值键。匹配键确定规则是否被应 用,而赋 值键表示分配某值给该键。这些值将影响udev创建的设备文件。赋值键可以处理一个多值列表。匹配键和赋值键操作符解释见下表:

udev 键/值对操作符

操作符        匹配或赋值                             解释
----------------------------------------
==             匹配                        相等比较
!=              匹配                        不等比较
=                赋值                       分配一个特定的值给该键,他可以覆盖之前的赋值。
+=              赋值                       追加特定的值给已经存在的键
:=               赋值                       分配一个特定的值给该键,后面的规则不可能覆盖它。

这有点类似我们常见的编程语言,比如C语言。只是这里的键一次可以处理多个值。有一些键在udev规则文件里经常出现,这些键的值可以使用通配符(*,?,甚至范围,比如[0-9]),这些常用键列举如下:

常用udev键
键                 含义
ACTION                     一个时间活动的名字,比如add,当设备增加的时候
KERNEL                     在内核里看到的设备名字,比如sd*表示任意SCSI磁盘设备
DEVPATH              内核设备录进,比如/devices/*
SUBSYSTEM              子系统名字,比如sound,net
BUS                     总线的名字,比如IDE,USB
DRIVER                     设备驱动的名字,比如ide-cdrom
ID                       独立于内核名字的设备名字
SYSFS{ value}              sysfs属性值,他可以表示任意
ENV{ key}              环境变量,可以表示任意
PROGRAM              可执行的外部程序,如果程序返回0值,该键则认为为真(true)
RESULT                     上一个PROGRAM调用返回的标准输出。
NAME                     根据这个规则创建的设备文件的文件名。注意:仅仅第一行的NAME描述是有效的,后面的均忽略。 如果你想使用使用两个以上的名字来访问一个设备的话,可以考虑SYMLINK键。
SYMLINK              根据规则创建的字符连接名
OWNER                     设备文件的属组
GROUP                     设备文件所在的组。
MODE                     设备文件的权限,采用8进制
RUN                     为设备而执行的程序列表
LABEL                     在配置文件里为内部控制而采用的名字标签(下下面的GOTO服务)
GOTO                     跳到匹配的规则(通过LABEL来标识),有点类似程序语言中的GOTO
IMPORT{ type}           导入一个文件或者一个程序执行后而生成的规则集到当前文件
WAIT_FOR_SYSFS         等待一个特定的设备文件的创建。主要是用作时序和依赖问题。
PTIONS                     特定的选项: last_rule 对这类设备终端规则执行; ignore_device 忽略当前规则; ignore_remove 忽略接下来的并移走请求。all_partitions 为所有的磁盘分区创建设备文件。

我们给出一个列子来解释如何使用这些键。下面的例子来自Fedora Core 5系统的标准配置文件。

KERNEL=="*", OWNER="root" GROUP="root", MODE="0600" 
KERNEL=="tty", NAME="%k", GROUP="tty", MODE="0666", OPTIONS="last_rule"
KERNEL=="scd[0-9]*", SYMLINK+="cdrom cdrom-%k"
KERNEL=="hd[a-z]", BUS=="ide", SYSFS{removable}=="1",
               SYSFS{device/media}=="cdrom", SYMLINK+="cdrom cdrom-%k" 
ACTION=="add", SUBSYSTEM=="scsi_device", RUN+="/sbin/modprobe sg"

上面的例子给出了5个规则,每一个都是KERNEL或者ACTION键开头:

*第一个规则是缺省的,他匹配任意被内核识别到的设备,然后设定这些设备的属组是root,组是root,访问权限模式是0600(-rw-----)。这也是一个安全的缺省设置保证所有的设备在默认情况下只有root可以读写

*第二个规则也是比较典型的规则了。它匹配终端设备(tty),然后设置新的权限为0600,所在的组是tty。它也设置了一个特别的设备文件名:%K。在这里例子里,%k代表设备的内核名字。那也就意味着内核识别出这些设备是什么名字,就创建什么样的设备文件名。

*第三行开始的KERNEL=="scd[0-9]*",表示 SCSI CD-ROM 驱动. 它创建一对设备符号连接:cdrom和cdrom-%k。

*第四行,开始的 KERNEL=="hd[a-z]", 表示ATA CDROM驱动器。这个规则创建和上面的规则相同的符号连接。ATA CDROM驱动器需要sysfs值以来区别别的ATA设备,因为SCSI CDROM可以被内核唯一识别。.

*第五行以 ACTION=="add"开始,它告诉udev增加 /sbin/modprobe sg 到命令列表,当任意SCSI设备增加到系统后,这些命令将执行。其效果就是计算机应该会增加sg内核模块来侦测新的SCSI设备。

当然,上面仅仅是一小部分例子,如果你的系统采用了udev方式,那你应该可以看到更多的规则。如果你想修改设备的权限或者创建信的符号连接,那么你需要熟读这些规则,特别是要仔细注意你修改的那些与之相关的设备。

修改你的udev配置

在修改udev配置之前,我们一定要仔细,通常的考虑是:你最好不要修改系统预置的那些规则,特别不要指定影响非常广泛的配置,比如上面例子中的第一行。不正确的配置可能会导致严重的系统问题或者系统根本就无法这个正确的访问设备。

而我们正确的做法应该是在/etc/udev/rules.d/下创建一个信的规则文件。确定你给出的文件的后缀是rules文件名给出的数字序列 应该比 标准配置文件高。比如,你可以创建一个名为99-my-udev.rules的规则文件。在你的规则文件中,你可以指定任何你想修改的配置,比如,假设你 修改修改floppy设备的所在组,还准备创建一个信的符号连接/dev/floppy,那你可以这么写:

KERNEL=="fd[0-9]*", GROUP="users",   SYMLINK+="floppy"

有些发行版本,比如Fedora,采用了外部脚本来修改某些特定设备的属组,组关系和权限。因此上面的改动可能并不见得生效。如果你遇到了这个问题,你就需要跟踪和修改这个脚本来达到你的目的。或者你可以修改PROGRAM或RUN键的值来做到这点。

某些规则的修改可能需要更深的挖掘。比如,你可能想在一个设备上使用sysfs信息来唯一标识一个设备。这些信息最好通过udevinfo命令来获取。

$ udevinfo -a -p $(udevinfo -q path      -n /dev/hda)

上面的命令两次使用udevinfo:一次是返回sysfs设备路径(他通常和我们看到的Linux设备文件名所在路径--/dev/hda--不 同);第 二次才是查询这个设备路径,结果将是非常常的syfs信息汇总。你可以找到最够的信息来唯一标志你的设备,你可以采用适当的替换udev配置文件中的 SYSFS选项。下面的结果就是上面的命令输出

[root@localhost rules.d]# udevinfo -a -p $(udevinfo -q path        -n      /dev/hda1)
Udevinfo 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 '/block/hda/hda1':     
KERNEL=="hda1"     SUBSYSTEM=="block"     DRIVER==""        
ATTR{stat}=="        1133         2268            2            4"         ATTR{size}=="208782"
ATTR{start}=="63"         ATTR{dev}=="3:1"        looking at parent device '/block/hda':   

KERNELS=="hda"     SUBSYSTEMS=="block"     DRIVERS==""        
ATTRS{stat}=="28905 18814 1234781 302540 34087 133247 849708 981336 0 218340 1283968"
ATTRS{size}=="117210240"         ATTRS{removable}=="0"        
ATTRS{range}=="64"         ATTRS{dev}=="3:0"

looking at parent device '/devices/pci0000:00/0000:00:1f.1/ide0/0.0':     

KERNELS=="0.0"     SUBSYSTEMS=="ide"     DRIVERS=="ide-disk"        
ATTRS{modalias}=="ide:m-disk"         ATTRS{drivename}=="hda"       
ATTRS{media}=="disk"       
looking at parent device '/devices/pci0000:00/0000:00:1f.1/ide0':     

KERNELS=="ide0"     SUBSYSTEMS==""     DRIVERS==""       
looking at parent device '/devices/pci0000:00/0000:00:1f.1':     
KERNELS=="0000:00:1f.1"     SUBSYSTEMS=="pci"     DRIVERS=="PIIX_IDE"        
ATTRS{broken_parity_status}=="0"         ATTRS{enable}=="1"        
ATTRS{modalias}=="pci:v00008086d000024CAsv0000144Dsd0000C009bc01sc01i8a"
ATTRS{local_cpus}=="1"         ATTRS{irq}=="11"         ATTRS{class}=="0x01018a"
ATTRS{subsystem_device}=="0xc009"         ATTRS{subsystem_vendor}=="0x144d"
ATTRS{device}=="0x24ca"         ATTRS{vendor}=="0x8086"       
looking at parent device '/devices/pci0000:00':     

KERNELS=="pci0000:00"     SUBSYSTEMS==""     DRIVERS==""






















举一个例子:假设你想修改USB扫描仪的配置。通过一系列的尝试,你已经为这个扫描仪标识了Linux设备文件(每次打开扫描仪时,名字都会变)。你可以 使 用上面的命令替换这个正确的Linux设备文件名,然后定位输出的采用SYSFS{idVendor}行和SYSFS{idProduct}行。最后你可 以使用这些信息来为这个扫描仪创建新的选项。

SYSFS{idVendor}=="0686",   SYSFS{idProduct}=="400e",  
SYMLINK+="scanner", MODE="0664",   group="scanner"

上面的例子表示将扫描仪的组设置为scanner,访问权限设置为0664,同时创建一个/dev/scanner的符号连接。

udev-FAQ

问:udev是什么? 它的目的何在?

答:udev是一种工具,它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。

问:udev支持什么内核?

答:udev只支持linux-2.6内核,因为udev严重依赖于sysfs文件系统提供的信息,而sysfs文件系统只在linux-2.6内核中才有。

问:udev是一个内核程序还是用户程序?

答:udev是一个用户程序(user-mode daemon)。

问:udev和devfs有什么差别?

答:udev能够实现所有devfs实现的功能。但udev运行在用户模式中,而devfs运行在内核模式中。据称:devfs具有一些不太容易解决的先天缺陷。

问:udev的配置文件放在哪里?

答:udev是一个用户模式程序。它的配置文件是/etc/udev/udev.conf。这个文件一般缺省有这样几项:

udev_root="/dev" ; udev产生的设备文件的根目录是/dev
udev_db="/dev/.udevdb" ; 通过udev产生的设备文件形成的数据库
udev_rules="/etc/udev/rules.d" ;用于指导udev工作的规则所在目录。
udev_log="err" ;当出现错误时,用syslog记录错误信息。

问:udev的工作过程是怎样的?

答:由于没有研究过udev的源程序,不敢贸然就说udev的工作过程。我只是通过一些网上的资料和udev的说明文档,大致猜测它的工作过程可能是这样的。

当内核检测到在系统中出现了新设备后,内核会在sysfs文件系统中为该新设备生成一项新的记录,一般sysfs文件系统会被mount到/sys目录中。新记录是以一个或多个文件或目录的方式来表示。每个文件都包含有特定的信息。(信息是如何表述的,还要另外研究?)

udev在系统中是以守护进程的方式udevd在运行,它通过某种途径(到底什么途径,目前还没搞懂。)检测到新设备的出现,通过查找设备对应的sysfs中的记录得到设备的一些信息。

udev会根据/etc/udev/udev.conf文件中的udev_rules指定的目录,逐个检查该目录下的文件,这个目录下的文件都是针 对某类或某个设备应该施行什么措施的规则文件。udev读取文件是按照文件名的ASCII字母顺序来读取的,如果udev一旦找到了与新加入的设备匹配的 规则,udev就会根据规则定义的措施对新设备进行配置。同时不再读后续的规则文件。

问:udev的规则文件的语法是怎样的?

答:udev的规则文件以行为单位,以"#"开头的行代表注释行。其余的每一行代表一个规则。每个规则分成一个或多个"匹配"和"赋值"部分。"匹 配"部分用"匹配"专用的关键字来表示,相应的"赋值"部分用"赋值"专用的关键字来表示。"匹配"关键字包 括:ACTION,KERNEL,BUS,SYSFS等等,"赋值"关键字包括:NAME,SYMLINK,OWNER等等。具体详细的描述可以阅读 udev的man文档。

下面举个例子来说明一下,有这样一条规则:SUBSYSTEM=="net", ACTION=="add", SYSFS{address}=="00:0d:87:f6:59:f3″, IMPORT="/sbin/rename_netiface %k eth0″
这个规则中的"匹配"部分有三项,分别是SUBSYSTEM,ACTION和SYSFS。而"赋值"部分有一项,是IMPORT。这个规则就是说,当系统 中出现的新硬件属于net子系统范畴,系统对该硬件采取的动作是加入这个硬件,且这个硬件在SYSFS文件系统中的"address"信息等于 "00:0d..."时,对这个硬件在udev层次施行的动作是调用外部程序/sbin/rename_netiface,传递的参数有两个,一个是 "%k",代表内核对该新设备定义的名称。另一个是"eth0"。    从上面这个例子中可以看出,udev的规则的写法比较灵活的,尤其在"匹配"部分中,可以通过诸如"*", "?",[a-c],[1-9]等shell通配符来灵活匹配多个匹配项。具体的语法可以参考udev的man文档。

问:udev怎样做到不管设备连接的顺序而维持一个统一的设备名?

答:实际上,udev是通过对内核产生的设备名增加别名的方式来达到上述目的的。前面说过,udev是用户模式程序,不会更改内核的行为。因此,内 核依然会我行我素地产生设备名如sda,sdb等。但是,udev可以根据设备的其他信息如总线(bus),生产商(vendor)等不同来区分不同的设 备,并产生设备文件。udev只要为这个设备文件取一个固定的文件名就可以解决这个问题。在后续对设备的操作中,只要引用新的设备名就可以了。但为了保证 最大限度的兼容,一般来说,新设备名总是作为一个对内核自动产生的设备名的符号链接(link)来使用的。

例如:内核产生了sda设备名,而根据信息,这个设备对应于是我的内置硬盘,那我就可以制定udev规则,让udev除了产生/dev/sda设备 文件外,另外创建一个符号链接叫/dev/internalHD。这样,我在fstab文件中,就可以用/dev/internalHD来代替原来的 /dev/sda了。下次,由于某些原因,这个硬盘在内核中变成了sdb设备名了,那也不用着急,udev还会自动产生/dev/internalHD这 个链接,并指向正确的/dev/sdb设备。所有其他的文件像fstab等都不用修改。

问:怎样才能找到这些设备信息,并把他们放到udev的规则文件中来匹配呢?

答:这个问题比较难,网上资料不多,我只找到一篇文章来介绍如何写udev的规则。他的基本方法是通过udevinfo这个实用程序来找到那些可以作为规则文件里的匹配项的项目。有这样两种情况可以使用这个工具:

第一种情况是,当你把设备插入系统后,系统为设备产生了设备名(如/dev/sda)。那样的
话,你先用udevinfo -q path -n/dev/sda,命令会产生一个该设备名对应的在sysfs下的路径,如/block/sda。然后,你再用udevinfo -a -p/sys/block/sda,这个命令会显示一堆信息,信息分成很多块。这些信息实际来自于操作系统维护的sysfs链表,不同的块对应不同的路 径。你就可以用这些信息来作为udev规则文件中的匹配项。但需要注意的是,同一个规则只能使用同一块中显示的信息,不能跨块书写规则。

第二种情况是,不知道系统产生的设备名,那就只有到/sys目录下去逐个目录查找了,反复用udevinfo -a -p/sys/path...这个命令看信息,如果对应的信息是这个设备的,那就恭喜你。否则就再换个目录。当然,在这种情况下,成功的可能性比较小。

问: udev和devfs是什么关系
答: udev完全在用户态(userspace)工作,利用设备加入或移除时内核所发送的hotplug事件(event)来工作。关于设备的详细信息是由内 核输出(export)到位于/sys的sysfs文件系统的。所有的设备命名策略、权限控制和事件处理都是在用户态下完成的。与此相反,devfs是作 为内核的一部分工作的。

问: 如果udev不能完成所有devfs的工作的话,为什么把devfs标记为OBSOLETE/removed?

答: 引用 Al Viro (Linux VFS 内核维护者):

-devfs所做的工作被确信可以在用户态来完成。
-devfs被加入内核之时,大家寄望它的质量可以迎头赶上。
-devfs被发现了一些可修复和无法修复的 bug。
-对于可修复的 bug,几个月前就已经被修复了,其维护者认为一切良好。
-对于后者,同样是相当常一段时间以来没有改观了。
-devfs的维护者和作者对它感到失望并且已经停止了对代码的维护工作。

问: 但是当一个并不存在的/dev节点被打开的时候,udev并不能如devfs一样自动加载驱动程序。
答: 的确如此,但Linux的设计是在设备被发现的时候加载模块,而不是当它被访问的时候。

问: 不过等等,我确实希望 udev 可以在不存在的节点被打开的时候自动加载驱动。这是我使用devfs的唯一原因了。给udev 增加这个功能吧。
答: 不,udev 是用来管理/dev 的,不是用来加载内核驱动的。

问: 嗨,求你们了。这不难做到的。
答: 这么个功能对于一个配置正确的计算机是多余的。系统中所有的设备都应该产生hotplug 事件、加载恰当的驱动,而 udev 将会注意到这点并且为它创建对应的设备节点。如果你不想让所有的设备驱动停留在内存之中,应该使用其它东西来管理你的模块(如脚本, modules.conf, 等等) 这不是udev 的工作。

问: 但是我真的喜欢那个功能,还是加上吧
答: devfs用的方法导致了大量无用的modprobe尝试,以此程序探测设备是否存在。每个试探性探测都新建一个运行 modprobe 的进程,而几乎所有这些都是无用的。

问: 我喜欢devfs的设备文件命名方式,udev 可以这样命名么?
答: 可以,udev 可以使用 /dev 的命名策略来创建节点。通过一个配置文件,可以把内核缺省的名字映射到 devfs 的名字。可以看看udev 中带的 udev.rules.devfs 文件。注意: devfs 的命名方式是不被建议并且不被官方支持的,因为它所用的简单枚举设备的方式在设备可能被随时加入或删除的情况下确实是一个比较笨的方法。这些编号代给你的 将只有麻烦,而并不能用来确定设备。看看那个永久性磁盘 (persistentdisk) 的规则就知道如何在用户态下正确的做这件事,而不是傻傻地列出设备。

问: udev 可以为哪些设备创建节点?
答: 所有在 sysfs 中显示的设备都可以由 udev 来创建节点。如果内核中增加了其它设备的支持,udev 也就自动地可以为它们工作了。现在所有的块设备都在被支持之列,大部分的主字符设备也是被支持的。内核开发者们正致力于让所有的字符设备都被支持。可以到 linux-kernel邮件列表上寻找补丁或是查看补丁的状态。

问: udev 是否会去掉匿名设备数量的限制?
答: udev 完全工作于用户态。如果内核支持了更多的匿名设备,udev就会支持。

问: udev 是否会支持符号链接?
答: udev 现在就支持符号链接,每个设备节点拥有多个符号链接也是被支持的。

问: udev如何处理/dev文件系统?
答: 建议使用一个每次启动系统的时候重新创建的 tmpfs 作为 /dev 的文件系统。不过实际上udev并不关心那种文件系统在被使用。

问: 在 init 运行之前,udev 如何处理设备?
答: udev 可以被放入 initramfs 之中,并在每个设备被发现的时候运行。也可以让udev 工作在一个真的根分区被加载之后根据 /sys 的内容创建的初始/dev目录之中。

问: 我是否可以利用 udev 在一个 USB 设备被加载的时候自动加载上这个设备?
答: 技术上讲是可以的,但是 udev 不是用于这个工作的。所有的主流发布版 (distro)都包含了 HAL (http://freedesktop.org/wiki/Software_2fhal) 用于这个工作,它也是专门用于监视设备变更的,并且集成进入了桌面软件。

换个角度说,这可以简单的通过 fstab 来实现:/dev/disk/by-label/PENDRIVE /media/PENDRIVE vfat user,noauto 0 0
这样,用户可以用如下命令来访问设备:
$mount /media/PENDRIVE
同样不需要管理员权限,但却拥有了设备的全部访问权限。使用永久性磁盘链接(label, uuid) 将可以指定同一设备,无论其实际上的内核名字是什么。

问: 有什么我需要注意的安全问题么?
答: 当使用动态设备编号的时候,一个给定的主/从设备号可能在不同时间对应不同的设备,如果一个用户拥有对这个节点的访问权限,并且可以创建一个到这个节点的 硬链接,他就可以如此得到一个这个设备节点的拷贝。当设备被移除之后,udev 删除了设备节点,但硬链接依然存在。如果这个设备节点之后被重新使用不同的访问权限被创建的时候,其硬链接仍然可以使用先前的访问权限来访问。(同样的问 题也存在在使用 PAM 改变访问权限的 login 上。)

简单的解决方案就是通过把 /dev 放在 tmpfs 这样的单独的文件系统之上来防止建立硬链接。

问: 我有其他的关于 udev 的问题,我应该问谁?
答: linux-hotplug-devel 正是问这些的地方。邮件列表的地址是linux-hotplug-devel@lists.sourceforge.net 。

Linux udev规则实战:实现磁盘设备永久绑定与稳定识别 在Linux系统管理与存储架构中,设备识别的稳定性是保障服务可靠性的基石。传统上,系统内核动态分配的磁盘设备名(如/dev/sda)可能因硬件初始化顺序而变动,这给依赖固定设备路径的应用(如数据库、LVM、软件RAID)带来风险。其核心原理在于利用udev——Linux内核的动态设备管理器,通过事件驱动机制,在设备添加时根据其固有属性(如全球唯一标识WWN或序列号)执行预定义规则。这项技术的核心价值在于,它能创建基于设备唯一标识的永久符号链接,从而将物理磁盘“锚定”在系统中,为上层应用提供稳定的存储访问点。 阅读详情

相关推荐

Linux 6.x udev 磁盘绑定实战:解决设备名漂移,实现持久化存储

在Linux系统管理与服务器运维中,设备管理的稳定性是基础。Linux内核通过udev动态管理/dev目录下的设备节点,其核心原理是监听内核发出的uevent事件,并依据预定义的规则文件,基于设备的固有属性(如序列号、WWID)执行创建设备节点、设置权限或创建符号链接等动作。这项技术的核心价值在于解决了物理磁盘设备名(如/dev/sda)因硬件初始化顺序变化而发生的“漂移”问题,为数据库、虚拟化、容器存储等依赖固定设备路径的应用场景提供了稳定基石。通过编写udev规则,系统管理员可以基于磁盘的WWID或序列

anheku1562的博客 513

SK海力士在美建首个HBM封装基地:AI算力背后的显存与先进封装

在 AI 算力需求持续攀升的背景下,高带宽内存(HBM)已成为 GPU 与大模型训练/推理的关键资源。与普通 DDR 不同,HBM 通过 TSV 硅通孔将多颗 DRAM 垂直堆叠,并以超千位宽接口换取极高显存带宽,从而解决大模型频繁读取参数时的访存瓶颈。HBM 的竞争正从存储制造转向先进封装与良率爬坡,SK海力士在美国建设首个 HBM 封装基地,正是为了提升 HBM3E/HBM4 的稳定交付能力,并贴近 AI 芯片客户。对开发者与基础设施团队而言,理解 HBM 代际、封装路线和供应链节奏,是 GPU 选型、

429

udev-114版本:arm-linux系统中的设备管理优化

本文还有配套的精品资源,点击获取 简介:udev是Linux系统中负责设备管理的关键组件,它在设备节点创建、命名及自动化操作上扮演重要角色。udev-114版本特别关注在arm-linux系统中增强对U盘自动挂载和USB设备的支持。udev通过规则文件和设备事件机制,简化了U盘等设备的自动挂载流程,并能对不同类型的USB设备执行定制化操作。新版本可能针对arm-linux平...

weixin_32836713的博客 1291

【Linux应用】Linux系统的设备管理——Udev

udev是 Linux2.6内核里的一个功能,它替代了原来的 devfs,成为当前 Linux 默认的设备管理工具,能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。udev以守护进程的形式运行,通过帧听内核发出来的uevent来管理/dev目录下的设备文件。不像之前的设备管理工具,udev在用户空间运行,而不在内核空间运行。

平凡的世界 4692

FPGA与GPU异构计算:重塑嵌入式AI的算力边界与场景定义

本文深入探讨了FPGA与GPU异构计算如何突破嵌入式AI的算力瓶颈。通过分析工业视觉、智能交通及航天等场景,阐述了FPGA负责高速数据采集与预处理,GPU专注复杂AI推理的协同模式,有效解决了传统单一架构在算力、功耗、接口和实时性上的挑战,为嵌入式AI应用提供了高效能解决方案。

spice的博客 486

生物信息学实战:如何用STRING数据库和R语言搞定蛋白互作网络分析(附完整代码)

本文提供了一份完整的生物信息学实战指南,详细介绍了如何利用STRING数据库和R语言进行蛋白互作网络分析。从差异表达基因列表出发,涵盖数据准备、数据库连接、网络构建到高级可视化与模块识别的全流程,并附有可复现的完整R代码,帮助研究人员深入解析转录组数据背后的蛋白互作关系。

milk5的博客 945

Linux-udev

udev 是一个用户空间的设备管理器,用于为事件设置处理程序。作为守护进程, udev 接收的事件主要由 linux 内核生成,这些事件是外部设备产生的物理事件。总之, udev 探测外设和热插拔,将设备控制权传递给内核,例如加载内核模块或设备固件。udev 是一个用户空间系统,可以让操作系统管理员为事件注册用户空间处理器。为了实现外设侦测和热插拔,udev 守护进程接收 Linux 内核发出的外设相关事件;加载内核模块、设备固件;调整设备权限,让普通用户和用户组能够访问设备。

qq_34968572的博客 2516

解决创建conda环境时Solving environment: failed 和 ResolvePackageNotFound 的错误

环境配置文件是在别的机器上导出的,文件里的软件包是按照导出文件的机器配置的,因此导出的时候,把这些包的详细信息也导了出来,即第二个等号后面跟着的信息,当我们按照这个文件创建环境时,conda就会根据我们机器的配置信息,按照配置文件里包的详细信息,去找这个包,那当然找不到,结果发现“查无此包”,因此也就会报上面的错误。上面找到了问题的所在之处,解决起来就很简单了,只需要在配置文件 environment.yml 中将包的详细信息删除,也就是第二个等号后面的内容。然而升级超级慢不说,也没有解决我的问题。...

番茄炒蛋三分糖 4万+

LINUX的UDEV(守护进程)

UDEV udev linux 守护进程

m0_62299670的博客 925

实战:如何用MIPI CSI-2高效传输RAW10图像数据(附带宽优化技巧)

本文深入探讨了MIPI CSI-2协议在RAW10图像数据传输中的高效应用,详细解析了4像素5字节打包机制及其带宽优化技巧。通过动态Lane分配、位深度自适应压缩和虚拟通道交错传输等实战方法,显著提升传输效率,适用于IoT摄像头开发等低功耗场景。

css33的专栏 731

基于STM32L4XX、HAL库的Ra-01SC-P LoRa模块驱动程序设计

0x22) { // SX1276/SX1278版本号。// 发射功率(2-20)// 工作频率(Hz)// 编码率(5-8)

zhusl6688的博客 424

亚马逊设备影子_如何查看哪些设备正在使用您的Amazon Video帐户

亚马逊设备影子pixinoo/Shutterstockpixinoo /快门 Amazon Prime Video offers a wide variety of movies, TV shows, and custom content from Amazon. Whether you’ve signed in to your account on old devices or you’re l...

culul01313的博客 1303

YOLOv10有效涨点专栏目录 | 包含卷积、主干、检测头、注意力机制、Neck、二次创新、独家创新等上百种创新机制

Hello,各位读者们好本专栏自开设以来已经更新改进教程100余篇其中包含二次创新、独家创新多种改进方法,包含C2f、主干、检测头、注意力机制、Neck多种结构,也有损失函数和一些细节点上的创新。同时本人一些讲解视频和包含我所有创新的YOLOv10文档并不能在优快云上传,通过建立交流群的形式在内上传我完整的文件和视频我也会在群内不定期和大家交流回答大家问题。专栏介绍。

Snu77的博客 1万+

ARM的守护进程和udev守护进程

概念:在Linux操作系统中,守护进程是一种后台运行的程序,它独立于任何用户会话,通常用于执行系统任务或提供持续的服务。特点后台运行:守护进程在后台运行,不与任何终端或控制台交互。持续运行:它们通常在系统启动时开始运行,并持续运行直到系统关闭。无用户交互:守护进程设计用于无需用户输入即可独立运行。系统权限:很多守护进程以root权限运行,因为它们需要访问系统资源或执行管理任务。服务提供:它们提供网络服务、文件系统管理、打印服务、系统日志记录等核心功能。概念udev。

weixin_65262119的博客 1014

SPICE仿真软件:HSPICE_(22).HSPICE仿真案例分析

通过上述案例分析,我们可以看到HSPICE仿真软件在不同电路类型和仿真场景中的应用。无论是简单的直流分析、交流分析还是复杂的暂态分析,HSPICE都能提供详细的仿真结果,帮助我们更好地理解和优化电路设计。希望这些案例能够为读者提供实用的参考和指导,进一步提升使用HSPICE进行电路仿真的能力。输入文件的编写:确保输入文件格式正确,使用注释来解释每一部分的内容。分析类型的选择:根据电路的特点选择合适的分析类型,如.DC.AC和.TRAN。输出结果的设置:使用.print命令来指定需要输出的节点电压和支路电流。

kkchenjj的博客 1306

PTC Creo软件二次开发:使用C++进行Creo二次开发实战

C++是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。由Bjarne Stroustrup在贝尔实验室开发,最初作为C语言的增强版出现,后来发展成为一种独立的语言。C++不仅保留了C语言的高效性和灵活性,还引入了类、模板、命名空间等高级特性,使其成为开发复杂系统和软件的理想选择。

kkchenjj的博客 4040

什么是udev

阅读总结:swain@126.com     20060410linux传统上使用静态设备创建方法,因此大量设备节点在 /dev 下创建(有时上千个),而不管相应的硬件设备是否真正存在。通常这由一个MAKEDEV脚本,组成它由许多calls of mknod program with the revelant major and minor device number for每一个世界上可能存

Steganography的编程之路 6249

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

udev和mdev hotplug事件

udev和mdev hotplug事件 关于udev和mdev之间的区别与联系我发现自己现在还没有把它完整的给区分开来和联系起来. 设备文件系统有devfs,mdev,udev mdev是udev的简化版本,是busybox中所带的程序,最适合用在嵌入式系统,而udev一般用在PC上的linux中,相对mdev来说要复杂些,devfs是2.4内核引入的,而在2.6内核中却被...

阿Sir问道 512

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Linux中的devfs 与 udev

Linux中的devfs 与 udev udev-FAQ 中文翻译 中文翻译 王旭 http://gnawux.blogchina.com                                     原文出处 http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-FAQ本文档遵循 GPL 2 及以后版

1421

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Linux系统下基于udev规则实现CAN接口开机自启动配置

本文详细介绍了在Linux系统中通过udev规则实现CAN接口开机自启动配置的方法。通过创建udev规则文件,自动设置CAN接口的队列长度、波特率等参数,解决了嵌入式开发和工业控制项目中手动配置的繁琐与不可靠问题,显著提升系统可靠性和维护效率。

hadoop5ranger的博客 702

RH436之Udev设备管理之概念

Udev管理设备 udev是一种工具,它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。 使用udev后,在/dev/目录下就只包含系统中真正存在的设备 与设备主/从编号无关 提供持续的设备命名 Udev是硬件平台无关的,属于user space 的进程,它脱离驱动层的关联而建立在操

幸福人生 2103

devfs 与 udev

这几天一直在看linux文件系统的文档,这里转载一篇,便于以后自己复习用。知识学得快的时候难免理解上有失误,同时遗忘得也是相当快,或者将来某个时候有些感悟时找不到相关的文章也是一种痛苦。我转载的这篇文章的作者在文章中也转载了别人的文章。 本文档遵循 GPL 2 及以后版本发布,修

ft1512975的专栏 906

udev详解

udev详解 2007-09-04  08:56 原文出处 http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-FAQ 中文翻译 王旭 http://gnawux.blogchina.com 本文档遵循 GPL 2 及以后版本发布,修改、发布请保持许可证不变 问: udev是什么? 它的目的何在? 答: 看看那篇 OLS

梁桥江的专栏 1076

Intel® RealSense™ SDK:Linux udev规则配置指南

当你第一次将Intel® RealSense™深度相机连接到Linux系统时,是否遇到过"权限被拒绝"的错误?或者相机能够被识别但无法获取深度流?这些问题大多源于**设备访问权限**配置不当。udev(用户空间设备管理器)作为Linux内核与用户空间的桥梁,通过规则文件定义硬件设备的访问策略,直接影响RealSense相机能否正常工作。 本文将系统讲解RealSense SDK的udev规则配置...

gitblog_00376的博客 655
上一篇: Linux修改eth2到eth0
下一篇: fstab
zhyjunFov
博客等级 码龄18年 17粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值