Chinaunix首页 | 论坛 | 博客
  • 博客访问: 328400
  • 博文数量: 85
  • 博客积分: 3433
  • 博客等级: 中校
  • 技术积分: 844
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-29 01:11
文章分类

全部博文(85)

文章存档

2013年(1)

2012年(12)

2011年(13)

2010年(59)

我的朋友

分类: LINUX

2010-10-31 16:42:20

Linux设备模型

 

 

看了一段时间的驱动编程,从LDD3的hello wrod到后来的字符设备以至于更加复杂的驱动,越看越是觉得对linux驱动的结构不清楚,越看越是迷糊。于是就停下脚步搜索一下资料理一下头绪:

以下四个方面来总结一些内容:
1.底层数据结构:kobject,kset.
2.linux设备模型层次关系:bus_type,device,device_driver.
3.集成:PCI设备驱动模型实例及设备,设备驱动注册源码的简单分析.
4.面向对象的思想在linux设备模型中的应用分析.

一、底层数据结构:kobject,kset
先说说模型的意义:
总体来说是为了系统地管理所有设备。


在具体实现方面分两个层次:
一是底层数据结构来实现基本对象及其层次关系:kobjects和ksets。
二是基于这两个底层数据结构上实现的设备模型:总线,设备,驱动。

kobject  

 

结合面向对象的思维。这个kobject属于最基础的结构,也就是最高抽象层(有点像java中的Cobject类)。任何一个设备模型如总线,设备,驱动都属于一个kobject 。在实现上这种派生关系就是在结构体中包含一个kobject的变量。

这个在层次上处理最顶层的kobject结构提供了所有模型需要的最基本的功能:
引用计数  用于内核维护其存在与消亡
sysfs表示  每个sys/下的对象对应着一个kobject。
热拔插事件处理。处理设备的热拔插事件。

Kobjects 在内核中对应有一套申请,初始化,添加,注册,计数操作,释放等函数
struct kobject {
 const char  k_name; 
 char   name[KOBJ_NAME_LEN];
 struct kref  
kref; 计数
 struct list_head entry; 用于连接到同类kobjects的链表
 struct kobject  parent;  用于实现层次,指向其父对象。
 struct kset  kset; 用于实现层次,所属的集合
 struct kobj_type 
ktype;  指向对象的类型。
 struct dentry  dentry;  指示在sysfs 中的目录项
 wait_queue_head_t poll;
}; (linux 2.6.18) 

Kset 和kobj_type 

Kset 在概念上是一个集合或者叫容器。实现了对象的层次。所有属于一个ksets的对象(kobject)的parent都指向该ksets的kobj.同时这个对象都连接到kset 的list表上。同时位于ksets层次之上的是subsys,在最新的内核中已经取消subsys,因为它本质上也就是一个ksets。Kset有一套类似kobject的操作,实现上只是进一步调用其自身kobj的相应操作,毕竟ksets本质上也是一个kobject。

struct kset {
 struct subsystem 
subsys;  在最新内核中已经没有subsys概念了。统一用ksets
 struct kobj_type ktype;   类型。
 struct list_head list;    同一kset的链表
 spinlock_t  list_lock;
 struct kobject  kobj; 
自身的kobjects
 struct kset_uevent_ops 
uevent_ops;
};(linux 2.6.18)

 最后 属于同一个集合的对象可以拥有共同的属性:ktype 

struct kobj_type {
 
void (*release)(struct kobject *);
 struct sysfs_ops 
sysfs_ops;
 struct attribute 
** default_attrs;
};
所谓的属性更具体一点说就是一些键值对。并且在sysfs_ops中的show函数被文件系统调用来显示sys/下面对应入口各属性的值。

如此 ,kobjects与ksets实现层次树的底层骨架。
进一步地,通过封装这些底层结构来实现上层的设备驱动模型。
内核设备驱动模型层次划分三个方面:总线,设备,驱动。

二、linux设备模型层次关系:bus_type,device,device_driver

基本关系简要的概括如下:
驱动核心可以注册多种类型的总线。
每种总线下面可以挂载许多设备。(通过kset devices)
每种总线下可以用很多设备驱动。(通过包含一个kset drivers)}
每个驱动可以处理一组设备。

这种基本关系的建立源于实际系统中各种总线,设备,驱动结构的抽象。

下面看看三者数据结构的定义。

首先是总线,bus_type.
struct bus_type {
 const char  * name;

 struct subsystem subsys;//代表自身
 struct kset  drivers;   //当前总线的设备驱动集合
 struct kset  devices; //所有设备集合
 struct klist  klist_devices;
 struct klist  klist_drivers;

 struct bus_attribute * bus_attrs;//总线属性
 struct device_attribute * dev_attrs;//设备属性
 struct driver_attribute * drv_attrs;

 int  (*match)(struct device * dev, struct device_driver * drv);//设备驱动匹配函数
 int  (*uevent)(struct device *dev, char **envp,  
      int num_envp, char *buffer, int buffer_size);//热拔插事件
 int  (*probe)(struct device * dev);
 int  (*remove)(struct device * dev);
 void  (*shutdown)(struct device * dev);
 int  (*suspend)(struct device * dev, pm_message_t state);
 int  (*resume)(struct device * dev);
};
这是2.6.18的定义。源码能说明一切。下面是设备device的定义:

struct device {

struct device  * parent; //父设备,一般一个bus也对应一个设备。
struct kobject kobj;//代表自身
char bus_id[BUS_ID_SIZE]; 
struct bus_type * bus;  
struct device_driver *driver; 

void  *driver_data; 
 void  *platform_data; 

///更多字段忽略了

};

下面是设备驱动定义:

struct device_driver {
 const char  * name;
 struct bus_type  * bus;//所属总线

 struct completion unloaded;
 struct kobject  kobj;//代表自身
 struct klist  klist_devices;//设备列表
 struct klist_node knode_bus;

 struct module  * owner;

 int (*probe) (struct device * dev);
 int (*remove) (struct device * dev);
 void (*shutdown) (struct device * dev);
 int (*suspend) (struct device * dev, pm_message_t state);
 int (*resume) (struct device * dev);
};

OK。基本的东西弄明白了。通过PCI驱动中设备模型的实例来看看细节。

阅读(1157) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-11-01 14:16:51

基本没有看明白 但是支持下

chinaunix网友2010-10-31 19:21:30

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com