udev比devfs好在哪里
为什么devfs 会被udev取代?
首先明确一点
udev 运行在用户空间 (内核版本2.6及以上)
devfs 运行在内核空间(内核版本 2.4)
Linux 设计中强调的一个基本观点是机制和策略的分离。
机制是做某样事情的固定步骤、方法,而策略就是每个步骤所采取的不同方式。
机制是相对固定的,而每个步骤采用的策略是不固定的。
机制是稳定的,而策略则是灵活的,因此在linux内核中,不应该实现策略
比如Linux 提供API可以让人把县城优先级调高或者调低,或者调整调度策略为SCHED_FIFO,
但是Linux内核本身却不管谁高谁低。
提供API属于机制,谁高谁低属于策略,所以应该是应该程序自己去告诉内核要高或者低,而内核不管这些杂事。
因此属于策略的东西应该被移动用户空间中,谁爱给那个设备创建什么名字或者想做更多的处理,谁自己去设定。
内核只管把这些信息告诉用户就可以了。
这就是位于内核空间的devfs应该被位于用户空间的udev取代的原因
udev 完全在用户态工作,利用设备加入或移除时内核所发送的热插拔事件(hotplug Event)来工作。
在热插拔时,设备的详细信息会由内核通过netlink套接字发送出来,发出的事件叫uevent.
udev的设备命名策略、权限控制和事件处理都是在用户态完成的,它利用从内核收到的信息来进行创建
设备文件节点等工作
devfs 与 udev 的另一个显著区别在于:采用devfs,当一个并不存在的/dev节点被打开的时候,devfs能自动加载对应的驱动,而udev则不这么做。这是因为udev的设计者认为Linux应该在设备被发现的时候加载驱动模块,而不是当它被访问的时候。
udev的设计者认为devfs所提供的打开/dev节点时自动加载驱动的功能对一个配置正确的计算机来说是多余的。系统中所有的设备都应该产生热插拔事件并加载恰当的驱动,而udev能注意这点并且为它创建对应的设备节点
本代码就是从内核通过netlink接收热插拔事件并显示出来
#include <linux/netlink.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <poll.h>
static void die(char *s)
{
write(2,s,strlen(s));
exit(1);
}
int main(int argc,char *argv[])
{
struct sockaddr_nl nls;
struct pollfd pfd;
char buf[512];
//open hotplug event netlink socket
memset(&nls, 0, sizeof(struct sockaddr_nl));
nls.nl_family = AF_NETLINK;
nls.nl_pid = getpid();
nls.nl_groups = -1;
pfd.events = POLLIN;
pfd.fd = socket(PF_NETLINK , SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
if(pfd.fd == -1)
die("Not root\n");
//Listen to netlink socket
if (bind(pfd.fd ,(void *)&nls , sizeof(struct sockaddr_nl)))
die("Bind failed\n");
while(-1 != poll(&pfd ,1,-1))
{
int i , len = recv(pfd.fd,buf,sizeof(buf),MSG_DONTWAIT);
if(len == -1)
die("recv\n");
//print the data to stdout
i = 0;
while (i < len)
{
printf("%s\n",buf +i);
i += strlen(buf + i) +1;
}
}
die("poll\n");
//dear gcc;shut up
return 0;
}
上文摘抄自《Linux设备驱动开发详解:基于最新的Linux 4.0内核》
Makefile文件
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
SRC = main.c
OBJ = main
all:
$(CROSS_COMPILE)gcc $(SRC) -o $(OBJ)
clean:
rm $(OBJ) $(OBJ).o
手动触发uevent
echo add > /sys/module/psmouse
此时就能看到信息流被打印出来了
如果提示没有权限这样操作,可以用一个U盘插入电脑,也能看到内核发出的netlink 信息