Before loading a kernel extension (KEXT), the kernel extension management facilities in Mac OS X check its compatibility with other loadable extensions it depends on and with the kernel itself. To make sure your KEXT loads, be sure you know what your KEXT depends on and how to declare those dependencies.
This document provides kernel subcomponent and loadable extension versions for Mac OS X versions 10.0 through 10.4.2. It also describes the kernel programming interface (KPI) collections introduced in Mac OS X version 10.4 and how to use them.
KEXT Versions and Dependencies
Installing and Removing Kernel Extensions
Every kernel extension has a version that is stored both in its information property list (Info.plist
file) and in its executable. The version number is stored as a string property in the ‘vers’
resource style named CFBundleVersion
(described in http://developer.apple.com/documentation/mac/Toolbox/Toolbox-454.html and Technical Note TN1132). A KEXT or kernel component that can be depended on also declares the earliest version its current version is compatible with. This version (also in the ‘vers’
resource style) is stored in the OSBundleCompatibleVersion
property at the top level of its Info.plist
file.
A KEXT declares dependencies on other loadable extensions or kernel subcomponents by listing them as elements in the OSBundleLibraries
dictionary at the top level of its Info.plist
file. Each element in the OSBundleLibraries
dictionary consists of a key/value pair. The key is the CFBundleIdentifier
of the dependency (such as com.apple.kernel.mach
), and the value is the required version of the dependency expressed as a ‘vers’
resource style string (such as 1.0b1
). When a KEXT is about to be loaded, the required version of each element in its OSBundleLibraries
dictionary is compared to the current and compatible versions of the dependency. If the required version lies between the current version of the dependency and its OSBundleCompatibleVersion
value, inclusive, the KEXT and its dependencies are deemed compatible and loading proceeds.
If you fail to declare the appropriate dependencies, your KEXT will probably compile, but it will not load. To help you catch such problems early, it’s good practice to use the kextload
tool to load your KEXT periodically thoughout the development cycle. The kextload
tool has options that allow it to perform a wide range of tests; for more information, see Mac OS X Man Pages or type man kextload
in a Terminal window.
In Mac OS X v10.4, Apple introduced sustainable kernel programming interfaces, or KPIs. In particular, the KPIs support the development of NKEs (network kernel extensions), file-system KEXTs, and other non-I/O Kit KEXTs. For more information on the KPIs themselves, see KPI Reference.
The KPIs are divided into collections which correspond in name to the kernel subcomponents available in earlier versions of Mac OS X. For example, the KPI collection that corresponds to the com.apple.kernel.libkern
kernel subcomponent is com.apple.kpi.libkern
. In Mac OS X v10.4 and later, you declare dependencies on KPI collections by creating key/value pairs in your KEXT’s OSBundleLibraries
dictionary, just as you did for dependencies on kernel subcomponents (as described in “KEXT Versions and Dependencies”). The key is the KPI collection’s CFBundleIdentifier
(such as com.apple.kpi.bsd
) and the value is the current version of the Darwin kernel expressed as a ‘vers’
resource style string. Because you can only declare a dependency on a KPI collection in Mac OS X v10.4 and later, the minimum version number is 8.0
. To get the current version of the Darwin kernel, type uname -a
in a Terminal window.
For pure I/O Kit KEXTs (those that use only I/O Kit-provided APIs), no changes in declared dependencies are necessary. This is because Mac OS X v10.4 provides backward compatibility with the I/O Kit kernel subcomponents available in earlier versions of Mac OS X. Therefore, you can continue to declare your pure I/O Kit KEXT’s dependencies on the kernel subcomponent versions of the earliest version of Mac OS X you need to run in. For more information on how to do this, see “Declaring Dependencies on Kernel Subcomponents.”
Note: If you are developing a universal I/O Kit device driver, see Technical Note TN2163: Building Universal I/O Kit Drivers for information on how to configure your Xcode project and declare the correct dependencies for your situation.
You should consider, however, taking this opportunity to make sure all your pure I/O Kit KEXT’s dependencies are explicitly declared. If, for example, your KEXT uses libkern symbols, declare an explicit dependency on com.apple.kernel.libkern
. This may seem obvious, but some earlier versions of Mac OS X allowed implicit dependencies on some kernel subcomponents (such as com.apple.kernel.libkern
) when you declared an explicit dependency on com.apple.kernel.iokit
. The KPI collections, on the other hand, do not allow any implicit dependencies. Therefore, if your KEXT declares only explicit dependencies on kernel subcomponents, it will make it much easier to switch to dependencies on KPIs at some point in the future.
If your I/O Kit-based KEXT makes non-I/O Kit BSD or Mach calls, it may not load in Mac OS X v10.4 because some non-I/O Kit symbols are no longer available. If this describes your KEXT, you must develop a new version of your KEXT for Mac OS X v10.4 that depends on the appropriate KPI collections instead of the kernel subcomponents it depended on before.
Important: You cannot combine dependencies on KPI collections and dependencies on kernel subcomponents in the same KEXT; dependencies must be all of one type or the other. If your KEXT declares dependencies on both KPI collections and kernel subcomponents, it will fail to load.
Beginning in Mac OS X v10.4, there are three, mutually exclusive ways to declare KEXT dependencies, the first two of which are discussed above. The following list summarizes the three methods, explains how to get the correct version for each type of dependency, and describes the circumstances in which you can use each method.
Declare dependencies on KPI collections. This is the preferred method because doing so ensures your KEXT links against the latest, sustainable interfaces for the kernel. When you use this method, the version of each KPI collection must match the version of the Darwin kernel (8.0 or greater).
This method is required for NKEs, file-system KEXTs, and other non-I/O Kit KEXTs.
This method is required for I/O Kit-based KEXTs that use non-I/O Kit functions (such as BSD or Mach functions) and that must run in Mac OS X v10.4 and later.
This method is not required for pure I/O Kit KEXTs, but it is strongly recommended for pure I/O Kit KEXTs that will run only in Mac OS X v10.4 and later.
Declare dependencies on the kernel subcomponents available in earlier versions of Mac OS X. This method provides backward compatibility for pure I/O Kit KEXTs, but some Mach and BSD symbols are no longer available. When you use this method, use the version of the kernel subcomponent that corresponds to the earliest version of Mac OS X you need to support (see the tables in “Declaring Dependencies on Kernel Subcomponents” for these values).
This method is suitable for pure I/O Kit KEXTs that must run in versions of Mac OS X prior to Mac OS X v10.4.
This method will not work for NKEs, file-system KEXTs, or other non-I/O Kit KEXTs. In addition, this method will not work for I/O Kit-based KEXTs running in Mac OS X v10.4 and later that use non-I/O Kit functions.
Declare a dependency on a specific version of the entire kernel. This method provides no binary compatibility between Mac OS X releases and is provided as a convenience for testing or educational purposes only. When you use this method, use the build version of the kernel displayed when you type sw_vers
in a Terminal window.
This method is recommended for in-house or educational environments in which access to internal kernel interfaces is desirable, but binary compatibility of a product is not required. You might also use this method in an open-source environment in which users of your product expect to rebuild it with every update.
Warning: This method is absolutely unsuitable for development of a consumer product. If you declare your KEXT's dependency on a specific version of the kernel, it will load on only that version and no other. If a user performs a software update or upgrades the kernel in any way, your KEXT will no longer load.
The following tables show the CFBundleVersion
value of each kernel subcomponent. Note that Table 1 also includes the CFBundleVersion
values for select kernel extensions. This is because in versions of Mac OS X prior to 10.1, these kernel extensions were included in the kernel. In Mac OS X version 10.1, however, most of these kernel extensions were removed from the kernel and made into loadable kernel extensions. The remaining four tables do not list these loadable kernel extensions.
Note: Component versions marked (L) in Table 1 indicate that the component was removed from the kernel and made into a loadable kernel extension.
Component versions marked (M) in Table 1 indicate that the component was moved into theSystem.kext
PlugIns folder.The following tables (Table 2, Table 3, Table 4, and Table 5) each list kernel subcomponent CFBundleVersion
values for a range of operating system releases, beginning with Mac OS X version 10.1.1. The kernel subcomponents in these tables are:
com.apple.kernel
com.apple.kernel.mach
com.apple.kernel.bsd
com.apple.kernel.libkern
com.apple.kernel.iokit
In the interests of space, the com.apple.
prefix is not included in each kernel subcomponent CFBundleIdentifier
value.
System release |
|
|
|
|
|
|
---|---|---|---|---|---|---|
10.4 (Build 8A428) | 8.0 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.1 (Build 8B15) | 8.1 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.2 (Builds 8C46, 8E45, 8E90, and 8E102) | 8.2 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.3 (Build 8F46) | 8.3 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.4 (Builds 8G32 and 8G1165) | 8.4 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.5 (Builds 8H14 and 8G1454) | 8.5 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.6 (Builds 8I127 and 8I1119) | 8.6 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.7 (Builds 8J135, 8J2135a, and 8K1079) | 8.7 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.8 (Builds 8L127 and 8L2127) | 8.8 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.9 (Builds 8P135 and 8P2137) | 8.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
10.4.10 (Builds 8R218 and 8R2218) | 8.10 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 | 7.9.9 |
You can also get this information by using the kextstat utility to examine the version numbers of these components. (For more information on how to use kextstat, type man kextstat
in a Terminal window.) To build a KEXT that works on two different versions of Mac OS X, build the KEXT on the oldest version you want to support.
If an I/O Kit kernel extension does not declare a dependency that defines a superclass but otherwise uses no symbols within that dependency, the KEXT will load successfully but the runtime metaclass system will fail to create an instance of the class, due to the absence of the superclass. In this case, an error message to this effect will be displayed.
The identifier com.apple.kernel
represents the kernel as a whole. Because every kernel extension is linked against the kernel, it may seem easier to declare your KEXT's dependency on com.apple.kernel
instead of the individual kernel subcomponents. However, if any part of the kernel changes in an incompatible way, the compatible version (the OSBundleCompatibleVersion
value) for com.apple.kernel
will be incremented. This may prevent your KEXT from loading even if the kernel subcomponents your KEXT actually depends on remain unchanged.
To determine which of the four kernel subcomponents your KEXT depends on, examine the #include
directives in your KEXT's code. Table 7 lists header directories and their corresponding kernel subcomponents.
If your KEXT can be depended on by other kernel extensions you must declare the earliest version that remains compatible with the current version in the OSBundleCompatibleVersion
property at the top level of its Info.plist
file. If this property is absent, no other kernel extension can declare a dependency on your KEXT. If you make changes to your KEXT that break binary compatibility with earlier versions (for example, the removal of a function or symbol) then you should change the value of the OSBundleCompatibleVersion
property to equal the value of the CFBundleVersion
property of the new version. It is not necessary to increment the OSBundleCompatibleVersion
value every time you increment the CFBundleVersion
value unless you've broken binary compatibility with a previously compatible version.
Software installers that install and remove kernel extensions can copy them to /System/Library/Extensions
or remove them from that folder. To load a new, nondriver KEXT either the system must be restarted or the new KEXT must be explicitly loaded with the kextload utility. To load a driver KEXT the system must be restarted to ensure reliable matching and loading of the driver for all possible devices.
The system keeps a cache of installed KEXTs to speed up boot time. It updates this cache when it detects any change to the /System/Library/Extensions
folder. If an installer installs an extension as a plug-in of another, however, only a subfolder of the /System/Library/Extensions
folder is updated and the automatic cache update is not triggered. To force a cache update, you can change the modification date of the /System/Library/Extensions
folder by using the UNIX command touch. For example, placing
touch /System/Library/Extensions |
in a postprocessing shell script for your installer will guarantee that the cache gets updated.
© 2003, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-10-31)