字符设备的内核抽象

Linux内核中处处体现面向对象的设计思想,为了统一形形色色的设备,Linux系统将设备分为三类:字符设备、块设备、网络设备。并将其分别抽象为struct cdev,struct block_device,struct net_devce三个对象,具体的设备都可以包含着三种对象从而继承和三种对象属性和操作,并通过各自的对象添加到相应的驱动模型中,从而进行统一的管理和操作。
顾名思义,字符设备驱动程序管理的是核心对象是字符设备。从字符设备的设计框架角度出发,内核为字符设备抽象出了一个具体的数据结构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
文件操作,是字符设备驱动中非常重要的数据结构,在应用程序通过文件系统(VFS)呼叫到设备设备驱动程序中实现的文件操作类函数过程中,ops起着桥梁纽带作用,VFS与文件系统及设备文件之间的接口是file_operations结构体成员函数,这个结构体包含了对文件进行打开、关闭、读写、控制等一系列成员函数。
struct list_head list
用于将系统中的字符设备形成链表(这是个内核链表的一个链接因子,可以再内核很多结构体中看到这种结构的身影)。
dev_t dev
字符设备的设备号,有主设备和次设备号构成。
unsigned int count
属于同一主设备好的次设备号的个数,用于表示设备驱动程序控制的实际同类设备的数量。

以下是具体设备与cdev的关系:
这里写图片描述

我们知道了具体的字符设备可以通过cdev来管理字符设备,那么我们如何能够在驱动中通过cdev来找到我们具体的设备呢?C语言中没有面向对象语言的继承的语法,但是我们可以通过结构体的包含来实现继承,例如一个字符设备adc_dev 结构体如下(这个一个能够进行ad采集设备):

struct adc_dev {
    unsigned int __iomem *adccon;
    unsigned int __iomem *adcdat;
    unsigned int __iomem *clrint;
    unsigned int __iomem *adcmux;

    unsigned int adcval;
    struct completion completion;
    atomic_t available;
    unsigned int irq;
    struct cdev cdev;
};

可以看到,这个设备结构体中包含着操作此设备的内存信息、中断信息等,其中就嵌入了cdev结构体,然后通过字符设备的驱动框架就可以将此设备注册进Linux系统。
一般在驱动中我们很容易就能知道cdev指针的值,那么我们可以通过cdev来找到设备结构体adc_dev,内核提供了如下的宏接口:

#define container_of(ptr, type, member) ({          \
    const typeof(((type *)0)->member) * __mptr = (ptr); \
    (type *)((char *)__mptr - offsetof(type, member)); })

此接口的具体实现在这不在赘述,详见内核链表相关文章。
现在我们来使用此接口获得我们的设备结构体:
int adc_open(struct inode *inode,struct file *filep)
{
struct adc_dev adc_devp;
adc_devp = container_of(inode->i_cdev, struct cdev, cdev);

return 0;
}

非常简单是不是,其中container_of接口的ptr是内嵌的cdev的内存地址,type为数据类型此处为struct cdev,member为内嵌的成员名此处为cdev。
由于Linux系统要管理成百上千中设备,所以这种抽象非常重要且有必要,它提取并抽象了设备的共性,为上层提供统一接口,使得管理和操作设备变的容易。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值