What is Mac OS X?

© Amit Singh. All Rights Reserved. Written in December 2003

XNU: The Kernel

The Mac OS X kernel is called XNU. It can be viewed as consisting of the following components:

Mach

XNU contains code based on Mach, the legendary architecture that originated as a research project at Carnegie Mellon University in the mid 1980s (Mach itself traces its philosophy to the Accent operating system, also developed at CMU), and has been part of many important systems. Early versions of Mach had monolithic kernels, with much of BSD's code in the kernel. Mach 3.0 was the first microkernel implementation.

XNU's Mach component is based on Mach 3.0, although it's not used as a microkernel. The BSD subsystem is part of the kernel and so are various other subsystems that are typically implemented as user-space servers in microkernel systems. XNU's Mach is responsible for various low-level aspects of the system, such as:

The sequence of events prior to the kernel is passed control is described in Booting Mac OS X. The secondary bootloader eventually calls the kernel's "startup" code, forwarding various boot arguments to it. This low-level code is where every processor in the system starts (from the kernel's point of view). Various important variables, like maximum virtual and physical addresses, the threshold temperature for throttling down a CPU's speed, are initialized here, BAT registers are cleared, Altivec (if present) is initialized, caches are initialized, etc. Eventually this code jumps to boot initialization code for the architecture (ppc_init() on the PowerPC). Thereafter:

At this point, Mach is up and running.

In addition to BSD system calls (the syscall API, as well as the sysctl and ioctl APIs), Mach messaging and IPC can be and is used (as appropriate) to exchange information between the user and kernel spaces. XNU also provides various ways of memory mapping and block copying. While it may be nice (say, from an academic point of view, if nothing else) to have many APIs in a system, there is always a burden on the programmer for choosing wisely what API to use. The situation is similar for user-space APIs on Mac OS X, as we shall see later.

BSD

XNU's BSD component uses FreeBSD as the primary reference codebase (although some code might be traced to other BSDs). Darwin 7.x (Mac OS X 10.3.x) uses FreeBSD 5.x. As mentioned before, BSD runs not as an external (or user-level) server, but is part of the kernel itself. Some aspects that BSD is responsible for include:

Note that XNU has a unified buffer cache but it ties in to Mach's VM.

XNU uses a synchronization abstraction (built on top of Mach mutexes) called funnels to serialize access to the BSD portion of the kernel. The kernel variables pointing to these funnels have the _flock suffix, such as kernel_flock and network_flock. When Mach initializes the BSD subsystem via a call to bsd_init(), the first operation performed is the allocation of funnels (the kernel funnel's state is set to TRUE). Thereafter:

XNU uses a specific type of kernel extensions, NKEs (Network Kernel Extensions), to make the 4.4BSD networking architecture fit in to Mac OS X.

The rest of the user space startup is described in Mac OS X System Startup.

I/O Kit

I/O Kit, the object-oriented device driver framework of the XNU kernel is radically different from that on traditional systems.

I/O Kit uses a restricted subset of C++ (based on Embedded C++) as its programming language. This system is implemented by the libkern library. Features of C++ that are not allowed in this subset include:

The device driver model provided by the I/O Kit has several useful features (in no particular order):

I/O Kit's implementation consists of three C++ libraries that are present in the kernel and available to loadable drivers: IOKit.framework, Kernel/libkern and Kernel/IOKit. The I/O Kit includes a modular, layered run-time architecture that presents an abstraction of the underlying hardware by capturing the dynamic relationships between the various hardware/software components (involved in an I/O connection).

Various tools such as ioreg, ioalloccount, ioclasscount, iostat, kextload, kextunload, kextstat, kextcache, etc. let you explore and control various aspects of I/O Kit. For example, the following command shows status of dynamically loaded kernel extensions:

% kextstat Index Refs Address Size Wired Name (Version) <Linked Against> 1 1 0x0 0x0 0x0 com.apple.kernel (7.2) 2 1 0x0 0x0 0x0 com.apple.kpi.bsd (7.2) 3 1 0x0 0x0 0x0 com.apple.kpi.iokit (7.2) 4 1 0x0 0x0 0x0 com.apple.kpi.libkern (7.2) ...

The following command lists the details of the I/O Kit registry in excruciating detail:

% ioreg -l -w 0 +-o Root <class IORegistryEntry, retain count 12> | { | "IOKitBuildVersion" = "IOKit Component Version 7.2: Thu Dec 11 16:15:20 PST 2003; root(rcbuilder):RELEASE_PPC/iokit/RELEASE " | "IONDRVFramebufferGeneration" = <0000000200000002> ... /* thousands of lines of output */

Platform Expert

The Platform Expert is an object (one can think of it as a driver) that knows the type of platform that the system is running on. I/O Kit registers a nub (see below) for the Platform Expert. This nub then loads the correct platform specific driver, which further discovers the buses present on the system, registering a nub for each bus found. The I/O Kit loads a matching driver for each bus nub, which discovers the devices connected to the bus, and so on. Thus, the Platform Expert is responsible for actions such as:

In the context of the I/O Kit, a "nub" is an object that defines an access point and communication channel for a device (a bus, a disk drive or partition, a graphics card, ...) or logical service (arbitration, driver matching, power management, ...).

libkern and libsa

As described earlier, the I/O Kit uses a restricted subset of C++. This system, implemented by libkern, provides features such as:

libsa provides functions for miscellaneous purposes: binary searching, symbol remangling (used for gcc 2.95 to 3.3, for example), dgraphs, catalogs, kernel extension management, sorting, patching vtables, etc.

<<< Booting Mac OS X main Above the Kernel >>>