函数cdev_alloc()用于动态申请并分配一个新的字符设备,该字符设备用cdev结构体变量描述,并对这个结构体变量进行初始化,其中包括cdev->list
对象及cdev->kobj
对象。经过cdev_alloc
分配的cdev结构的变量还需初始化cdev->owner
和cdev->ops
对象之后才能被加入Linux内核系统。
cdev_alloc文件包含
#include <linux/cdev.h>
cdev_alloc函数定义
在内核源码中的位置:linux-3.19.3/fs/char_dev.c
函数定义格式:
struct cdev *cdev_alloc(void)
cdev_alloc输入参数说明
- 函数的输入参数是void类型的变量,即不需要任何参数。
cdev_alloc返回参数说明
函数cdev_alloc()返回的结果是struct cdev结构体类型的指针变量,代表新创建的字符设备对象,定义见文件linux-3.19.3/include/linux/cdev.h,如下:
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
其中:
- 字段
kobj
用来描述设备的引用计数,在终端中,可以通过lsmod命令显示模块相关的信息,其中包括引用计数。 - 字段
owner
描述了模块的从属关系,指向拥有这个结构的模块的指针,这个描述符只有对编译为模块方式的驱动才是有意义的,一般赋值为“THIS_MODULE”
。 - 字段
ops
描述了字符设备的操作函数指针,此结构体的详细解释可以参考函数cdev_init()的分析文档的输入参数说明部分。 - 字段
list
描述了与cdev对应的字符设备文件的inode->i_devices
的链表的表头。 - 字段
dev
描述了字符设备的设备号,包括主设备号和次设备号。 - 字段
count
指定设备编号范围的大小。
cdev_alloc实例解析
编写测试文件:cdev_alloc.c
头文件引用、全局变量定义:
/*头文件引用*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/cdev.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
struct cdev *mem_cdev; //字符设备对象
模块加载函数定义:
static int __init cdev_alloc_init (void)
{
printk("into the cdev_alloc_init\n");
mem_cdev = cdev_alloc(); //调用函数动态分配字符设备
if (mem_cdev == NULL) //检测函数调用成功与否
{
printk("cdev_alloc failed! \n");
return -1;
}
/*显示设备地址空间*/
printk("cdev_alloc success! addr = 0x%x\n", (unsigned int)mem_cdev); if(&(mem_cdev->list)! =NULL) //检测函数调用结果,对list的初始化情况
printk("the list_head of the mem_cdev has been initialized\n");
if(&(mem_cdev->kobj)! =NULL) //检测函数调用结果,对字段kobj的初始化情况
{
printk("the kobj of the mem_cdev has been initialized\n");
printk("the state_in_sysfs of the kobj of the mem_cdev is:%d\n", mem_cdev->kobj.state_in_sysfs);
printk("the state_initialized of the kobj of the mem_cdev is:%d\n", mem_cdev->kobj.state_initialized);
}
printk("out the cdev_alloc_init\n");
return 0;
}
模块退出函数定义:
static void __exit cdev_alloc_exit (void)
{
printk("into cdev_alloc_exit\n");
if (mem_cdev ! = NULL)
kfree(mem_cdev); //释放设备空间
printk("kfree mem_cdev OK! \n");
printk("out cdev_alloc_exit\n");
}
模块加载、退出函数调用:
module_init(cdev_alloc_init); //模块加载函数调用
module_exit(cdev_alloc_exit); //模块卸载函数调用
实例运行结果及分析:
首先编译模块,执行命令insmod cdev_alloc.ko插入内核模块,然后输入命令dmesg -c查看模块插入结果,会出现如图A
所示的结果。
卸载内核模块,执行命令rmmod cdev_alloc.ko,然后输入命令dmesg -c出现如图B
所示的信息。
结果分析:
由图A
可以看出函数cdev_alloc()成功执行后,新字符设备申请成功,并且对cdev->list
对象及cdev->kobj
对象的初始化也是成功的。