字符设备的内核抽象[转]

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

<include/linux/cdev.h>

复制代码
 1 struct cdev {
 2 
 3        struct kobject kobj;
 4 
 5        struct module *owner;
 6 
 7        const struct file_operations *ops;
 8 
 9        struct list_head list;
10 
11        dev_t dev;
12 
13        unsigned int count;
14 
15 };
复制代码

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

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>

复制代码
 1 struct cdev *cdev_alloc(void)
 2 
 3 {
 4 
 5        struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
 6 
 7        if (p) {
 8 
 9               INIT_LIST_HEAD(&p->list);
10 
11               kobject_init(&p->kobj, &ktype_cdev_dynamic);
12 
13        }
14 
15        return p;
16 
17 }
复制代码

 

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

复制代码
 1 struct my_keypad_dev{
 2 
 3        //硬件相关的成员变量
 4 
 5        int a;
 6 
 7        int b;
 8 
 9        int c;
10 
1112 
13        //内嵌的struct cdev数据结构
14 
15        struct cdev cdev;
16 
17 };
复制代码

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

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

 

 

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

<fs/char_dev.c>

复制代码
 1 void cdev_init(struct cdev *cdev, const struct file_operations *fops)
 2 
 3 {
 4 
 5        memset(cdev, 0, sizeof *cdev);
 6 
 7        INIT_LIST_HEAD(&cdev->list);
 8 
 9        kobject_init(&cdev->kobj, &ktype_cdev_default);
10 
11        cdev->ops = fops;
12 
13 }
复制代码

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

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

 

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

图书详细信息:http://blog.chinaunix.net/space.php?uid=13164110&do=blog&id=3078991

本 PPT 介绍了制药厂房中供配电系统的总体概念与设计要点,内容包括: 洁净厂房的特点及其对供配电系统的特殊要求; 供配电设计的一般原则与依据的国家/行业标准; 从上级电网到工厂变电所、终端配电的总体结构与模块化设计思路; 供配电范围:动力配电、照明、通讯、接地、防雷与消防等; 动力配电中电压等级、接地系统形式(如 TN-S)、负荷等级与可靠性、UPS 配置等; 照明的电源方式、光源选择、安装方式、应急与备用照明要求; 通讯系统、监控系统在生产管理与消防中的作用; 接地与等电位连接、防雷等级与防雷措施; 消防设施及其专用供电(消防泵、排烟风机、消防控制室、应急照明等); 常见高压柜、动力柜、照明箱等配电设备案例及部分设计图纸示意; 公司已完的典型项目案例。 1. 工程背景与总体框架 所属领域:制药厂房工程的公用工程系统,其中本 PPT 聚焦于供配电系统。 放在整个公用工程中的位置:与给排水、纯化水/注射用水、气体与热力、暖通空调、自动化控制等系统并列。 2. Part 01 供配电概述 2.1 洁净厂房的特点 空间密闭,结构复杂、走向曲折; 单相设备、仪器种类多,工艺设备昂贵、精密; 装修材料与工艺材料种类多,对尘埃、静电等更敏感。 这些特点决定了:供配电系统要安全可靠、减少积尘、便于清洁和维护。 2.2 供配电总则 供配电设计应满足: 可靠、经济、适用; 保障人身与财产安全; 便于安装与维护; 采用技术先进的设备与方案。 2.3 设计依据与规范 引用了大量俄语标准(ГОСТ、СНиП、SanPiN 等)以及国家、行业和地方规范,作为设计的法规基础文件,包括: 电气设备、接线、接地、电气安全; 建筑物电气装置、照明标准; 卫生与安全相关规范等。 3. Part 02 供配电总览 从电源系统整体结构进行总览: 上级:地方电网; 工厂变电所(10kV 配电装置、变压
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值