笔记之 - class
==============
开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点(包括ldd3中不少例子也是这样),实际上现在Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录
下创建相应设备节点,并在卸载模块时删除该节点。
内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个
类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。
这样,加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
此外,利用device_create_file函数可以在/sys/class/下创建对应的属性文件,从而通过对该文件的读写实现特定的数据操作。
----------------------------------------------------------------------------------------------
#include
class_create()
class_destory()
创建及销毁/sys/class/下的一个目录, 创建一个struct class的结构体指针,这个指针可用作device_create()函数的参数。
device_create()
creates a device and registers it with sysfs。
注:device_create会默认创建一些属性。
device_create_file()
create sysfs attribute file for device.
需要引用device_create所返回的device*指针。
static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store);
---------------------------------------------------------------------------------
摘录(kernel docs device.txt):
Word of warning: While the kernel allows device_create_file() and
device_remove_file() to be called on a device at any time, userspace has
strict expectations on when attributes get created. When a new device is
registered in the kernel, a uevent is generated to notify userspace (like
udev) that a new device is available. If attributes are added after the
device is registered, then userspace won't get notified and userspace will
not know about the new attributes.
This is important for device driver that need to publish additional
attributes for a device at driver probe time. If the device driver simply
calls device_create_file() on the device structure passed to it, then
userspace will never be notified of the new attributes. Instead, it should
probably use class_create() and class->dev_attrs to set up a list of
desired attributes in the modules_init function, and then in the .probe()
hook, and then use device_create() to create a new device as a child
of the probed device. The new device will generate a new uevent and
properly advertise the new attributes to userspace.
--------------------------------------------------------------------------------------
简单示例:
#include
#include
#include
#include
#define MOD_AUTHOR "Jon"
#define MOD_DESC "A sample module"
static struct class *hello_class;
static struct device *dev;
static DEVICE_ATTR(hello, 0444, NULL, NULL);
static int __init init_hello(void)
{
int err = 0;
printk("Hello, world.\n");
hello_class = class_create(THIS_MODULE, "hello");
if(IS_ERR(hello_class))
{
err = PTR_ERR(hello_class);
printk(KERN_ALERT "Failed to create class.\n");
goto CLASS_CREATE_ERR;
}
dev = device_create(hello_class, NULL, MKDEV(100,0), NULL, "hello");
if(IS_ERR(dev))
{
err = PTR_ERR(dev);
printk(KERN_ALERT "Failed to create device.\n");
goto DEVICE_CREATE_ERR;
}
err = device_create_file(dev, &dev_attr_hello);
if(err < 0)
{
printk(KERN_ALERT "Failed to create attribute file.\n");
goto DEVICE_CREATE_FILE_ERR;
}
return 0;
DEVICE_CREATE_FILE_ERR:
device_destroy(hello_class, MKDEV(100, 0));
DEVICE_CREATE_ERR:
class_destroy(hello_class);
CLASS_CREATE_ERR:
return err;
}
static void __exit cleanup_hello(void)
{
printk("Goodbye, world.\n");
device_remove_file(dev, &dev_attr_hello);
device_destroy(hello_class, MKDEV(100, 0));
class_destroy(hello_class);
}
module_init(init_hello);
module_exit(cleanup_hello);
MODULE_LICENSE("GPL");
MODULE_AUTHOR(MOD_AUTHOR);
MODULE_DESCRIPTION(MOD_DESC);
阅读(790) | 评论(0) | 转发(0) |