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

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 提供了一些对于Mach API的封装的API,这些API用于线程创建、内存分配和一些通用任务

  • 一个面向对象的开发环境:I/OKit 驱动程序是从继承于OSObject类实例化来的。开发者可以找到和自己要写的驱动程序最接近的那个类,然后从这个类开始实现自己的类,有效地重用这个类的通用部分的代码

  • 一个特别为驱动程序而设计的开发环境:I/O Kit 为很多操作设备特别要考虑的问题提供了支持,主要包括即插即用和电源管理;另一个重要的架构思想是驱动程序堆叠(driver layering),允许为一个设备驱动构建在另一个设备驱动的基础之上

  • ** 一个工作循环驱动的开发环境**:I/O Kit 提供了一个工作循环(work loop)模型,工作循环是一个不断处理事件的消息循环。通常使用工作循环可以极大简化了并发问题,而且通常可以避免对锁的使用,锁是会影响性能的

  • 一个基于注册表的开发环境:I/O Kit 中的所有东西都是要记账的:对象需要引用计数,类需要注册等,所有这些信息都通过I/O Registry(I/O 注册表)管理。I/O Kit Registry 是一个多层的层次化数据库,跟踪对象以及对象之间的相互关系

  • 一个用户态友好的开发环境:I/O Kit 提供了用户态可以访问的API,而且完全由用户态实现一些驱动程序,例如USB 设备的驱动程序就是完全在用户态实现的。I/O Kit 注册表也可以在用户态访问,因此用户态可以硬件配置和参数信息

  • 一个通过C++子集实现的开发环境:I/O Kit 是基于C++的,所以I/OKit 利用了一些C++语言有用的编译时特性,例如:

  • 名称空间:I/O Kit 驱动程序可以通过C++名称空间将自己的函数和符号包装起来,避免内核中全局的符号突出

  • 名称重整(name mangling ):I/O Kit 的符号名称是经过重新整过的,其中在函数名称中包含了C++层面的原型信息(名称空间、返回值和参数)

I/OKit 不是什么
  • 一个完整的C++开发环境:I/O Kit 没有使用以下特性:

  • 模版

  • 异常

  • 标准的构造函数

  • 一套全功能的API:由于没有完整的C++运行时库,所以所有的运行时库功能都是通过libkern库提供的。为了完整地兼容I/O Kit,开发者应该仅仅使用libkern中的API

  • 最灵活的编程模型:I/O Kit 驱动程序必须实现一个非常具体的生命周期,因此和其它操作系统中众所周知的驱动程序回调函数有严重的不同。驱动程序的生命周期非常复杂,开发者要清楚在什么条件下必须实现什么回调函数

  • 代码可以搞定一切:I/OKit 驱动程序不仅仅是二进制程序。作为内核扩展,还必须包含一个Info.plist文件。由于是I/O Kit 驱动程序,所以Info.plist文件必须包含I/O Kit相关的指令,如果没有这些指令的话,驱动程序就无法正常工作

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的特性。这些宏包括:

  • OSDeclareDefaultStructors:用于生产I/O Kit 对象默默认构造和析构函数的原型。

  • OSDefinwMetaClassAndStructors:类似地,这个宏用在类的实现中。抽象类使用OsDefineMetaClassAndStructors:这两个类都可以添加WithInit后缀,得到的还是包含初始化函数的宏。

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 模型设备驱动程序中都是对象,因此有自己的属性。这些属性在用户态都是可见的,而且可以通过用户态的客户程序访问甚至修改。可以通过以下几个函数进行属性操作:

  • IORegistryEntryCreateCFProperties( ):获取驱动程序完整属性表的拷贝
  • IORegistryEntryCreatepProperty( ):通过名字访问某一个属性
即插即用(通知端口)

用户态的应用程序有时会要求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外,苹果仅仅提供了另外两个诊断工具:

  • ioalloccount(8):显示I/O Kit 分配的内存消耗
  • ioclasscount(8):计算所有注册的I/O Kit 类及子类的实例数,提供的是积累的计数

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 提供了面向对象的中断视图,即高效又直观。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容