字符设备的内核抽象

来源:互联网 发布:数据库冗余设计 编辑:程序博客网 时间:2024/05/18 06:27

字符设备的内核抽象

顾名思义,字符设备驱动程序管理的核心对象是字符设备。从字符设备驱动程序的设计框架角度出发,内核为字符设备抽象出了一个具体的数据结构struct cdev,其定义如下:

<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;

};

在本章后续的内容中将陆续看到它们的实际用法,这里只把这些成员的作用简单描述如下:

struct kobject kobj

内嵌的内核对象,其用途将在“Linux设备驱动模型”一章中讨论。

struct module *owner

字符设备驱动程序所在的内核模块对象指针。

const struct file_operations *ops

字符设备驱动程序中一个极其关键的数据结构,在应用程序通过文件系统接口呼叫到设备驱动程序中实现的文件操作类函数的过程中,ops指针起着桥梁纽带的作用。

struct list_head list

用来将系统中的字符设备形成链表。

dev_t dev

字符设备的设备号,由主设备号和次设备号构成。

unsigned int count

隶属于同一主设备号的次设备号的个数,用于表示由当前设备驱动程序控制的实际同类设备的数量。

设备驱动程序中可以用两种方式来产生struct cdev对象。一是静态定义的方式,比如在前面的那个示例程序中,通过下列代码静态定义了一个struct cdev对象:

static struct cdev chr_dev;

另一种是在程序的执行期通过动态分配的方式产生,比如:

static struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL);

其实Linux内核源码中提供了一个函数cdev_alloc,专门用于动态分配struct cdev对象。cdev_alloc不仅会为struct cdev对象分配内存空间,还会对该对象进行必要的初始化:

<fs/char_dev.c>

struct cdev *cdev_alloc(void)

{

       struct cdev *p =kzalloc(sizeof(struct cdev), GFP_KERNEL);

       if (p) {

              INIT_LIST_HEAD(&p->list);

              kobject_init(&p->kobj,&ktype_cdev_dynamic);

       }

       return p;

}

需要注意的是,内核引入structcdev数据结构作为字符设备的抽象,仅仅是为了满足系统对字符设备驱动程序框架结构设计的需要,现实中一个具体的字符硬件设备的数据结构的抽象往往要复杂得多,在这种情况下struct cdev常常作为一种内嵌的成员变量出现在实际设备的数据机构中,比如:

struct my_keypad_dev{

       //硬件相关的成员变量

       int a;

       int b;

       int c;

       …

       //内嵌的struct cdev数据结构

       struct cdev cdev;

};

在这样的情况下,如果要动态分配一个struct real_char_dev对象,cdev_alloc函数显然就无能为力了,此时只能使用下面的方法:

static struct real_char_dev *p = kzalloc(sizeof(struct real_char_dev),GFP_KERNEL);

前面讨论了如何分配一个structcdev对象,接下来的一个话题是如何初始化一个cdev对象,内核为此提供的函数是cdev_init:

<fs/char_dev.c>

void cdev_init(struct cdev *cdev, const struct file_operations *fops)

{

       memset(cdev, 0, sizeof *cdev);

       INIT_LIST_HEAD(&cdev->list);

       kobject_init(&cdev->kobj,&ktype_cdev_default);

       cdev->ops = fops;

}

函数的代码非常直白,不再赘述。一个struct cdev对象在被最终加入系统前,都应该被初始化,无论是直接通过cdev_init或者是其他途径。理由很简单,这是Linux系统中字符设备驱动程序框架设计的需要。

照理在谈完cdev对象的分配和初始化之后,下面应该讨论如何将一个cdev对象加入到系统了,但是由于这个过程需要用到设备号相关的技术点,所以暂且先来探讨设备号的问题。

 

——本段文字节选自《深入Linux设备驱动程序内核机制》

图书详细信息:http://blog.csdn.net/broadview2006/article/details/7281061

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 错过法宣考试怎么办 两套房改房不退怎么办 孩子初一政治差怎么办 学生上课老说话怎么办 一年级语文太差怎么办 二年级成绩不好怎么办 初中学生数学差怎么办 孩子数学计算能力差怎么办 股票没有客户号怎么办 五岁宝宝鼻炎怎么办 孩子怕老师家长怎么办 孩子得了厌学症怎么办 幼儿不好好吃饭怎么办 孩子在学校胆小怎么办 孩子胆小没自信怎么办 特别倔强的学生怎么办 初中生注意力不集中怎么办 父母水平太低怎么办 父母不肯买电脑怎么办 与父母性格不合怎么办 父母和孩子吵架怎么办 如果有孩子离婚怎么办 离婚时成年孩子怎么办 父母离婚后孩子怎么办 父母吵架闹离婚怎么办 父母吵架后冷战怎么办 家里每天都吵架怎么办 夫妻因为钱吵架怎么办 离婚了很痛苦怎么办 身份证丢了怎么办离婚 和老婆离婚了怎么办 老婆跟前任联系怎么办 离异小孩上户口怎么办 离婚之后孩子户口怎么办 父母离婚孩子户口怎么办 夫妻离婚孩子户口怎么办 孩子有心理阴影怎么办 孩子心里有障碍怎么办 初中的孩子厌学怎么办 孩子抑郁了家长怎么办 大人得地图舌怎么办