一、接口
这个结构体表示一个字符设备,可以静态声明,也可以动态分配
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
1、设备号
设备号表示字符设备在系统中的唯一性,包括主设备号和次设备号,主要用于设备分大类的目的
下面是三个宏操作,分别是从设备号获取主设备号,次设备号,以主次设备号计算设备号
#define MAJOR(dev) ((dev)>>8)
#define MINOR(dev) ((dev) & 0xff)
#define MKDEV(ma,mi) ((ma)<<8 | (mi))
静态申请一个设备号,自己指定设备号去申请,有可能会失败
参数说明
from 表示从哪个设备号开始
count 表示连续几个设备号
name 字符设备的名称
int register_chrdev_region(dev_t from, unsigned count, const char *name)
动态申请设备号
参数说明
dev 申请返回的设备号
baseminor 次设备号从几开始
count 有几个次设备号
name 字符设备的名称
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name)
个人理解:申请设备号就是对dev_t范围内的数字进行占位,以达到字符设备号的唯一性。
所以,注册一个字符设备绑定多个次设备号,和注册多个字符设备绑定一个次设备号的效果是一样的吗???
2、字符设备注册
动态分配一个字符设备结构体
// 动态分配一个字符设备
struct cdev *cdev_alloc(void)
分配一个字符设备结构体后,需要对齐初始化(填充域),
下面接口我们主要关心,是给struct cdev初始化一个操作回调函数集。
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
初始化之后需要将字符设备驱动加入到系统管理
参数说明
p 注册的字符设备
dev 注册的设备号(第一个设备号,如果有多个次设备)
count 注册几个次设备
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
3、字符设备的移除和释放
void cdev_del(struct cdev *p)
void cdev_put(struct cdev *p)
4、封装过的接口
注册字符设备
// 这个接口会注册0~256的次设备号的字符设备
static inline int register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops);
major 主设备号
name 驱动名称
fops 操作集