Chinaunix首页 | 论坛 | 博客

分类: BSD

2012-04-12 04:45:44

    Mac OS 内核是基于BSD的,所以很多地方和BSD的内核是一样的,但是也有很多不同的地方,Mac OS为了用户开发方便做了很多封装。这篇文章将介绍如何使用XCode开发一个最简单的内核扩展模块。这篇文章的内容来自《Kernel Extension Programming Topics》。
Creating a Generic Kernel Extension with Xcode

In this tutorial, you learn how to create a generic kernel extension (kext) for Mac OS X. You create a simple kext that prints messages when loading and unloading. This tutorial does not cover the process for loading or debugging your kext—see “Debugging a Kernel Extension With GDB” after you have completed this tutorial for information on loading and debugging.

If you are unfamiliar with Xcode, first read A Tour of Xcode.

Road Map

These are the four major steps you follow:

  1. “Create a New Project”

  2. “Implement the Start and Stop Functions”

  3. “Add Library Declarations”

  4. “Prepare the Kernel Extension for Loading”

This tutorial assumes that you are logged in as an administrator of your machine, which is necessary for using the sudo command.

Create a New Project

Creating a kext project in Xcode is as simple as selecting the appropriate project template and providing a name.

  1. Launch Xcode.

  2. Choose File > New > New Project. The New Project panel appears.

  3. In the New Project panel, select System Plug-in from the list of project categories on the left. Select Generic Kernel Extension from the list of templates on the right. Click Next.

  4. In the screen that appears, enter MyKext for the product name, enter a company identifier, and click Next.

  5. Choose a location for the project, and click Create.

    Xcode creates a new project and displays its project window. You should see something like this:The new project contains several files, including a source file, MyKext.c, that contains templates for the kext’s start and stop functions.

    6. Make sure the kext is building for the correct architectures.
    1. (If you don’t see the screen above, select MyKext under Targets. Select the Build Settings tab. Click the disclosure triangle next to Architectures.)

      Next to Build Active Architecture Only make sure to select No—this is especially important if you are running a 32-bit kernel on a 64-bit machine.

    Implement the Start and Stop Functions

    Now that you’ve created the project, it’s time to make your kext do something when it gets loaded and unloaded. You’ll do so by adding code to your kext’s start and stop functions, which are called when your kext is loaded and unloaded.

    Implement the Start and Stop Functions

    Open MyKext.c to edit the start and stop functions.

    Figure 1 shows the unedited file.

    Figure 1  Viewing source code in Xcode

    The default start and stop functions do nothing but return a successful status. A real kext’s start and stop functions typically register and unregister callbacks with kernel runtime systems, but for this tutorial, your kext simply prints messages so that you can confirm when your kext has been started and stopped.

    2. Edit MyKext.c to match the code in Listing 1.



    Listing 1  MyKext.c file contents

    点击(此处)折叠或打开

    1. #include <sys/systm.h>

    2. #include <mach/mach_types.h>

    3.  

    4. kern_return_t MyKext_start (kmod_info_t * ki, void * d)

    5. {

    6.     printf("MyKext has started.\n");

    7.     return KERN_SUCCESS;

    8. }

    9.  

    10. kern_return_t MyKext_stop (kmod_info_t * ki, void * d)

    11. {

    12.     printf("MyKext has stopped.\n");

    13.     return KERN_SUCCESS;

    14. }

  6. Notice that MyKext.c includes two header files, and . Both header files reside in Kernel.framework. When you develop your own kext, be sure to include only header files from Kernel.framework (in addition to any header files you create), because only these files have meaning in the kernel environment. If you include headers from outside Kernel.framework, your kernel extension might compile, but it will probably fail to load or run because the functions and services those headers define are not available in the kernel.

  7. Save your changes by choosing File > Save.

Edit the Information Property List

Like all bundles, a kext contains an information property list, which describes the kext. The default Info.plist file created by Xcode contains template values that you must edit to describe your kext.

A kext’s Info.plist file is in XML format. Whenever possible, you should view and edit the file from within Xcode or within the Property List Editor application. In this way, you help ensure that you don’t add elements (such as comments) that cannot be parsed by the kernel during early boot.

