The I/O Kit is a collection of system frameworks, libraries, tools, and other resources for creating device drivers in Mac OS X. It is based on an object-oriented programming model implemented in a restricted form of C++ that omits features unsuitable for use within a multithreaded kernel. By modeling the hardware connected to a Mac OS X system and abstracting common functionality for devices in particular categories, the I/O Kit streamlines the process of device-driver development.
From its inception, the fundamental goal for the I/O Kit has been to accommodate and augment native features and capabilities of Mac OS X, particularly those of the kernel environment. As the driver model for Mac OS X, the I/O Kit supports the following features: •Dynamic and automatic device configuration (plug-and-play) •Many new types of devices, including graphics acceleration and multimedia devices •Power management (for example, “sleep”
• The kernel’s enforcement of protected memory—separate address spaces for kernel and user programs • Preemptive multitasking • Symmetric multiprocessing • Common abstractions shared between types of devices • Enhanced development experience— new drivers should be easy to write
The I/O Kit supports these kernel features with its new model for device drivers and adds some additional features: • An object-oriented framework implementing common behavior shared among all drivers and types (families) of drivers • Many families for developers to build upon • Threading, communication, and datamanagement primitives for dealing with issues related to multiprocessing, task control, and I/O-transfers • A robust, efficient match-and-load mechanism that scales well to all bus types
• The I/O Registry, a database that tracks instantiated objects (such as driver instances) and provides information about them • The I/O Catalog, a database of all I/O Kit classes available on a system • A set of device interfaces—plug-in mechanisms that allows applications and other software in “user space” to communicate with drivers • Excellent overall performance • Support for arbitrarily complex layering of client and provider objects
The I/O Kit’s object-oriented programming model is implemented in a restricted subset of C++. Object-orientation just in itself is an advantage in driver development because of the code reusability it fosters. Once you are familiar with the I/O Kit, you can write device drivers much more quickly and efficiently than you can using a procedural model. In addition, code reusability decreases the memory footprint of drivers; drivers ported from Mac OS 9, for example, have been up to 75% smaller in Mac OS X.
The Mac OS X kernel is significantly more advanced than its Mac OS precursors; it handles memory protection, preemptive multitasking, multiprocessing, and other features not present in previous versions of Mac OS. • The primary motivation behind the I/O Kit was the inadequacy of the currently available driver models. The redesign of the I/O architecture had to take advantage of and support the operating-system features of Mac OS X. • Toward this end, the I/O Kit’s designers settled on object-oriented programming model that abstracted the kernel capabilities and hardware of a Mac OS X system and provided a view of this abstraction to •
• Another part of the design philosophy of the I/O Kit is to make the design completely open. • The I/O Kit functions as a kind of foundation and coordinator for device drivers. • Mac OS X delivers the I/O Kit as part of a single kernel development kit (KDK); all portions of the KDK rest on common underpinnings
The I/O Kit’s layered architecture models the chain of connections between the system’s hardware buses and devices, gathering common functionality into classes your driver can interact with. Each layer is a client of the layer below it and a provider of services to the layer above it. Broad groupings of layers, defined by the I/O Kit families, define the functionality common to a general type of I/O provider, such as networking or PCI bus devices.
Another way to look at a stack of driver objects in a typical I/O connection is to consider the stack from a dynamic perspective. In other words, what happens when a Mac OS X system discovers a new device attached to it? How is the stack of driver objects constructed? For this, let’s use the example of a SCSI disk drive; the general order of creation or discovery in Figure 2-2 is left to right.
The I/O Kit encompasses dozens of C++ classes and is itself an extension of the libkern C++ library, the foundation for loadable kernel modules. Taken together, the I/O Kit and libkern would seem to form a forbiddingly large and complex hierarchy of classes. Yet the essential structure of that hierarchy is fairly simple, as Figure 2-3 illustrates.
You can break down the extended I/O Kit class hierarchy into three broad groupings: • The classes of libkern (sometimes called the OS classes because of their “OS” prefix) • The I/O Kit base classes and helper classes • The classes of the I/O Kit families
Mac OS X supports numerous technologies for interprocess communication (IPC) and for delivering notifications across the system. The following sections describe the available technologies.
• Introduced in Mac OS X v10.5 • FSEvents API notifies your application when changes occur in the file system • The FSEvents API provides a much simpler way to monitor many directories at once • The FSEvents API is not intended for detecting fine-grained changes to individual files like detecting changes to an individual file as in a virus checker program • Instead, you might use FSEvents to detect general changes to a file hierarchy
Kernel queues (also known as kqueues) and kernel events (also known as kevents) are an extremely powerful technology you use to intercept kernel-level events. Although often used to detect file-system changes, you can also use this technology to receive notifications about changes to sockets, processes, and other aspects of the system. For example, you could use them to detect when a process exits or when it issues fork and exec calls. Kernel queues and events are part of the FreeBSD layer of the operating
Shared memory is a region of memory that has been allocated by a process specifically for the purpose of being readable and possibly writable among several processes. You create regions of shared memory in several different ways. Access to shared memory is controlled through POSIX semaphores, which implement a kind of locking mechanism. Shared memory has some distinct advantages over other forms of interprocess communication:
An Apple event is a high-level semantic event that an application can send to itself, to other applications on the same computer, or to applications on a remote computer. Apple events are the primary technology used for scripting and interapplication communication in Mac OS X. Applications can use Apple events to request services and information from other applications. To supply services, you define objects in your application that can be accessed using Apple events and then provide Apple event handlers to respond to requests for those objects. Apple events have a well-defined data structure that supports extensible, hierarchical data types. To make it easier for scripters and other developers to access it, your application should generally support the standard set of events defined by Apple. If you want to support additional features not covered by the
Cocoa distributed objects provide a transparent mechanism that allows different applications (or threads in the same application) to communicate on the same computer or across the network. The implementation of distributed objects lets you focus on the data being transferred rather than the connection. As a result, implementing distributed objects takes less time than most other IPC mechanisms; however, this ease of implementation comes at the cost of performance. Distributed objects are typically not as efficient as many other techniques.
Mach IPC can approximately be compared with BSD sockets, but is more powerful and is mainly used for local machine communication. Mach IPC is a facility of the XNU kernel; it falls into two distinct categories, ports and messages. The XNU kernel implements most aspects of Mach IPC except network-transparent IPC.