一、字符设备核心:
字符设备的核心包括cdev结构体和设备号!
- cdev结构体:驱动中用来描述一个字符设备。
struct cdev {
struct kobject kobj;//内核对象,由内核管理
struct module *owner;
const struct file_operations *ops;//字符设备驱动方法结构体,需自己填充
struct list_head list;
dev_t dev;//设备号一般有自己指定和动态申请两种方式
unsigned int count;
};
- 设备号:实现设备文件与驱动的程序的关联。
<include/linux/types.h>
-------------------------------------------------
typedef __u32 __kernel_dev_t;
typedef __kernel_dev_t dev_t;
---->dev_t dev_num = MKDEV(major, minor);//指定方式
major = MAJOR(dev_num);
minor = MINOR(dev_num);
二、字符设备一般注册方法register_chrdev(…)函数内部封装了设备号申请以及cdev创建并注册的过程,如下图:
1)register_chrdev()-->申请主设备号并注册
-->__register_chrdev()
上图描述的是一般的注册函数方法的拆分(深入)。
2)class_create()-->创建设备类。
查看方法:cat /proc/devices
3)device_create()-->创建设备节点
查看方法:cat /dev
三、cdev方式注册注销字符设备的流程:
注册:
1、申请并注册主从设备号
2、初始化已定义的cdev变量,cdev变量指定file_operations接口
3、添加cdev变量到内核,完成驱动注册,添加cdev时需要一个已申请成功的主从设备号
注销:
1、删除已添加的cdev
2、注销申请的主从设备号
例子:(描述上述功能代码:一般在驱动入口函数中!)
signed int ret = 0;
printk(KERN_WARNING "**%d,%s**\n", __LINE__, __FUNCTION__);
devid = MKDEV(500, 500);/* 指定设备号 */
ret = register_chrdev_region(devid, 1, DEMOS_NAME);//1、指定设备号
//ret = alloc_chrdev_region(&devid, 0, 1, DEMOS_NAME);//2、动态申请设备号
cdev_init(&demo_cdev, &f_ops);
ret = cdev_add(&demo_cdev, devid, 1);
my_class = class_create(THIS_MODULE, DEMOS_NAME);
my_device = device_create(my_class, NULL, devid, NULL, DEMOS_DEV);