10.1 分配内存空间 前面介绍的杂项设备并没有分配内存空间这个过程,是因为系统自带的代码已经给杂项设备分配好了。 Linux 中注册字符类设备需要首先申请内存空间,有一个专门分配小内存空间的函数kmalloc,这个函数在头文件“include/linux/slab.h”中,如下图所示
如上图所示,函数sta tic inline void *kzalloc(size_t size, gfp_t flags)有两个参数,参数size_t size:申请的内存大小(最大128K),参数gfp_t flags:常用参数GFP_KERNEL,代表优先权,内存不够可以延迟分配。 和申请内存的函数kzalloc 对应的是kfree 释放函数,如下图所示。
void kfree(const void *)函数只有一个参数,就是内存的指针,这个指针由申请内存的函数kzalloc 返回。 10.2 注册字符类设备的函数 注册字符类设备的初始化函数为cdev_init,这个函数在头文件“include/linux/cdev.h”中,使用命令“vim include/linux/cdev.h”打开这个头文件如下图所示。
如上图所示红框中的函数“void cdev_init(struct cdev *, const struct file_operations *)”和结构体“cdev”。cdev_init 函数有两个参数,参数struct cdev *:cdev 字符设备文件结构体,参数const struct file_operations *:file_operations 结构体,注册字符设备的函数为cdev_add,这个函数也是在头文件“include/linux/cdev.h”中,如下图所示。
如上图所示,和注册驱动的函数cdev_add 对应的还有卸载驱动的函数cdev_del。注册驱动的函数int cdev_add(struct cdev *, dev_t, unsigned);有三个参数:参数struct cdev *:cdev 字符设备文件结构体,参数dev_t:设备号dev,参数unsigned:设备范围大小,卸载驱动的函数void cdev_del(struct cdev *)只有一个参数,cdev 字符设备结构体 10.3 源代码 如下图所示,添加申请内存空间函数的头文件“linux/slab.h”,然后定义内存空间大小为3000。
接着将申请的内存数据控件打个包为结构体reg_dev,因为是有两个子设备,所以接着定义一个结构体数组*my_devices。
然后申请内存空间,并将内存空间先清零,接着对设备进行初始化,如下图所示。
如上图所示,用到多次memset 函数,第一次由于没有规定my_devices.data 的大小,所以只是对默认大小的数据赋值为0,在设备初始化的循环中,又重新对my_devices.data申请了REGDEV_SIZE 大小的数据,所以需要重新赋值为0。然后如下图所示,是自定义的函数reg_init_cdev,在这个函数中会将my_devices 和编号传过去。
如上图所示,首先需要将设备号使用MKDEV 转化成dev_t 类型,然后初始化,接着给dev->cdev 赋值。这里只给cdev 添加了两个参数owner 和ops,参数owner 默认为THIS_MODULE,参数ops 这里只定义了其中的参数owner。接着添加一下fail 部分,如下图所示。 |