linux设备模型浅析
2013-01-01 17:00
288 查看
linux设备模型浅析
2012-10-16 22:22:32| 分类: 默认分类 | 标签:linux设备模型 |字号 订阅说明:基于linux-2.6.30.4的内核源码
一、linux设备模型作用
Linux 2.6内核最初为了应付电源管理的需要,提出了一个设备模型来管理所有的设备。在物理上,外设之间是有一种层次关系的,比如把一个U盘插到笔记本上,实际上这个U盘是接在一个USB Hub上,USB Hub又是接在USB 2.0 Host Controller (EHCI)上,最终EHCI又是一个挂在PCI Bus上的设备。这里的一个层次关系是:PCI->EHCI->USB Hub->USB Disk。如果操作系统要进入休眠状态,首先要逐层通知所有的外设进入休眠模式,然后整个系统才可以休眠。因此,需要有一个树状的结构可以把所有的外设组织起来。这就是最初建立Linux设备模型的目的。
当然,Linux设备模型给我们带来的便利远不止如此。既然已经建立了一个组织所有设备和驱动的树状结构,用户就可以通过这棵树去遍历所有的设备,建立设备和驱动程序之间的联系,根据类型不同也可以对设备进行归类,这样就可以更清晰的去“看”这颗枝繁叶茂的大树。另外,Linux驱动模型把很多设备共有的一些操作抽象出来,大大减少了重复造轮子的可能。同时Linux设备模型提供了一些辅助的机制,比如引用计数,让开发者可以安全高效的开发驱动程序。达成了以上这些好处之后,我们还得到了一个非常方便的副产品,这就是sysfs----一个虚拟的文件系统。sysfs给用户提供了一个从用户空间去访问内核设备的方法,它在Linux里的路径是/sys。
二、linux设备模型的构成
linux设备模型对外封装后提供给我们使用的一般是:struct bus_type(总线),struct device(设备),struct device_driver (驱动)这三个结构体:即经典的总线、设备、驱动模型。
每个bus_type对象都对应/sys/bus目录下的一个子目录,如PCI总线类型对应于/sys/bus/pci。在每个这样的目录下都存在两个子目录:devices和drivers(分别对应于bus type结构中的devices和drivers域)。其中devices子目录描述连接在该总线上的所有设备,而drivers目录则描述与该总线关联的所有驱动程序。与device_driver对象类似,bus_type结构还包含几个函数(match()、hotplug()等)处理相应的热插拔、即插即拔和电源管理事件。
系统中的任一设备在设备模型中都由一个device对象描述。内核提供了相应的函数用于操作device对象。其中device_register()函数将一个新的device对象插入设备模型,并自动在/sys/devices下创建一个对应的目录。device_unregister()完成相反的操作,注销设备对象。get_device()和put_device()分别增加与减少设备对象的引用计数。通常device结构不单独使用,而是包含在更大的结构中作为一个子结构使用,比如描述PCI设备的struct
pci_dev结构体里面就内嵌一个struct device。
系统中的每个驱动程序由一个device_driver对象描述。与device 结构类似,device_driver对象依靠内嵌的kobject对象实现引用计数管理和层次结构组织。内核提供类似的函数用于操作device_driver对象,如get_driver()增加引用计数,driver_register()用于将一个新的driver对象插入设备模型,并自动在/sys/drivers下创建一个对应的目录。device_driver()结构还包括几个函数,用于处理热拔插、即插即用和电源管理事件。
三、linux设备模型的操作流程
1、注册总线:总线是设备和驱动挂载的地方,总线中有加入该总线的设备列表和驱动列表,这些用于管理加入总线中的设备。
2、向设备模型(总线)中加入设备/驱动:加入设备使用device_register(device_add将被调用),加入驱动一般使用driver_register(driver_add被调用)。
3、设备和驱动的首次匹配:加入新的设备/驱动后,会导致总线的match函数被调用,用来检查这个新加入的设备/驱动,在总线已有的驱动/设备中有没有跟它匹配的。
4、驱动的probe函数的再次检查:在总线的match函数匹配成功后会调用驱动的probe探测函数做进一步细致的匹配工作。如果不出什么问题,这个驱动/设备就算成功加入到这个总线当中(设备模型)。
struct bus_type {
const char *name;//总线的名称
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, struct kobj_uevent_env *env);
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 (*suspend_late)(struct device *dev, pm_message_t state);
int (*resume_early)(struct device *dev);
int (*resume)(struct device *dev);//电源管理:恢复
struct dev_pm_ops *pm;
struct bus_type_private *p;//总线的私有数据
};
struct device {
struct device *parent; //设备的父设备
struct device_private *p;//设备的私有数据
struct kobject kobj;
const char *init_name;
struct device_type *type;//设备的类型
struct semaphore sem;//信号量,用于同步访问驱动
struct bus_type *bus; //设备挂接的总线的类型
struct device_driver *driver; //设备的驱动
void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device core doesn't touch it */
struct dev_pm_info power;
#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask ;
struct device_dma_parameters *dma_parms;
struct list_head dma_pools; /* dma pools (if dma'ble) */
struct dma_coherent_mem *dma_mem;
struct dev_archdata archdata;
dev_t devt; //设备号,驱动程序的号码
spinlock_t devres_lock;
struct list_head devres_head;
struct klist_node knode_class;
struct class *class;
struct attribute_group **groups; /* optional groups */
void (*release)(struct device *dev);
}
struct device_driver
{
const char *name;//驱动的名字
struct bus_type *bus; //驱动挂接的总线
struct module *owner;
const char *mod_name; /* used for built-in modules */
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);
struct attribute_group **groups; //驱动支持的设备集合(推测)
struct dev_pm_ops *pm;
struct driver_private *p;
};
相关文章推荐
- linux设备模型浅析
- Linux 设备模型浅析之 uevent 篇
- Linux设备模型浅析之uevent篇图片版
- Linux设备模型浅析之设备
- Linux 设备模型浅析之 uevent 篇(2)
- Linux设备模型浅析之uevent篇文字版
- Linux设备模型浅析之uevent篇
- Linux设备模型浅析之驱动篇
- Linux设备模型浅析之固件篇
- Linux设备模型浅析之uevent篇
- linux 设备模型浅析
- Linux 设备模型浅析之 uevent 篇
- Linux内核平台总线设备驱动模型浅析
- Linux 设备驱动模型中的class(类)
- linux设备模型____I2C具体实现
- Linux驱动之设备模型(7)
- 转一篇关于linux设备模型的好文章
- linux设备模型与sys文件系统
- Linux设备模型分析之bus
- Linux设备模型之tty驱动架构分析