Udev详解
(2013-02-16 10:40:42)
标签:
udevit |
分类: linux设备驱动 |
- udev
linux用户空间设备管理(Linux userspace device management),在kernel
2.6.13后被使用,动态提供了在系统中实际存在的设备节点。
udev与不同的发布版本有很强的依赖性。一个系统如果没有安装正确的udev版本,有可能造成无法启动或者工作不正常。udev的开发团队也不推荐使用新版本替代系统当前版本的udev.
随着udev发布的工具和规则文件可以改变为己用,不是公共的API。不要直接从外部程序调用/lib/udev目录下的私有工具,因为在下一个发布版本中有可能不存在这个私有工具。获取udev相关信息只通过udevadm和libudev。在/lib/udev和/dev/.udev目录下的所有Tools和rules都是私有的,可能在不同版本中不同。
udev要求:
需要配置kernel的以下选项:
udev在系统启动时,将devtmpfs挂载到/dev目录下,udev管理kernel创建的设备节点的权限和所有权,udev会创建附加的软链接。udev也可以使用tmpfs文件系统,像/dev/null,
/dev/console, /dev/kmsg这样的静态结点,需要在udev开始时创建。
基于kernel的发送设备文件创建/移除的事件,udev在/dev目录下创建/移除结点。
所有的kernel事件与一组指定的规则相匹配,这些规则与事件处理函数和kernel模块有关。所有的设备结点都需要主设备号、从设备号。udev还可以创建所有权限,以及软连接来指向结点,和事件处理函数。
- 为什么使用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的配置文件
一般放在/etc/udev/和/lib/udev/。udev的主配置文件是/etc/udev/udev.conf,里面主要设置
udev_root和udev_log。udev_root指定放置设备结点的位置,默认是/dev。udev_log保存记录优先级,有效的值为err,
info和debug或者syslog优先级支持的数字。
udev的规则文件
一般存放在/lib/udev/rules.d/和/etc/udev/rules.d/,前者存放默认的规则,后者存放自定义的规则。还有一个存放临时规则的目录/run/udev/rules.d/。这些规则汇总后按字母排序。但是/etc/udev/rules.d/下面的同名规则优先于/lib/udev/rules.d/默认的规则。
规则文件必须以.rules会后缀,否则被忽略。
规则文件支持:==,!=,=,+=,:=,*,?,[]。分别表示相等,不等,赋值,添加入列,终极赋值(后面的无效),[]配置之中某一个,[0-9]表示0到9中的一个。
关键字:ACTION,DEVPATH,KERNEL,NAME,SYMLINK,SYBSYSTEM,DRIVER,ATTR{filename},KERNELS,SYBSYSTEMS,DRIVERS,ATTRS{filename},TAGS,ENV{key},TAG,TEST{octal
mod mask},PROGRAM,RESULT。
ACTION:事件活动名称;常用ACTION=="add"或者ACTION=="remove"表示添加或移除。
DEVPATH:事件设备路径;比如/dev
KERNEL:事件设备名称;如:sd[a-z][0-9]
NAME:结点或者网络接口名;设置一次,可全局使用。
SYBSYSTEM:事件设备子系统;比如:usb,sound,net
DRIVER:事件设备驱动名,比如:usb
ATTR{filename}:匹配事件设备的sysfs属性值。
PROGRAM:执行匹配的程序,返回0,为真。
ENV{key}:环境变量
RESULT:返回最后PROGRAM调用的字串。
RUN:为指定的设备添加PROGRAM列表。
LABEL:常和GOTO使用。
BUS:总线的名字,比如IDE,USB
OPTIONS:特殊选项;last_rule为这类设备规则执行;ignore_device
忽略当前规则; ignore_remove 忽略接下来的并移走请求,all_partitions
为所有的磁盘分区创建设备文件。
更多参数请man
udev.
libudev参考手册:
libudev主要由以下六部分组成:
{
}
udev结构体:主要保存从配置文件读取的默认值。
struct udev {
};
udev_list_entry结构体:设备链表入口
struct udev_list_entry {
};
udev_device结构体:udev设备链表
struct udev_device {
};
udev_monitor结构体:udev设备事件源
struct udev_monitor {
};
udev_enumerate结构体:查找和排序sys设备
struct udev_enumerate {
};
udev_queue结构体:存取当前活动事件
struct udev_queue {
};
udev代码的一般编译选项:
./configure \
更多资料可以参阅: