This article provides some general information about kernel extensions (KEXTs).
Why to Avoid KEXTs
When You Need a KEXT
KEXT Tutorials
Because KEXTs provide both modularity and dynamic loadability, they are a natural choice for any relatively self-contained service that requires access to kernel internal interfaces. Many of the components of the kernel environment support this extension mechanism, although in different ways.
For example, some networking features involve the use of network kernel extensions (NKEs). The ability to dynamically add a new file-system implementation is based on VFS KEXTs. Device drivers and device families in the I/O Kit are implemented using KEXTs. KEXTs make development much easier for developers writing drivers or those writing code to support a new volume format or networking protocol.
Because KEXTs run in supervisor mode in the kernel’s address space, they are also harder to write and debug than user-level modules, and must conform to strict guidelines. Further, kernel resources are wired (permanently resident in memory) and are thus more costly to use than resources in a user-space task of equivalent functionality.
In addition, although memory protection keeps applications from crashing the system, no such safeguards are in place inside the kernel. A badly behaved kernel extension in Mac OS X can actually cause more trouble than a badly behaved application or extension could in previous version of the Mac OS.
Bugs in KEXTs can have far more severe consequences than bugs in user-level code. For example, a memory access error in a user application can, at worst, cause that application to crash. In contrast, a memory access error in a KEXT causes a system panic, crashing the operating system.
Finally, for security reasons, some customers restrict or don’t permit the use of third-party KEXTs. As a result, use of KEXTs is strongly discouraged in situations where user-level solutions are feasible. The Darwin kernel guarantees that user threads are just as efficient as kernel threads, so efficiency should not be an issue. Unless your application requires low-level access to kernel interfaces or the data stream, you should use a higher level of abstraction when developing code for Mac OS X.
When you are trying to determine if a piece of code should be a KEXT, the default answer is generally no.
In particular, if your code was a system extension in previous versions of the Mac OS, such as Mac OS 9, that does not imply that it must necessarily be a kernel extension in Mac OS X. There are only a few good reasons for a developer to write a kernel extension:
Your code needs to take a primary interrupt, that is, something in the hardware needs to interrupt the CPU.
The primary client of your code is inside the kernel, for example, a block device whose primary client is a file system.
A sufficiently large number of running applications require a resource that your code provides; for example, you have written a file-system stack.
Your code needs to multiplex between multiple client applications that require high speed, excellent synchronization, or low latency.
If your code does not meet any of the above criteria, you should consider developing it as a library or a user-level daemon, or using one of the user-level plug-in architectures (such as QuickTime components or the Core Graphics framework) instead of writing a kernel extension.
If you are writing device drivers or code to support a new volume format or networking protocol, however, KEXTs may be the only feasible solution.
Fortunately, while KEXTs may be more difficult to write than user-space code, several tools and procedures are available to enhance the development and debugging process. The tutorials collected in this topic are designed to give you some hands-on experience with creating, building, and debugging KEXTs.
Be sure to complete “Hello Kernel” first. This tutorial describes how to create and test a kernel extension (KEXT) for Mac OS X. In this tutorial, you’ll create a very simple extension that prints text messages when loading and unloading.
The second tutorial, “Hello IOKit”, describes how to write an I/O Kit device driver for Mac OS X. The driver you’ll create is a simple driver that prints text messages but doesn’t actually control any hardware.
The third tutorial, “Hello Debugger”, builds upon what you have learned in the first two. Using the sample driver you created in “Hello IOKit”, this tutorial describes how to prepare to debug a device driver for Mac OS X. You will learn how to set up a two-machine debugging environment and how to start using GDB, a command-line debugger, to perform remote debugging.
Although “Hello Debugger” is written with a device driver as the example, the steps for debugging are similar for debugging any type of kernel extension (KEXT). If you wish, you can substitute your own code for the HelloIOKit example. Note, however, that you may encounter a few inconsistencies. For example, examples of GDB commands may be dependent on the underlying source code language—I/O Kit extensions (drivers) use C++; the GDB commands for C may differ.
In the packaging tutorial, you’ll learn how to package a kernel extension for distribution and installation on Mac OS X. The KEXT can be any type: a device driver, file system stack, or Network Kernel Extension (NKE). This tutorial may be completed out of sequence; that is, you may decide to work through this tutorial before completing “Hello IOKit” or “Hello Debugger”.
© 2003, 2007 Apple Inc. All Rights Reserved. (Last updated: 2007-10-31)