The base class for most I/O Kit families, devices, and drivers.
- macOS 10.0+
The IOService base class defines APIs used to publish services, instantiate other services based on the existance of a providing service (ie. driver stacking), destroy a service and its dependent stack, notify interested parties of service state changes, and general utility functions useful across all families.
Types of service are specified with a matching dictionary that describes properties of the service. For example, a matching dictionary might describe any IOUSBDevice (or subclass), an IOUSBDevice with a certain class code, or a IOPCIDevice with a set of matching names or device & vendor IDs. Since the matching dictionary is interpreted by the family which created the service, as well as generically by IOService, the list of properties considered for matching depends on the familiy.
Matching dictionaries are associated with IOService classes by the catalogue, as driver property tables, and also supplied by clients of the notification APIs.
IOService provides matching based on C++ class (via OSMetaClass dynamic casting), registry entry name, a registry path to the service (which includes device tree paths), a name assigned by BSD, or by its location (its point of attachment).
Driver Instantiation by IOService
Drivers are subclasses of IOService, and their availability is managed through the catalogue. They are instantiated based on the publication of an IOService they use (for example, an IOPCIDevice or IOUSBDevice), or when they are added to the catalogue and the IOService(s) they use are already available.
When an IOService (the "provider") is published with the registerService method, the matching and probing process begins, which is always single threaded per provider. A list of matching dictionaries from the catalog and installed publish notification requests, that successfully match the IOService, is constructed, with ordering supplied by
k ("IOProbeScore") property in the dictionary, or supplied with the notification.
Each entry in the list is then processed in order - for notifications, the notification is delivered, for driver property tables a lot more happens.
The driver class is instantiated and
init() called with its property table. The new driver instance is then attached to the provider, and has its probe method called with the provider as an argument. The default
probe method does nothing but return success, but a driver may implement this method to interrogate the provider to make sure it can work with it. It may also modify its probe score at this time. After probe, the driver is detached and the next in the list is considered (ie. attached, probed, and detached).
When the probing phase is complete, the list consists of successfully probed drivers, in order of their probe score (after adjustment during the probe call). The list is then divided into categories based on the
k property ("IOMatchCategory"); drivers without a match category are all considered in one default category. Match categories allow multiple clients of a provider to be attached and started, though the provider may also enforce open/close semantics to gain active access to it.
For each category, the highest scoring driver in that category is attached to the provider, and its start method called. If
start is successful, the rest of the drivers in the same match category are discarded, otherwise the next highest scoring driver is started, and so on.
The driver should only consider itself in action when the start method is called, meaning it has been selected for use on the provider, and consuming that particular match category. It should also be prepared to be allocated, probed and freed even if the probe was successful.
After the drivers have all synchronously been started, the installed "matched" notifications that match the registered IOService are delivered.
Properties used by IOService
Class of the driver to instantiate on matching providers.
Class of the provider(s) to be considered for matching, checked with OSDynamicCast so subclasses will also match.
The probe score initially used to order multiple matching drivers.
A string defining the driver category for matching purposes. All drivers with no
IOMatch property are considered to be in the same default category. Only one driver in a category can be started on each provider.
A string or collection of strings that match the provider's name. The comparison is implemented with the IORegistryEntry::compareNames method, which supports a single string, or any collection (OSArray, OSSet, OSDictionary etc.) of strings. IOService objects with device tree properties (eg. IOPCIDevice) will also be matched based on that standard's "compatible", "name", "device_type" properties. The matching name will be left in the driver's property table in the
For a list of possible matching names, a serialized array of strings should used, eg.
The name successfully matched name from the
k property will be left in the driver's property table as the
A dictionary of properties that each must exist in the matching IOService and compare successfully with the
The class name that the service will attempt to allocate when a user client connection is requested. First the device nub is queried, then the nub's provider is queried by default.
Set some debug flags for logging the driver loading process. Flags are defined in
65535 works well.