欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux设备驱动--字符设备(三、自动创建设备文件)

程序员文章站 2022-07-14 16:30:58
...

之前写Linux设备驱动程序的时候,都是利用mknod命令手动创建设备节点:

% mknod Name { b | c } Major Minor

用完之后,需要删除时,使用 rm Name 命令删除设备文件。这样做相当繁琐。实际上Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录下创建相应设备节点,并在卸载模块时删除该节点,前提条件是用户空间移植了udev(嵌入式中用的是mdev)。

在Linux早期,设备文件仅仅是是一些带有适当的属性集的普通文件,它由mknod命令创建,文件存放在/dev目录下;

后来,采用了devfs, 一个基于内核的动态设备文件系统,他首次出现在2.3.46内核中。Mandrake,Gentoo等Linux分发版本采用了这种方式。devfs创建的设备文件是动态的。但是devfs有一些严重的限制,从2.6.13版本后被移走;

目前取代它的便是udev —— 它是一个用户空间程序。因为udev需要sysfs文件系统的支持(sysfs文件系统只在linux-2.6内核中才有),所以它存在于Linux-2.6版本之后的内核。udev借助于netlink协议在内核驱动和应用层之间传递信息。当内核中的驱动完成注册和注销时,信息会被传送给应用层的udev,udev便会自动地完成设备文件的创建和删除。

内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类, 内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。

注意,在2.6较早的内核版本中,device_create(…)函数名称不同,是class_device_create(…),所以在新的内核中编译以前的模块程序有时会报错,就是因为函数名称不同,而且里面的参数设置也有一些变化。
struct class和device_create(…) 以及device_create(…)的原型都可以在/include/linux/device.h中找到。

#define class_create(owner, name)		\
({						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})
owner为类的拥有者,通常为THIS_MODULE;name为类名。返回一个struct class结构体。
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;
}
class为class_create创建的类,parent为父设备,devt为设备号,drvdata被添加到该设备回调的数据,fmt设备名。

其作用为创建一个设备并注册到内核驱动架构。

示例:

myclass= class_create(THIS_MODULE, "test_class");
if (IS_ERR(myclass))
    return -EINVAL;
device_create(myclass, NULL, mydev, NULL, "test");
如此,在模块加载后,就可以在/dev目录下找到test这个设备文件了。对应的,模块卸载时的操作为:

device_destroy(myclass, mydev);
class_destroy(myclass); 

如此,在模块卸载时,udev就会自动把/dev/test这个设备文件删除。

最直观的变化的是,class_create在 /sys/class 下新建了一个名为“test_class”的设备类文件。进入到test_class类,device_create在里面新建了一个名为“test”的设备。这是Linux下的基于对象的设计思想。在test设备下,共有四个文件(power和subsystem为文件夹),其中的dev记录设备的主次设备号,uevent用于内核传递给应用层创建设备文件(通过事件传递机制)。

Linux设备驱动--字符设备(三、自动创建设备文件)