Click Info.plist in the Xcode project window.

Xcode displays the Info.plist file in the editor pane. You should see the elements of the property list file, as shown in Figure 2.

Figure 2  MyKext Info.plist
  1. By default, Xcode’s property list editor masks the actual keys and values of a property list. To see the actual keys and values, Control-click anywhere in the property list editor and choose Show Raw Keys/Values from the contextual menu.

  2. Change the value of the CFBundleIdentifier property to use your unique namespace prefix.

    On the line for CFBundleIdentifier, double-click in the Value column to edit it. Select com.yourcompany and change it to com.MyCompany (or your company’s DNS domain in reverse). The value should now be com.MyCompany.kext.${PRODUCT_NAME:rfc1034identifier}.

    Bundles in Mac OS X typically use a reverse-DNS naming convention to avoid namespace collisions. This is particularly important for kexts because all loaded kexts share a single namespace for bundle identifiers.

    The last portion of the default bundle identifier, ${PRODUCT_NAME:rfc1034identifier}, is replaced with the Product Name build setting for the kext target when you build your project.

  3. Save your changes by choosing File > Save.

Build the Kernel Extension

Now you’re ready to configure your build settings and build your kext to make sure the source code compiles. First, configure your build settings to build the kext for every architecture, to make sure your kext will load regardless of the architecture of the kernel.

  1. Click the disclosure triangle next to Targets in the Groups and Files pane.

  2. Select the MyKext target.

  3. Choose File > Get Info. The Target “MyKext” Info window opens.

  4. In the list of settings, find Build Active Architecture Only and make sure the checkbox is unchecked.

  5. Close the Target MyKext Info window.

Now that your kext is building against every architecture, choose Build > Build to build your project. If the build fails, correct all indicated errors and rebuild before proceeding.

Add Library Declarations

Because kexts are linked at load time, a kext must list its libraries in its information property list with the OSBundleLibraries property. At this stage of creating your kext, you need to find out what those libraries are. The best way to do so is to run the kextlibs tool on your built kext and copy its output into your kext’s Info.plist file.

Run kextlibs on the Kernel Extension

kextlibs is a command-line program that you run with the Terminal application. Its purpose is to identify libraries that your kext needs to link against.

Note: This tutorial uses the dollar sign ($) prompt when it shows the commands you type in the Terminal application. This is the default prompt of the bash shell, which is the default shell in Mac OS X. If you’re using a different shell, you may see a different prompt (the percent symbol (%) is another common prompt).

  1. Start the Terminal application, located in /Applications/Utilities.

  2. In the Terminal window, move to the directory that contains your kext.

    Xcode stores your kext in the Debug folder of the build folder of your project (unless you’ve chosen a different build configuration or set a different location for build products using Xcode’s Preferences dialog).

    点击(此处)折叠或打开

    1. $ cd MyKext/build/Debug

    This directory contains your kext. It should have the name MyKext.kext. This name is formed from the Product Name as set in your target’s build settings, and a suffix, in this case .kext.

  3. Run kextlibs on your kernel extension with the -xml command-line flag.

    This command looks for all unresolved symbols in your kernel extension’s executable among the installed library extensions (in /System/Library/Extensions/) and prints an XML fragment suitable for pasting into an Info.plist file. For example:

    点击(此处)折叠或打开

    1. $ kextlibs -xml MyKext.kext

    2. OSBundleLibraries


    3. com.apple.kpi.libkern

    4. 10.2

  4. Make sure kextlibs exited with a successful status by checking the shell variable $?.

    点击(此处)折叠或打开

    1. $ echo $?

    2. 0

    If kextlibs prints any errors or exits with a nonzero status, it may have been unable to locate some symbols. For this tutorial, the libraries are known, but in general usage you should use the kextfind tool to find libraries for any symbols that kextlibs cannot locate. See “Locate Kexts with kextfind” for information on kextfind.

  5. Select the XML output of kextlibs and choose Edit > Copy.

Add the Library Declarations to the Information Property List

Earlier, you edited the information property list with Xcode’s graphical property list editor. For this operation, however, you need to edit the information property list as text.

Control-click Info.plist in the Xcode project window, then choose Open As > Source Code File from the contextual menu.

