自动创建设备节点

udev

udev根据sysfs系统提供的设备信息来实现对/dev目录下设备节点的动态管理,包括设备节点的创建和删除。

因此想要系统可以自动创建设备节点就是要利用udev,就是在sysfs系统中注册设备信息。


sysfs

sys/devices

在这里插入图片描述
安装模块之后会在sysfs/device下创建对应的设备名同名文件夹,通过检测这个文件夹来自动创建设备节点。

book@100ask:/sys/devices/virtual/input/mice$ ls
dev  power  subsystem  uevent

其中也储存了设备的信息。

cat uevent
MAJOR=13
MINOR=63
DEVNAME=input/mice

sysfs/devices目录与/dev目录下数据相互对应的

book@100ask:/sys/devices/virtual/input/mice$ ls /dev/input/mice -l
crw-rw---- 1 root input 13, 63 Jun 11 17:32 /dev/input/mice

sys/class

sysfs是管理设备的一种虚拟文件系统,挂载在/sys目录下。每一个设备在sysfs目录中都有唯一对应的目录,可以从用户层访问。
在这里插入图片描述
将所有的设备分类统一,比如输入设备都在class/input目录下。
sys/class/XXX/dev:设备号信息
sys/class/XXX/uevent:完整的设备信息
udev根据sysfs目录中的内容,在/dev目录下创建相应的设备节点。


class_creat 创建一个类

/* This is a #define to keep the compiler from merging different
 * instances of the __key variable */
#define class_create(owner, name)		\
({						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})

将会在 sysfs/class创建一个类,所有的设备都会隶属于一个类。


在类下创建设备:device_create

/**
 * device_create - creates a device and registers it with sysfs
 * @class: pointer to the struct class that this device should be registered to
 * @parent: pointer to the parent struct device of this new device, if any
 * @devt: the dev_t for the char device to be added
 * @drvdata: the data to be added to the device for callbacks
 * @fmt: string for the device's name
 *
 * This function can be used by char device classes.  A struct device
 * will be created in sysfs, registered to the specified class.
 *
 * A "dev" file will be created, showing the dev_t for the device, if
 * the dev_t is not 0,0.
 * If a pointer to a parent struct device is passed in, the newly created
 * struct device will be a child of that device in sysfs.
 * The pointer to the struct device will be returned from the call.
 * Any further sysfs files that might be required can be created using this
 * pointer.
 *
 * Returns &struct device pointer on success, or ERR_PTR() on error.
 *
 * Note: the struct class passed to this function must have previously
 * been created with a call to class_create().
 */
struct device *device_create(struct class *class, struct device *parent,
			     dev_t devt, void *drvdata, const char *fmt, ...)
{
	va_list vargs;
	struct device *dev;

	va_start(vargs, fmt);
	dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
	va_end(vargs);
	return dev;
}

parent该设备的父类,或者NULL;drvdata设备回调函数值,或者NULL;fmt const char *类型的可变参数,设备名(节点)。
device_create就是在sysfs系统下创建设备节点。
当模块被加载时:
1、在sys/devices中创建设备同名XXX目录;并注册到特定的class(sysfs/class)。
2、在sys/devices/XXX下创建dev目录(设备节点),存入设备号信息。
3、udev检测到sysfs下的设备更新,自动去/dev下创建设备节点。


关于参数列表中的 … 三个圆点
“变参数函数”,头文件<stdarg.h>
这里提供了一个特殊类型va_list。在每个变参数函数的函数体里必须定义一个va_list类型的局部变量,它将成为访问由三个圆点所代表的实际参数的媒介。在能够用vap访问实际参数之前,必须首先用“函数”va_start做这个变量初始化。函数va_start的类型特征可以大致描述为:
va_start(va_list vap, 最后一个普通参数)
实际上va_start通常并不是函数,而是用宏定义实现的一种功能。在函数sum里对vap初始化的语句应当写为:
va_start(vap, n);
在完成这个初始化之后,我们就可以通过另一个宏va_arg访问函数调用的各个实际参数了。
但是所有参数类型是固定的。


注册流程

1、定义

static struct lock_class_key *hello_class;
static struct file_operations hello_drv = {}

2、注册

1、注册设备名设备号,得到设备号
register_chrdev(major, "hello", &hello_drv);
2、创建设备类
hello_class = class_create(THIS_MODULE, "hello_class");
3、创建设备==**节点**==并注册到sysfs/devices下。
device_create(hello_class, NULL, MKDEV(major, 0), NULL, "hello");

3、出错返回和销毁

if(IS_ERR(error)){
	printk("......");
	/*提取错误码*/
	ret = PTR_ERR(error);
	goto A
}

A:
	device_destroy(hello_class, MKDEV(major, minor));
	class_destroy(hello_class);
	/* 在卸载时主设备号不能为0 */
	unregister_chrdev(major, "hello");

销毁时后创建的先销毁,先创建的后销毁。
1、如果不是自己创建的类,就不要销毁了。
2、在每一个可能出错地方都需要记得销毁。


/proc/devices 中呈现的是已经分配好的设备号,但不代表该设备号对应的设备节点已经被创建。插入驱动后都可以根据/proc/devices文件中的信息来创建设备节点。
device_creat()函数用于在sysfs/class中创建dev文件,以供用户空间使用;是在sysfs系统中创建设备节点。
udev根据sysfs目录中的内容,在/dev目录下创建相应的设备节点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值