在linux2.4和linux2.6早期版本中,在驱动开发中,多使用mknod命令手动创建设备节点,但当动态申请设备号时必须通过命令查出设备号,再添加。或者使用DEVFS文件系统函数添加设备节点。DEVFS在现在linux内核中已取消,取而代之的是UDEV,UDEV是处于用户态的程序。它根据内核发出的EVENTS,动态创建事件。内核是通过device_create发出event,我得linux版本是linux2.6.37所以要动态创建设备节点,必须在系统中移植UDEV(很简单,这里就不说了)。
下面我们看看在驱动中动态添加框架:
1.创建类:
创建类在base/class.c中实现,在linux2.6.37中clase_create是一个宏在device.h中定义
#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \
__class_create(owner, name, &__key); \
})
struct class *__class_create(struct module *owner, const char *name,
struct lock_class_key *key)
{
struct class *cls;
int retval;
cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
cls->name = name;
cls->owner = owner;
cls->class_release = class_create_release;
retval = __class_register(cls, key); //注册类
if (retval)
goto error;
return cls;
error:
kfree(cls);
return ERR_PTR(retval);
}
a.在驱动程序中首先定义全局类变量:static struct class *my_class;
b.在完成字符设备添加cdev_add完成后调用class_create创建类(其实位置无所谓,但是如果设备没有创建成功,创建没有意义): my_class = class_create(THIS_MODULE, "m24256");
c.在驱动卸载时销毁类
class_destroy(my_class);
2.动态创建设备节点
调用class_create给UDEV发送event,UDEV接收到后自动在/dev下创建设备节点
device_create函数在device.h导出。在core.c中实现
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;
}
EXPORT_SYMBOL_GPL(device_create);
device_create(my_class, NULL,devno,NULL, "m24256");
在驱动卸载时销毁:
void device_destroy(struct class *class, dev_t devt)
{
struct device *dev;
dev = class_find_device(class, NULL, &devt, __match_devt);
if (dev) {
put_device(dev);
device_unregister(dev);
}
}
EXPORT_SYMBOL_GPL(device_destroy);
device_destroy(my_class, data->dev.dev);