udev原理及使用方法

本文参考以下两篇文章结合自己的理解总结。
https://blog.csdn.net/huangminilong/article/details/83782142
https://blog.csdn.net/chituhuan/article/details/52383610

一、udev概念:
1、udev是linux kernel的设备管理器,在最新的内核版本中kernel_3.10中udev已经代替了devfs、hotplug等功能。它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。
2、为什么udev要取代devfs?
udev是硬件平台无关的,属于user space的进程,它脱离驱动层的关联而建立在操作系统之上,基于这种设计实现,我们可以随时修改及删除/dev下的设备文件名称和指向,随心所欲地按照我们的愿望安排和管理设备文件系统,而完成如此灵活的功能只需要简单地修改udev的配置文件即可,无需重新启动操作系统。
3、linux 传统上使用静态设备创建方法,因此大量设备节点在 /dev 下创建(有时上千个),而不管相应的硬件设备是否真正存在。采用udev的方法,只有被kernel检测到的设备才会被创建。
4、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机制:
1、udev怎么获取内核的这些模块动态变化的信息
设备节点的创建,是通过sysfs接口分析dev文件取得设备节点号。那么 udevd是通过什么机制来得知内核里模块的变化情况,怎么得知设备的插入移除情况呢?当然是通过hotplug机制了,那hotplug又是怎么实现的?或说内核是怎么通知用户空间一个事件的发生的呢?
答案是通过netlink socket通讯,在内核和用户空间之间传递信息。
内核调用kobject_uevent函数发送netlink message给用户空间,这部分工作通常不必驱动去自己处理,在统一设备模型里面,在子系统这一层面,已将这部分代码处理好了,包括在设备对应的特定的Kobject创建和移除的时候都会发送相应add和remove消息,当然前提是你在内核中设置了hotplug的支持。
Netlink socket作为一种内核和用户空间的通信方式,不仅仅用在hotplug机制中,同样还应用在其他非常多真正和网络相关的内核子系统中。
udevd通过标准的socket机制,创建socket连接来获取内核广播的uevent事件并解析这些uevent事件。
2、Udevd怎么监视规则文件的变更
如果内核版本足够新的话,在规则文件发生变化的时候,udev也能够自动的重新应用这些规则,这得益于内核的inotify机制,inotify是一种文件系统的变化通知机制,如文件增加、删除等事件能即时让用户态得知。
在 udevd中,对inotify和udev的netlink socket文件描述符都进行了select的等待操作。有事件发生以后再进一步处理。
3、Udevtrigger的工作机制?
运行 udevd以后,使用udevtrigger的时候,会把内核中已存在的设备的节点创建出来,那么他是怎么做到这一点的? 分析udevtrigger的代码能看出:
udevtrigger通过向/sysfs 文件系统下现有设备的uevent节点写"add"字符串,从而触发uevent事件,使得 udevd能够接收到这些事件,并创建buildin的设备驱动的设备节点及所有已insmod的模块的设备节点。
4、udev与mdev:udev 和mdev 是两个使用uevent 机制处理热插拔问题的用户空间程序,两者的实现机理不同。udev 是基于netlink 机制的,它在系统启动时运行了一个deamon 程序udevd,通过监听内核发送的uevent 来执行相应的热拔插动作,包括创建/删除设备节点,加载/卸载驱动模块等等。mdev 是基于uevent_helper 机制的,它在系统启动时修改了内核中的uevnet_helper 变量(通过写/proc/sys/kernel/hotplug),值为“/sbin/mdev”。这样内核产生uevent 时会调用uevent_helper 所指的用户级程序,也就是mdev,来执行相应的热拔插动作。udev 使用的netlink 机制在有大量uevent 的场合效率高,适合用在PC 机上;而mdev 使用的uevent_helper 机制实现简单,适合用在嵌入式系统中。另外要说明的一点是,uevent_helper 的初始值在内核编译时时可配置的,默认值为/sbin/hotplug。如果想修改它的值,写/proc/sys/kernel/hotplug 文件就可以了,例如:
echo “/sbin/mdev” > /proc/sys/kernel/hotplug
原文链接:https://blog.csdn.net/chituhuan/article/details/52383610
原文链接:https://blog.csdn.net/huangminilong/article/details/83782142

三、如何得到udev ?
udev的主页在这里: http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
我们按照下面的步骤来生成udev的工具程序,以arm-linux为例:
1、wget http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/udev-100.tar.bz2
2、tar xjf udev-100.tar.bz2
3、cd udev-100 编辑Makefile,查找CROSS_COMPILE,修改CROSS_COMPILE ?= arm-linux-
4、make

没有什么意外的话当前目录下生成udev,udevcontrol, udevd, udevinfo,udevmonitor,udevsettle,udevstart,
udevtest,udevtrigger九个工具程序,在嵌入式系统里,我们只需要 udevd和udevstart就能使udev工作得很好,
其他工具则帮助我们完成udev的信息察看、事件捕捉或者更高级的操作。

另外一个方法是直接使用debian提供的已编译好的二进制包,美中不足的是版本老了一些。
1、wget http://ftp.us.debian.org/debian/pool/main/u/udev/udev_0.056-3_arm.deb
2、ar -xf udev_0.056-3_arm.deb
3、tar xzf data.tar.gz

在sbin目录里就有我们需要的 udevd和udevstart工具程序。
建议大家采用第一种方式生成的 udevd和udevstart。为什么要用最新udev呢?新的强,旧的弱,用强的不用弱的。

