1.cdev结构体
linux2.6中使用cdev结构体描述字符设备
以下宏可以获得主次设备号
3.分配和释放设备号
在调用cdev_add()向系统注册字符设备之前,需要先向系统申请设备号。
静态分配:用于已知起始设备的设备号,需要先查询,避免冲突
linux2.6中使用cdev结构体描述字符设备
struct cdev {
struct kobject kobj;//内嵌的kobject对象
struct module *owner;//所属模块
const struct file_operations *ops;//文件操作结构体
struct list_head list;
dev_t dev;//设备号
unsigned int count;
};
dev_t定义了设备号,为32位,高12位为主设备号,低20位为次设备号。以下宏可以获得主次设备号
MAJOR(dev_t dev);
MINOR(dev_t dev);
通过主次设备号获得dev_t的宏MKDEV(int major,int minor);
2.cdev的主要操作函数内核提供了一些操作cdev的结构体
void cdev_init(struct cdev *,struct file_operations *);
struct cdev *cdev_alloc(void);
void cdev_put(struct cdev *p);
int cdev_add(struct cdev *,dev_t,unsigned);
void cdev_del(struct cdev *);
cdev_init()初始化cdev的成员,建立cdev和file_operation之间的连接
void cdev_init(struct cdev *cdev,struct file_operations *fops)
{
memset(cdev,0,sizeof *cdev);//清除cdev中的缓存
INIT_LIST_HEAD(&cdev->list);
cdev->kobj.ktype=&ktype_cdev_default;
kobject_init(&cdev->kobj);
cdev->ops=fops;//将传入的文件操作结构体指针赋值给cdev的ops
}
cdev_alloc用于动态申请一个cdev内存
struct cdev *cdev_alloc(void)
{
struct cdev *p=kmalloc(sizeof (struct cdev),GFP_KERNEL);//分配cdev的内存
if(p)
{
memset(p,0,sizeof(struct cdev));
p->kobj.type=&ktype_cdev_dynamic;
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj);
}
return p;
}
cdev_add()向系统添加一个cdev,完成字符设备的注册,用于模块加载函数中。
cdev_del()向系统删除一个cdev,完成字符设备的注销,用于模块卸载函数中。3.分配和释放设备号
在调用cdev_add()向系统注册字符设备之前,需要先向系统申请设备号。
静态分配:用于已知起始设备的设备号,需要先查询,避免冲突
int register_chrdev_region(dev_t from,unsigned count,const char *name);
from:要注册的第1个设备号
count:要注册的次设备号个数
name:设备名
动态分配:向系统动态申请未占用的设备号,可自动避免设备号冲突
int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name)
dev:分配到的设备号
baseminor:起始次设备号,不一定要从0开始
count:要注册的设备号个数
name:设备名
释放设备号之前,需要先调用cdev_del()函数注销字符设备
释放: void unregister_chrdev_region(dev_t from,unsigned count);