从事Mac的应用程序开发已经有很长一段时间了,但对于Mac下的内核层编程却一直处于空白状态,每次看到那些写内核扩展的大牛,我都无比崇拜,所以最近下决心来学习学习这方面的知识,同时计划一边学习一边在博客上写心得,加深记忆的同时也希望与大家一同交流,如遇大神路过请一定记得点拨一二~~~
好了,废话不多说了,直接打开Xcode准备进入写代码的节奏,Xcode本身就已经提供了内核扩展和内核驱动的模板,如图:
第一个框中的模板就是内核扩展,第二个框中的模板是驱动模板,他们的区别就是内核扩展会随系统运行而加载,而驱动会因为特定的硬件才会被加载,我们先创建一个内核扩展的工程,然后工程名为TestExtension,然后可以看到工程中会自动创建一个TestExtension.C的文件,并且已经生成了两个方法,如下:
|
|
这两个方法分别会在扩展加载时和卸载时调用,你可能会觉得好奇系统怎么会知道这两个方法的名字呢?其实秘诀就是在工程的配置文件中有两个属性,所以也可以手动去修改这两个方法名并与这两个属性相对应即可,如图:
并注意Info.plist文件中OSBundleLibraries项下面的com.apple.kpi.libkern属性,它对应的是系统内核的版本,你可以通过在命令行中输入uname -r来查看,比如10.9的内核版本为13.0.0。
至此,一个最最简单的内核扩展就已经完成了,编译工程,到build目录下找到编译的后的TestExtension.kext文件,下一步就是怎样加载它了,内核扩展要求文件的所有者是root,用户组是wheel,所以你可以在命令行下通过以下的命令修改文件所有者:
|
|
然后通过以下的命令加载内核扩展:
|
|
此时你可以通过控制台程序Console查看到“TestExtension Start!”的输出,说明我们编写的该扩展已经能够正常工作了,在Mac下内核扩展通常都放在/System/Library/Extensions目录下面,所以也建议加载前先将TestExtension.kext移动到该目录。
如果需要卸载该内核扩展,使用以下的命令即可:
|
|
同时在控制台也就能看到“TestExtension Stop!”的输出了。
文章相关的Demo示例下载:TestExtension.zip