Xcode displays the Info.plist file in the editor pane. You should see the XML contents of the property list file, as shown in Figure 3. Note that dictionary keys and values are listed sequentially.

Figure 3  MyKext Info.plist as textFigure 3  MyKext Info.plist as text

2. Select all the lines defining the empty OSBundleLibraries dictionary:

点击(此处)折叠或打开

  1. <key>OSBundleLibraries</key>

  2.         <dict/>

3. Paste text into the info dictionary.

  • If kextlibs ran successfully, choose Edit > Paste to paste the text you copied from Terminal.

  • If kextlibs didn’t run successfully, type or paste this text into the info dictionary:

    点击(此处)折叠或打开

    1. <key>OSBundleLibraries</key>

    2.         <dict>

    3.                 <key>com.apple.kpi.libkern</key>

    4.                 <string>10.0</string>

    5.         </dict>

    4. Save your changes by choosing File > Save.
    5. Choose Build > Build a final time to rebuild your kext with the new information property list.

Prepare the Kernel Extension for Loading

Now you are ready to prepare your kext for loading. You do this with the kextutil tool, which can examine a kext and determine whether it is able to be loaded. kextutil can also load a kext for development purposes, but that functionality is not covered in this tutorial.

Note: This tutorial does not cover actually loading a kext. For safety reasons, you should not load your kext on your development machine. For information on loading and debugging a kext with a two-machine setup, see “Debugging a Kernel Extension With GDB.”

Set the Kernel Extension’s Permissions

Kexts have strict permissions requirements (see “Kernel Extensions Have Strict Security Requirements” for details). The easiest way to set these permissions is to create a copy of your kext as the root user. Type the following into Terminal from the proper directory and provide your password when prompted:

点击(此处)折叠或打开

  1. $ sudo cp -R MyKext.kext /tmp

Now that the permissions of the kext’s temporary copy are correct, you are ready to run kextutil.

Run kextutil

Type the following into Terminal:

点击(此处)折叠或打开

  1. $ kextutil -n -print-diagnostics /tmp/MyKext.kext
The -n (or -no-load) option tells kextutil not to load the driver, and the -t (or -print-diagnostics) option tells kextutil to print the results of its analysis to Terminal. If you have followed the previous steps in this tutorial correctly, kextutil indicates that the kext is loadable and properly linked.

点击(此处)折叠或打开

  1. No kernel file specified; using running kernel for linking.

  2. MyKext.kext appears to be loadable (including linkage for on-disk libraries).
Note: You may encounter an error similar to the following:

点击(此处)折叠或打开

  1. Warnings:

  2. Executable does not contain code for architecture:

  3. i386
If you do, make sure you set your kext to build for all architectures, as described in “Create a New Project.”


注解:这篇文档详细的描述了如何去创建一个内核扩展模块,总结起来就是下面几个步骤:
1.通过xcode创建一个General Kernel Extension Project
2.对工程进行设置,主要是设置模块的唯一标识
3.编译工程,然后用kextlibs命令对编译生成的*.kext文件进行查看,查看依赖的库
4.然后将依赖库信息的xml格式拷贝到plist文件对应的位置。
5.重新编译工程,修改生成的*.kext文件的所有者为root用户
6.用kextload安装内核模块
阅读(11303) | 评论(12) | 转发(1) |
给主人留下些什么吧!~~

zhanleewo2012-04-16 22:03:23

星期五啦: http://blog.chinaunix.net/uid-24512513-id-3173147.html
这个不错哦~~多谢了.....
呵呵,分享快乐

zhanleewo2012-04-16 22:02:26

夏冰软件: 写的不错,支持一下.....
这是Apple的一篇文章,我复制过来了,他们肯定写的很不错的

zhanleewo2012-04-16 22:01:12

小蝌蚪123: 后面的链接不错~希望大家多多去看看啊~.....
呵呵,谢谢推广

zhanleewo2012-04-16 21:48:58

桔色花花朵: 博主很好很强大,新人前来学习一番啊.....
谢谢夸奖,我只是把苹果的文档稍微翻译了一下呵呵

桔色花花朵2012-04-16 21:43:24

博主很好很强大,新人前来学习一番啊