无法在OS X中开始使用kext开发

dig*_*doo 6 macos kernel iokit kernel-extension

我正在尝试做Apple的"内核扩展"教程.我创建了一个项目文件,创建了Info.plist,构建了它,使用kextlibs来学习依赖关系,将它们添加到Info.plist中,重建,复制到/ tmp,使用kextutil来测试它.到目前为止一切都很好.但是,当我尝试加载kext时,我的启动/停止/探测功能似乎永远不会被调用.我的IOLog消息没有出现在/var/log/system.log中.

实际上,system.log没有显示任何内容.在使用sysctl -w debug.kextlog = 0x0007780E激活kext日志记录后,kernel.log执行了.kernel.log说:"Kext ch.digorydoo.driver.XinputDevice成功解决了依赖关系." 然后:"刷新未加载的kexts和其他未使用的数据." 也许我的班级会立刻变得脸红?

我的类出现在kextstat的末尾,但有0个引用.与ioclasscount相同.在ioreg,我的班级没有出现.

我已经将IOProviderClass设置为IOResources,所以它应该始终有一个引用,对吧?我已正确设置IOMatchCategory.

有什么帮助吗?!!?!非常感谢!

编辑:这是我的Info.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleExecutable</key>
    <string>${EXECUTABLE_NAME}</string>
    <key>CFBundleName</key>
    <string>${PRODUCT_NAME}</string>
    <key>CFBundleIconFile</key>
    <string></string>
    <key>CFBundleIdentifier</key>
    <string>ch.digorydoo.driver.${PRODUCT_NAME:rfc1034identifier}</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundlePackageType</key>
    <string>KEXT</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleVersion</key>
    <string>1.0.0</string>
    <key>IOKitPersonalities</key>
    <dict>
        <key>Generic Xinput Gamepad</key>
        <dict>
            <key>CFBundleIdentifier</key>
            <string>ch.digorydoo.driver.${PRODUCT_NAME:rfc1034identifier}</string>
            <key>IOProviderClass</key>
            <string>IOResources</string>
            <key>IOMatchCategory</key>
            <string>ch_digorydoo_driver_XinputDevice</string>
            <key>IOClass</key>
            <string>ch_digorydoo_driver_XinputDevice</string>
            <key>IOKitDebug</key>
            <integer>65535</integer>
        </dict>
    </dict>
    <key>OSBundleLibraries</key>
    <dict>
        <key>com.apple.kpi.iokit</key>
        <string>10.8</string>
        <key>com.apple.kpi.libkern</key>
        <string>10.8</string>
        <key>com.apple.kpi.mach</key>
        <string>10.8</string>
    </dict>
</dict>
</plist>
Run Code Online (Sandbox Code Playgroud)

dig*_*doo 1

仍然不知道为什么我的简单 KEXT 没有启动。这是 kextutil 的输出:

$ kextutil -t -n XinputDevice.kext
No kernel file specified; using running kernel for linking.
Notice: XinputDevice.kext has debug properties set.
XinputDevice.kext appears to be loadable (including linkage for on-disk libraries).
Run Code Online (Sandbox Code Playgroud)

请注意,当我加载 KEXT 时,它显示“可加载,不包括链接”,但随后仍然显示它已加载:

