深入解析Mac OS X & iOS 操作系统 学习笔记

2016-11-16  本文已影响627人  CoderKo1o

I/OKit驱动程序框架

和其他操作系统不同,XNU的独特之处在于为设备驱动程序提供了一个完整的运行时环境。XNU的设备驱动程序运行时环境称为I/O Kit,是一个苹果开发的一个私有组件。I/O Kit为开发者提供了面向对象的强大能力,主要包括子类化和方法重写,通过这些特性使得设备驱动程序的开发过程非常高效。

I/O Kit 还提供了一组用户态的API:I/O Kit Framework,这个框架提供了一些更高级的特性,例如内核态通知以及内核态和用户态之间的双向通信。

I/O Kit 简介

I/OKit 的设计非常独特。尽管所有的操作系统肯定都有设备驱动程序,但是大部分都是完全用C语言编写的,没有自己的运行时环境。但是没有一个能够像I/OKit 这样提供面向对象的开发环境。

I/OKit 是什么
I/OKit 不是什么

libkern:I/O Kit的基类

libkern C++运行时是I/OKit的基础,定义了所有I/O Kit驱动程序都可以使用的基础类。libkern中的基础类和CoreFundation中的一些功能上有交集,这些基础类定义在XNU的libkern/libkern/c++目录中,实现在libkern/c++中,一个类对应一个文件。这个目录下还包含了其它支持文件(OSRuntime.c和OSRuntineSupport.cpp),里面包含了libkern初始化的代码,以及序列化函数(OSSerialize/OSUnserialize)的代码。序列化/反序列化操作作用于向/从XML属性列表中写入/读取对象。

OSObject

I/OKit 中所有类都会追溯到一个祖宗,那就是OSObject。

OSMetaClass

I/O Kit 并不支持标准C++的Run Time Type Identifation(RTTI)。但是I/O Kit 提供了一个同样强大的机制:OSMetaClass类。这是一个抽象类,不能直接使用。需要通过一些特殊的宏来实现RTTI的特性。这些宏包括:

I/O Kit Registry

I/O Kit 维护了一个保存了所有对象及对象间关系最新信息的数据库。这个数据库在内存中,出纳岗位I/O Registry 。 I/O Registry 是一个多平面的数据库。简单地说,I/O Registry 表示的是三维的关系。

IORegistryEntry

I/O RegistryEntry 类是I/O Registry 中所有对象的父类。I/O RegistryEntry 是一个包含了对象属性的简单容器,对象的属性保存了一个OSDictionary 对象中。这个类不应该直接继承。I/O Kit 对象的父类是IOService,即IORegistryEntry的子类。通过继承关系,所有的驱动程序也自动注册了。

IOService

IOService是IORegistryEntry的直接后代也是唯一后代。IOService也是所有驱动程序()包括苹果提供的驱动程序以及第三方的驱动程序)的祖先,尽管大部分驱动程序不是直接继承于IOService,但是IOService仍然是这些驱动程序的最终祖先。这些驱动程序从IOSevice继承了一组可以直接使用的方法(例如电源管理和中断处理等),在有些情况下还需要实现一些方法(例如驱动程序标准的回调函数)。

用户态的I/O Kit

I/O Kit 可以通过IOKit.Framework提供的API以及IOKitLib API 和 用户态通信。这个框架就是给用户态使用的。内核态的I/O Kit组件使用的是Kernel.Framework的IOKit/子目录。用户态应用程序可以通过这些API和内核中的I/O Kit 驱动程序以及I/O Kit组件(最重要的是I/O Registry)本身做接口。
所有的I/O Kit 都依赖一个特殊的主机端口,I/O Kit 通过IOMasterPort( )获得并引用这个端口。用户态和I/O Kit内核组件以及驱动程序之间的通信是通过Mach 消息进行的。

访问I/O Registry

有了Master Port,应用程序就可以无限量地发送I/O Kit 请求了。通常情况下有很多请求都涉及查询I/O Reigstry。

获得/设置驱动程序属性

由于在I/O Kit 模型设备驱动程序中都是对象,因此有自己的属性。这些属性在用户态都是可见的,而且可以通过用户态的客户程序访问甚至修改。可以通过以下几个函数进行属性操作:

即插即用(通知端口)

用户态的应用程序有时会要求I/O Kit发出任何I/O Registry 变化的通知,例如设备到达(添加)和分离(删除),以及某些特定设备的状态变化。这个通知对于即插即用设备的支持非常有用,例如插入i-设备时启动iTunes。
要请求这些通知,客户程序必须首先创建一个通知端口。通过调用IONotificationPortCreate 返回的结果得到IONotificationPort 的引用(即IONotificationPortRef)。这个引用在用户态是不透明的,实际上隐藏了一个Mach端口。通知端口可以通过Mach消息的原语直接监听,不过推荐的使用方法是将通知端口连接到一个运行循环(run loop)结构中。运行循环属于Core Foundation 编程模型,实现了消息循环。当消息到达通知端口时,用户提供的回调函数会被调用。

I/O Kit 电源管理

驱动程序可以注册电源相关的通知,既可以响应系统电源状态的变化,也可以影响系统电源状态的变化。在IOPower 平面上可以找到要求这项功能的驱动程序,而且规模随着对电源依赖性的增加而成本增大。应用程序也可以请求参与到电源管理当中。

I/O Kit 诊断

除了ioreg(8)命令和Xcode 捆绑的IORegistry Explorer外,苹果仅仅提供了另外两个诊断工具:

I/O Kit 内核驱动程序

I/O Kit 驱动程序是从一个公共祖先IOService 继承而来的对象。IOService 下面的继承树非常庞大复杂,顺着这棵树下来,驱动程序越来越具体化,并且只适合驱动程序专用的设备或总线。I/O Kit的驱动可以分为“驱动程序(driver)”和“节点(nub)”。节点简单地说就是两个驱动程序之间的适配器,表示被控制的设备。

驱动程序匹配

I/O Kit 维护了一个Catalogue对象,这个对象是一个保存了所以已知设备驱动程序和注册的驱动程序personality的数据库。I/O Kit 利用驱动程序的personality来匹配驱动程序和新加入的设备。

IOWorkLoop

I/O Kit 采用了NeXT的runloop模型,用户态开发者应该会想到CFRunLoop。I/O Kit 版本的runloop 成为IOWorkLoop,基本思想是一样的:提供一个单线程且现场安全的机制处理所有类型的时间,如果不采用这种机制则是异步的。工作循环的访问被一个互斥体保护,因此不需要开率可重入的问题以及线程安全的问题。

中断处理

尽管有部分设备驱动程序是虚拟设备的驱动程序,但是大部分驱动程序都要面对真实的硬件,因此需要和中断打交道,I/O Kit 想驱动程序开发者隐藏了Mach 的中断处理逻辑,I/O Kit 的这项隐藏做得非常棒,开发者可以很开心地忽略底层细节。开发者不需要陷入中断处理相关的具体细节,I/O Kit 提供了面向对象的中断视图,即高效又直观。

上一篇 下一篇

猜你喜欢

热点阅读