接上文,我们已经通过Xcode自带的模板完成了简单的内核创建到部署的过程,然后我们准备来尝试创建一个驱动程序然后完成布署,上文上已经提到了内核扩展与驱动的差别在于加载的时机不一样,另外他们还有一个很明显的差别,内核扩展是用C来实现的,而Mac的驱动却是用C++去完成的,Mac OSX系统的驱动开发有一套基于C++的IO Kit框架,这也是OSX内核中非常重要的一个部分,在内核开发中使用C++其实只是它的一个子集,嵌入式C++,它不可以使用C++的异常、多继承、模板、运行时等特性,但IO Kit框架为了开发的方便而去实现了类似Cocoa编程中的引用计数、运行时、容器等特性。
当硬件插入电脑时,系统会根据硬件的类型创建一个Provider(提供者)的对象,并且这个Provider会在初使化的过程中去尝试匹配合适的驱动程序,如上图,我们开发一款适合于PCI声卡或USB音频设备的驱动程序,首先硬件载入后会去查找驱动程序Info.plist中的IOKitPersonalities的信息,如果IOProviderClass中定义了IOPCIDriver就表示可以为PCI做匹配,如果同时也有IOUSBDriver项就表示USB的设备也可以做匹配,同时如果有多个支持PCI或USB的驱动出现时,就会去调用驱动程序的probe方法,最终找到匹配度最高的驱动程序进行加载(实际的原理会更复杂),然后该驱动程序就可以通过不同的Provider与硬件通信,并且通过标准的IOAudioDriver接口为系统提供音频的服务,从而用户程序就可以通过系统的标准方法最终让音频设备工作。
好了,直接开始编码,打开Xcode,选择IOKit Driver模板,取名工程名IOKitTest,然后可以在工程中看到会自动创建两个文件,分别是IOKitTest.h和IOKitTest.cpp,但非常遗憾的是,模板并没有为我们在这两个文件中生成任何的内容。我们手动在IOKitTest.h中输入以下内容:
|
|
在IOKitTest.cpp中输入以下的代码:
|
|
至此,程序部分就完成了,但如果需要让驱动程序正常的被加载,我们需要在Info.plist文件中加入必要的项目,如下图:
其中OSBundleLibraries中的两个值对应的是内核中iokit和libkern的版本,此处我们设置内核的版本即可,而IOKitPersonalities就是上文也有提到的,用于匹配驱动程序用,IOProviderClass是需要对应特定类型的,如IOPCIDriver、IOUSBDriver等,但我们这是一个测试程序,不希望去驱动某个特定的硬件,所以指定IOResources就是无需硬件设备。
好了,我们的驱动程序就已经开发完成了,编译后在Build目录中找到IOKitTest.kext文件,如第一篇文章一样,用以下的命令完成文件所有者修改及驱动的加载:
|
|
然后我们在控制台Console中就可以看到依次执行了init,probe,start这三个方法,并且发现在init中打印的dict字典正是Info.plist文件中IOKitPersonalities项所填写的项目。
当在命令行下执行以下操作:
|
|
你会在控制台上收到stop,free的的日志信息。
本文也只是记录了如何创建一个驱动程序的示例,但具体如何通过驱动程序与特定的硬件通信,还未涉及到相关的业务,文章中的示例代码下载:IOKitTest.zip
