内核扩展使用的Info.plist属性

内核在加载kext扩展和驱动时需要了解驱动的一些属性,例如这个驱动能够驱动哪个设备等等。

顶层属性

CFBundleIdentifier

CFBundleIdentifier属性唯一的标识你的kext。如果两个kext的CFBundleIdentifier相同,那么它们不能被同时加载到内核中。这个属性的值应该使用reverse-DNS形式。

CFBundleExecutable

指定可执行文件的名字。Xcode生成的模版中,这个值是一个Xcode变量,在编译时由Xcode自动生成。如果你的kext,诶呦代码,那么可以不写这个属性。

CFBundleVersion

定义kext的版本。kext版本号必须遵守严格的格式:

  • 版本号必须用句号分隔为三段,例如,3.1.2
    • 主版本号,最长为四位数字
    • 最近的重大修正,最长为两位数字
    • 最近的次要bug修正,最长为两位数字,如果第三个部分是0,那么你可以不写它和它前面的那个句点
  • 在开发新版本的过程中,请在版本号中添加一个后缀,例如3.1.3a1。这个后缀中的字母表示软件所处的开发阶段,例如,d代表development、a代表alpha、b代表beta、fc代表final candidate;后缀字母后面的数字代表构建版本build version,这个数字不应该超过255。当你的软件正式发布时,请移除这个后缀。

OSBundleLibraries

是一个字典,列出了了kext需要链接到的库。key是所依赖库的CFBundleIdentifier,value是所需的kext的版本。可以使用kextlibs命令行工具来查看一个kext所依赖的库。

OSBundleRequired

如果存在这个属性,表示你的kext必须在early boot阶段被加载;如果没有这个属性,表示这个kext不能再early boot阶段被加载。这个属性的取值如下:

  • Root:这个kext是挂载root文件系统所需的,不区分root来自哪里(见下面两条)
  • Network-Boot:如果root位于远端卷(remote volume,例如NFS)上,那么在挂载root文件系统前必须加载这个kext
  • Local-Root:如果root位于本地卷(local volume,例如本地磁盘),那么在挂载root文件系统前必须加载这个kext
  • Console:这个kext是字符控制台(single-user mode)所必需的的,例如键盘驱动
  • Safe Boot:即使在safe-boot模式(不回家再非必须的kext)下,也要加载这个kext

OSBundleCompatibleVersion

指出当前版本的kext最多同哪个早期版本兼容,它的格式同CFBundleVersion相同。

OSBundleAllowUserLoad

表示允许非root的用户来加载这个kext。I/O Kit驱动永远不应该添加这个属性,因为它们是由内核自动加载的。

OSBundleEnableKextLogging

表示是否将这个kext的log记录到/var/log/kernel.log中。kextutil工具会为了方便调试自动启用这一选项。

IOKitPersonalities

这个属性用于I/O Kit驱动。它的内容是一个嵌套的字典,描述了这个kext可以驱动什么样的硬件设备。

IOClass

这里的值是一个C++的类名,这个类会在这个驱动程序kext匹配到一个nub上时被加载。

IOKitDebug

开启后,I/O Kit相关的事件(例如attaching、matching、probing)会被记录到/var/log/kernel.log内。具体记录哪些事件由这个属性的值来规定,参见IOKitDebug.h,65535表示记录所有的事件。

IOProviderClass

这里的值是一个C++的类名,它是你的驱动程序所能匹配到的I/O Kit设备对象。通常,这个名字是你的设备连接到的nub的名字,例如,如果你的驱动程序连接到PCI总线,那么你就应该指定IOPCIDevice作为IOProviderClass。也就是说,这个属性用来约束这个驱动能连到什么nub上。

IOMatchCategory

FIXME:等掌握了provider的publish和driver的匹配过程后再来理解

背景知识:

  1. 所有没有IOMatchCategory属性的驱动程序都被认为属于同一个默认category。
  2. 只要每个client的category各不相同,就可以连接多个client到同一个provider;否则就只能一个client连接一个provider。

这个属性允许多个驱动程序匹配到同一个provider类(也就是IOProviderClass属性规定的),只要他们的IOMatchCategory属性值都不重复。通常,只有一个驱动能匹配到一个指定的provider类。 这个属性的值要同CFBundleIdentifier一致,只不过是要把句点“.”替换为下划线“_”,例如,"com_MyCompany_driver_MyDriver"。其实这个规则不是强制的,你只要保证你的名字唯一即可。

IOResourceMatch

你可以用IOResourceMatch属性来声明你的kext依赖于哪些资源,例如依赖于BSD内核,或者某些设备上的某些特殊资源(如audio video jack)。如果你设置了这个属性,那么只有在这些依赖关系满足时才会加载你的驱动。

同架构相关的属性

在plist文件最上层的属性中,那些以OS或者IO开头的属性有同架构先关的属性版本,也就是说,你可以为不同的架构定义同一属性的不同的值,从而为不同的架构定义不同的行为。在属性名字的后面加上架构的名字作为后缀,得到的就是它的同架构相关的属性。例如,可以为OSBundleCompatibleVersion定义同架构相关的属性OSBundleCompatibleVersion_x86_64和OSBundleCompatibleVersion_i386