Linux驱动开发probe字符设备的完整创建流程
一、 设备号分配
1.静态分配
通过register_chrdev_region预先指定设备号(需要确保未被占用)
2.动态分配
通过alloc_chrdev_region由内核自动分配主设备号,一般都是动态分配以避免冲突。
3316 xxxx_dev.major = 0;
3317
3318 if (xxxx_dev.major)
3319 {
3320 xxxx_dev.devid = MKDEV(xxxx_dev.major,0);
3321 ret = register_chrdev_region(xxxx_dev.devid, xxxx_CNT, XX_DRV_NAME);
3322 }
3323 else
3324 {
3325 ret = alloc_chrdev_region(&xxxx_dev.devid, 0, xxxx_CNT, XX_DRV_NAME);
3326 xxxx_dev.major = MAJOR(xxxx_dev.devid);
3327 xxxx_dev.minor = MINOR(xxxx_dev.devid);
3328 }
二、 初始化cdev结构体
通过cdev_init绑定file_operations操作集(需实现open、read、write等函数)
示例:
static struct file_operations xx_fops = {.owner = THIS_MODULE,.open = my_open,.read = my_read,.write = my_write,
};
cdev_init(&xxxx_dev.cdev, &xx_fops);
三、 注册字符设备
通过cdev_add将cdev添加到系统,关联设备号与操作集。
cdev_add(&xxx_dev.cdev, xxx_dev.devid, xxx_CNT);
四、 创建设备节点
1、手动创建:mknod命令在/dev 下生成设备文件
2、自动创建:
1)通过class_create创建设备类
2)调用device_create在/dev和/sys下自动生成设备节点
xxx_dev.class = class_create(THIS_MODULE, XXX_DRV_NAME);
xxx_dev.device = device_create(xxx_dev.class, NULL, xxx_dev.devid, NULL, xxx_DRV_NAME)
五、 资源释放(remove函数)
卸载驱动时需逆序释放资源:
device_destroy(my_class, dev_num);
class_destroy(my_class);
cdev_del(&my_cdev);
unregister_chrdev_region(dev_num, 1);
六、 总结
ret = alloc_chrdev_region(&xx_dev.devid, 0, xx_CNT, XX_DRV_NAME);
cdev_init(&xxx_dev.cdev, &xx_fops);
ret = cdev_add(&xx_dev.cdev, xx_dev.devid, xx_CNT);
xx_dev.class = class_create(THIS_MODULE, XX_DRV_NAME);
xx_dev.device = device_create(xx_dev.class, NULL, xx_dev.devid, NULL, XX_DRV_NAME);