$ kextutil -v 4 XinputDevice.kext 
Kext library architecture set to i386.
Kext library recording diagnostics for: validation authentication dependencies warnings.
Notice: XinputDevice.kext has debug properties set.
XinputDevice.kext appears to be loadable (not including linkage for on-disk libraries).
Loading XinputDevice.kext.
Reading load info for all kexts.
Reading loaded kext info from kernel.
Adding /private/tmp/XinputDevice.kext to mkext.
/private/tmp/XinputDevice.kext added 29260-byte noncompressed executable to mkext.
Created mkext for architecture i386 containing 1 kexts.
Loading XinputDevice.kext.
(kernel) Received request from user space to load kext ch.digorydoo.driver.XinputDevice.
(kernel) Recorded kext ch.digorydoo.driver.XinputDevice as a candidate for inclusion in prelinked kernel.
(kernel) Loading kext ch.digorydoo.driver.XinputDevice.
(kernel) Allocated link buffer for kext ch.digorydoo.driver.XinputDevice at 0x4d1e6000 (8192 bytes).
(kernel) Kext ch.digorydoo.driver.XinputDevice executable loaded; 2 pages at 0x4d1e6000 (load tag 114).
(kernel) Kext ch.digorydoo.driver.XinputDevice calling module start function.  ####
(kernel) Kext ch.digorydoo.driver.XinputDevice registered class ch_digorydoo_driver_XinputDevice.
(kernel) Kext ch.digorydoo.driver.XinputDevice has IOService subclass ch_digorydoo_driver_XinputDevice; enabling autounload.
(kernel) Kext ch.digorydoo.driver.XinputDevice is now started.
(kernel) Kext ch.digorydoo.driver.XinputDevice sending 1 personality to the IOCatalogue and starting matching.
(kernel) Kext ch.digorydoo.driver.XinputDevice loaded.
Successfully loaded XinputDevice.kext.
XinputDevice.kext successfully loaded (or already loaded).
Run Code Online (Sandbox Code Playgroud)

在上面我用####标记的行中,它表示调用了启动函数。但这不是真的,因为我的 start() 调用 IOLog,它应该在 /var/log/system.log 中写入一条消息,但事实并非如此。

以下是 /var/log/kernel.log 中显示的内容:

Jan  5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice, v1.0 registered and available for loading.
Jan  5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice resolving dependencies.
Jan  5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice added dependency com.apple.kpi.mach.
Jan  5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice added dependency com.apple.kpi.iokit.
Jan  5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice added dependency com.apple.kpi.libkern.
Jan  5 15:20:00 karaboudjan3 kernel[0]: Kext ch.digorydoo.driver.XinputDevice successfully resolved dependencies.
Jan  5 15:20:00 karaboudjan3 kernel[0]: Flushing nonloaded kexts and other unused data.
Run Code Online (Sandbox Code Playgroud)

事实上,类已加载,但没有创建实例:

$ ioclasscount | grep digory
ch_digorydoo_driver_XinputDevice = 0

$ kextstat | grep digory
  116    0 0x106f000  0x2000     0x1000     ch.digorydoo.driver.XinputDevice (1.0.0) <5 4 3>
Run Code Online (Sandbox Code Playgroud)

该类不会出现在 I/O 注册表中:

$ ioreg | grep Xinput
$ ioreg | grep digory
Run Code Online (Sandbox Code Playgroud)

没有实例意味着没有调用 init 或 start,因此没有 IOLog。如果没有人使用该类,它显然不会出现在活动对象的注册表中。

我的结论是教程一定是错的!即使它的提供者类是 IOResources,该类也永远不会被实例化!

我尝试用 IOUSBDevice 替换 IOResources。由于我没有提供任何 idProduct 或 idVendor,因此任何 USB 设备都应该匹配。除非我弄错了,否则侦听 USB 设备的守护进程应该实例化我的类并调用probe() 来查看这是否是该设备的正确驱动程序。

不幸的是,我仍然没有在 system.log 中收到任何日志消息!哪个守护进程负责 USB 设备?也许有一个驱动程序会在我的 KEXT 有机会之前以某种方式“吃掉”新插入的设备?如何追踪守护进程选择的驱动程序?

有什么提示吗?!?

  • 哈,它有效,我简直不敢相信!:D 我所要做的就是将 IOUSBDevice 设置为 IOProviderClass,定义 0 的 IOProbeScore(整数!),定义 idProduct 和 idVendor(都是整数!)并将它们设置为特定的 USB 设备。文档又错了,我的 IOLog 消息没有出现在 system.log 中,但出现在 kernel.log 中!哇,这花了我将近 10 个小时……笨蛋! (2认同)