第四、如何配置udev?

1、首先,udev需要内核sysfs和tmpfs的支持(需要在udev进程启动前挂载sysfs和tmpfs文件系统),sysfs为udev提供设备入口和uevent通道,tmpfs为udev设备文件提
供存放空间,也就是说,在上电之前系统上是没有足够的设备文件可用的,我们需要一些技巧让kernel先引导起来。

由于在kernel启动未完成以前我们的设备文件不可用,如果使用mtd设备作为rootfs的挂载点,这个时候/dev/mtdblock
是不存在的,我们无法让kernel找到rootfs,kernel只好停在那里panic。
这个问题我们可以通过给kernel传递设备号的方式来解决,在linux系统中,mtdblock的主设备号是31,part号
从0开始,那么以前的/dev/mtdblock/3就等同于31:03,以次类推,所以我们只需要修改bootloader传给kernel
的cmd line参数,使root=31:03,就可以让kernel在 udevd未起来之前成功的找到rootfs。

2、其次,需要做的工作就是重新生成rootfs,把 udevd和udevstart复制到/sbin目录。然后我们需要在/etc/下为udev建立设备规则(/etc/udev/udev.conf和/etc/udev/rules.d/udev.rules),这可以说是udev最为复杂的一步。这篇文章提供了最完整的指导: Writing udev rules文中描述的复杂规则我们可以暂时不用去理会,上路指南将带领我们轻松穿过这片迷雾。这里提供一个由简入繁的方法,对于嵌入式系统,这样做可以一劳永逸。

1)在前面用到的udev-100目录里,有一个etc目录,里面放着的udev目录包含了udev设备规则的详细样例文
本。为了简单而又简洁,我们只需要用到etc/udev/udev.conf这个文件,在我们的rootfs/etc下建立一个udev目
录,把它复制过去,这个文件很简单,除了注释只有一行,是用来配置日志信息的,嵌入式系统也许用不上
日志,但是 udevd需要检查这个文件。

2)在rootfs/etc/udev下建立一个rules.d目录,生成一个空的配置文件touch etc/udev/rules.d/udev.conf。然后
我们来编辑这个文件并向它写入以下配置项:

###############################################
# vc devices
KERNEL=="tty[0-9]*", NAME="vc/%n"

# block devices
KERNEL=="loop[0-9]*", NAME="loop/%n"

# mtd devices
KERNEL=="mtd[0-9]*", NAME="mtd/%n"
KERNEL=="mtdblock*", NAME="mtdblock/%n"

# input devices
KERNEL=="mice" NAME="input/%k"
KERNEL=="mouse[0-9]*", NAME="input/%k"
KERNEL=="ts[0-9]*", NAME="input/%k"
KERNEL=="event[0-9]*", NAME="input/%k"

# misc devices
KERNEL=="apm_bios", NAME="misc/%k"
KERNEL=="rtc", NAME="misc/%k"
################################################

保存它,我们的设备文件系统基本上就可以了, udevd和udevstart会自动分析这个文件。

3、为了使 udevd在kernel起来后能够自动运行,我们在rootfs/etc/init.d/rcS中增加以下几行:

PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH

udev_root=/dev
#udevd是一个二进制文件
UDEV_BIN=/sbin/udevd
test -x $UDEV_BIN || exit 1
#udevstart是一个二进制文件
UDEVSTART_BIN=/sbin/udevstart
test -x $UDEVSTART_BIN || exit 1
#udev的配置文件
UDEV_CONFIG=/etc/udev/udev.conf
test -r $UDEV_CONFIG || exit 1
. $UDEV_CONFIG

#检查sysfs文件系统是否挂载
SYSFS=/sys
if [ ! -d $SYSFS ]; then
echo "${0}: SYSFS \"$SYSFS\" not found"
fi
grep -q "^sysfs $SYSFS" /proc/mounts || mount -t sysfs sys /sys 

#将udev以ramfs文件系统的格式挂载到/etc目录
if [ ! -d $udev_root ]; then
echo "${0}: udev_root \"$udev_root\" not found"
fi
grep -q "^udev $udev_root" /proc/mounts || mount -t ramfs udev $udev_root || exit 1

#创建虚拟终端ttyS0设备节点
mknod /dev/ttyS0 c 4 64
mkdir $udev_root/pts $udev_root/shm
#为虚拟设备/dev/null、/dev/zero、/dev/console创建设备节点
#/dev/null称为空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF。
mknod -m 0666 /dev/null c 1 3
#/dev/zero“零”设备,可以无限的提供空字符(0x00,ASCII代码NUL)。常用来生成一个特定大小的文件。
mknod -m 0666 /dev/zero c 1 5
#/dev/console这个设备代表的是系统控制台。错误信息和诊断信息通常会被发送到这个设备。可用于printk信息输出。它是个虚拟设备, 他需要映射到真正的tty设备,比如2440,会映射到 ttySAC0
mknod -m 0600 /dev/console c 5 1

#启动udev文件系统的守护进程udevd
$UDEV_BIN -d
#启动udevstart进程
$UDEVSTART_BIN

4、重新生成rootfs,烧写到flash指定的rootfs part中。

5、如果需要动态改变设备规则,可以把etc/udev放到jffs或yaffs part,以备修改,根据需求而定,可以随时扩
充udev.conf中的配置项。

  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值