Linux内核API cdev_alloc

函数cdev_alloc()用于动态申请并分配一个新的字符设备,该字符设备用cdev结构体变量描述,并对这个结构体变量进行初始化,其中包括cdev->list对象及cdev->kobj对象。经过cdev_alloc分配的cdev结构的变量还需初始化cdev->ownercdev->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所示的结果。

Linux内核API cdev_alloc

卸载内核模块,执行命令rmmod cdev_alloc.ko,然后输入命令dmesg -c出现如图B所示的信息。

Linux内核API cdev_alloc

结果分析:

由图A可以看出函数cdev_alloc()成功执行后,新字符设备申请成功,并且对cdev->list对象及cdev->kobj对象的初始化也是成功的。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程