(本章基于:linux-4.4.0-37)
Linux内核模块具有自动创建设备模块的功能(需要应用层支持udev)
使用class_create()创建一个类,这个类可在/sys/class下找到对应目录,再用device_create()在类中创建设备。当模块被加载时udev会在类目录下发现此设备,并在/dev下创建相应的设备文件。
(以下宏、函数均在linux/device.h中定义)
创建类:
class_create(owner, name)
owner:当前模块
name:类名称
返回一个struct class类型指针,返回值需要使用IS_ERR()检查,成功创建后可在/sys/class下找到相应的目录
销毁类:
void class_destroy(struct class *cls);
创建设备节点:
struct device *device_create(struct class *cls, struct device *parent,
dev_t devt, void *drvdata,
const char *fmt, ...);
cls:类
parent:父设备,没有为NULL
devt:设备号
drvdata:被添加到该设备回调的数据,不能为NULL
fmt:设备名
删除设备节点:
void device_destroy(struct class *cls, dev_t devt);
例:
hello.c
#include <linux/device.h>
static dev_t devId;
static struct class *cls = NULL;
static __init int hello_init(void)
{
int result;
if(( result = alloc_chrdev_region(&devId, 0, 1, "stone-alloc-dev") ) != 0) {
printk(KERN_WARNING "register dev id error:%d\n", result);
goto err;
} else {
printk(KERN_WARNING "register dev id success!\n");
}
cls = class_create(THIS_MODULE, "stone-class");
if(IS_ERR(cls)) {
printk(KERN_WARNING "create class error!\n");
goto err;
}
if(device_create(cls, NULL, devId, "", "hello%d", 0) == NULL) {
printk(KERN_WARNING "create device error!\n");
goto err;
}
printk(KERN_ALERT "hello init success!\n");
return 0;
err:
device_destroy(cls, devId);
class_destroy(cls);
unregister_chrdev_region(devId, 1);
return -1;
}
static __exit void hello_exit(void)
{
device_destroy(cls, devId);
class_destroy(cls);
unregister_chrdev_region(devId, 1);
printk(KERN_WARNING "helloworld exit!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stone");
成功加载模块后可在/dev/下发现此设备
# ls /dev/hello0 -l
crw------- 1 root root 247, 0 Apr 18 21:22 /dev/hello0