From the moment a user turns on a Mac OS X system to beyond the time the login window appears, Mac OS X executes a boot sequence that readies the system for use. If you provide system services to all users, you might need to execute some code during this process. The following sections explain the basic boot sequence and the places where your code can tie into it.
BootROM
BootX, boot.efi, and System Initialization
Authenticating Users
Configuring User Sessions
Logout Responsibilities
Identifying the Scope of Processes
The Shutdown Process
When the power to a Macintosh computer is turned on, the BootROM firmware is activated. BootROM (which is part of the computer’s hardware) has two primary responsibilities: it initializes system hardware and it selects an operating system to run. BootROM has two components to help it carry out these functions:
POST (Power-On Self Test) initializes some hardware interfaces and verifies that sufficient memory is available and in a good state.
On PowerPC-based Macintosh computers, Open Firmware initializes the rest of the hardware, builds the initial device tree (a hierarchical representation of devices associated with the computer), and selects the operating system to use.
On Intel-based Macintosh computers, EFI does basic hardware initialization and selects which operating system to use.
If multiple installations of Mac OS X are available, BootROM chooses the one that was last selected by the Startup Disk System Preference. The user can override this choice by holding down the Option key while the computer boots, which causes Open Firmware or EFI to display a screen for choosing the boot volume.
Note: On some legacy hardware, the same version of BootROM can start either Mac OS 9 or Mac OS X. Most current hardware can start only Mac OS X.
Once BootROM is finished and a Mac OS X partition has been selected, control passes to the BootX (PowerPC) or boot.efi (Intel) boot loader. The principal job of this boot loader is to load the kernel environment. As it does this, the boot loader draws the “booting” image on the screen.
BootX and boot.efi can be found in the /System/Library/CoreServices
directory on the root partition. In addition, a copy of boot.efi can be found at /usr/standalone/i386/boot.efi
.
In "exotic” boot situations such as booting from a software RAID volume, a copy of the boot loader is stored on a separate HFS+ “helper” volume to get the system started. In some versions of Mac OS X, a copy of the kernel and mkext cache are also included on the helper volume. In these cases, the booter and other components on the root volume are unused.
The boot loader first attempts to load a prelinked version of the kernel that includes all device drivers that are involved in the boot process. This prelinked kernel is located in /System/Library/Caches/com.apple.kernelcaches
. By linking these drivers into the kernel ahead of time, boot time is reduced.
If the prelinked kernel is missing, out-of-date, or corrupt, the boot loader attempts to load that same set of device drivers all at once in the form of a single, compressed archive called an mkext cache.
If this cache is also out-of-date, missing, or corrupt, the boot loader searches /System/Library/Extensions
for drivers and other kernel extensions whose OSBundleRequired
property is set to a value appropriate to the type of boot (for example, local or network boot).
For more information on how drivers are loaded, see I/O Kit Fundamentals.
Once the kernel and all drivers necessary for booting are loaded, the boot loader starts the kernel’s initialization procedure. At this point, enough drivers are loaded for the kernel to find the root device. Also from this point, on PowerPC-based Macintosh computers, Open Firmware is no longer accessible (quiesced).
The kernel initializes the Mach and BSD data structures and then initializes the I/O Kit. The I/O Kit links the loaded drivers into the kernel, using the device tree to determine which drivers to link. Once the kernel finds the root device, it roots(*) BSD off of it.
Note: As a terminology aside, the term “boot” was historically reserved for loading a bootstrap loader and kernel off of a disk or partition. In more recent years, the usage has evolved to allow a second meaning: the entire process from initial bootstrap until the OS is generally usable by an end user. In this case, the term is used according to the former meaning.
As used here, the term “root” refers to mounting a partition as the root, or top-level, filesystem. Thus, while the OS boots off of the root partition, the kernel roots the OS off of the partition before executing startup scripts from it.Prior to Mac OS X v10.4, the remaining system initialization was handled by the mach_init
and init
processes. During the course of initialization, these processes would call various system scripts (including /etc/rc
), run startup items, and generally prepare the system for the user. While many of the same scripts and daemons are still run, the mach_init
and init
processes have been replaced by launchd
in Mac OS X v10.4 and later. This change means that launchd
is now the root system process.
In addition to initializing the system, the launchd
process coordinates the launching of system daemons in an orderly manner. Like the inetd
process, launchd
launches daemons on-demand. Daemons launched in this manner can shut down during periods of inactivity and be relaunched as needed. (When a subsequent service request comes in, launchd
automatically relaunches the daemon to process the request.)
This technique frees up memory and other resources associated with the daemon, which is worthwhile if the daemon is likely to be idle for extended periods of time. More importantly, however, this guarantees that runtime dependencies between daemons are satisfied without the need for manual lists of dependencies.
Next, launchd
starts SystemStarter
, which starts any non-launch-on-demand daemons.
Note: While launchd
does support non-launch-on-demand daemons, this use is not recommended. The launchd
daemon was designed to remove the need for dependency ordering among daemons. If you do not make your daemon be launch-on-demand, you will have to handle these dependencies in another way, such as by using the legacy startup item mechanism.
For more information about launch-on-demand and SystemStarter
daemons and how to launch them, see “Daemons.”
As the final part of system initialization, launchd
launches loginwindow
. The loginwindow
program controls several aspects of user sessions and coordinates the display of the login window and the authentication of users.
Note: By default, Mac OS X boots with a graphical boot screen. For debugging the boot process, it is often useful to disable this, revealing the text console underneath. This mode is known as verbose boot mode. To enable verbose boot mode, simply hold down command-v after the boot chime.
Mac OS X requires users to authenticate themselves prior to accessing the system. The loginwindow
program coordinates the visual portion of the login process (as manifested by the window where users enter name and password information) and the security portion (which handles the user authentication). Once a user is authenticated by the security systems, loginwindow
begins setting up the user environment.
In two key situations, loginwindow
bypasses the usual login prompt and begins the user session immediately. The first situation occurs when the system administrator has configured the computer to automatically log in as a specified user. The second occurs during software installation when the installer program is to be launched immediately after a reboot.
Immediately after the user is successfully authenticated, loginwindow
sets up the user environment and records information about the login. As part of this process, it performs the following tasks:
Secures the login session from unauthorized remote access. Applications that are launched remotely are not registered with the pasteboard server’s (Clipboard’s) port. As a result, some standard features are blocked for these processes, including copy, cut, paste, Apple events, window minimization, and other services.
Records the login in the system’s utmp
database.
Sets the owner and permissions for the console terminal.
Resets the user’s preferences to include global system defaults.
Registers the pasteboard server (pbs
) with the bootstrap port and launches pbs
.
Configures the mouse, keyboard, and system sound using the user’s preferences.
Sets the user’s group permissions (gid
).
Retrieves the user record from Directory Services and applies that information to the session.
It loads the user’s computing environment (including preferences, environment variables, device and file permissions, keychain access, and so on).
It launches the Dock, Finder, and SystemUIServer.
It automatically launches applications specified in the Login Items pane of the Accounts System Preferences for the user.
Once the user session is up and running, loginwindow
monitors the session and user applications in the following ways:
It manages the logout, restart, and shutdown procedures. See “Logout Responsibilities” for more information.
It manages the Force Quit window, which includes monitoring the currently active applications and responding to user requests to force-quit applications and relaunch the Finder. (Users open this window from the Apple menu or by pressing Command-Option-Escape.)
It writes any standard-error (stderr
) output to a log file. Log files are stored in the /Library/Logs/Console/
<uid>/console.log
file, where <uid> is the user ID of the currently logged in user.
If the Finder, Dock, or SystemUIServer processes die for some reason, loginwindow
automatically restarts them. In the same manner, if the loginwindow
process dies, the launchd
process automatically restarts it.
The procedures for logging out, restarting the system, or shutting down the system have similar semantics. The foreground process usually initiates these procedures in response to the user choosing an item from the Apple menu; however, a process can also initiate the procedure programmatically by sending an appropriate Apple event to loginwindow
. The loginwindow
program carries out the procedure, posting alerts and notifying applications to give them a chance to clean up before closing.
A typical logout/restart/shutdown procedure is as follows:
The user selects Log Out, Restart, or Shut Down from the Apple menu.
The foreground application initiates the user request by sending an Apple event to loginwindow
. (See “Application Responsibilities” for a list of events.)
The loginwindow
program displays an alert to the user asking for confirmation of the action.
If the user confirms the action, loginwindow
sends a Quit Application Apple event (kAEQuitApplication
) to every foreground and background user process.
Once all processes have quit, loginwindow
closes out the user session and continues with the action.
For a logout action, loginwindow
dequeues all events in the event queue, starts the logout-hook program (if one is defined), records the logout, resets device permissions and user preferences to their defaults, and quits. It is subsequently relaunched by launchd
to handle a new login. (See “Customizing Login and Logout” for more on loginwindow
hooks.)
For a restart action, loginwindow
sets the device permissions and user preferences to their defaults and then restarts the system.
For a shutdown action, loginwindow
powers off the system.
Foreground processes can choose not to terminate when they receive the Quit Application event. See “Terminating Processes” for more information.
To initiate a logout, restart, or shutdown sequence programmatically, the foreground application must send an appropriate Apple event to loginwindow
. Upon receipt of the event, loginwindow
begins the process of shutting down the user session. Depending on the Apple event sent by the process, loginwindow
may or may not post an alert dialog and give the user a chance to abort the sequence.
The following list shows the preferred Apple events for logout, restart, and shutdown procedures. These events have no required parameters.
Upon receipt of one of these events, loginwindow
displays an alert notifying the user of the impending action. At this point, the user may continue with the action or abort it. If the user continues with the action, loginwindow
sends an Apple event to each application asking it to quit. See “Terminating Processes.”
In addition to the preferred Apple events, there are two additional events that tell loginwindow
to proceed immediately with a restart or shutdown sequence:
These events proceed with the corresponding sequence without posting an alert dialog to the user. Thus, if you send one of these events to loginwindow
, the user does not have an opportunity to abort the sequence. These events should be used sparingly, if at all.
Important: Note that if a logout, restart, or shutdown event originates from an application in the Classic environment, the event affects only the Classic environment and its applications. The rest of the user session continues running.
As part of a log out, restart, or shutdown sequence, loginwindow
attempts to terminate all foreground and background user processes. It sends each process a Quit Application Apple event (kAEQuitApplication
), as a courtesy, to give each process a chance to shut itself down gracefully. For foreground processes, loginwindow
sends the event and waits for a reply. For background processes, loginwindow
sends the event but does not wait for a reply. It terminates any lingering background processes by sending a kill
command.
When a foreground process receives the Quit Application Apple event from loginwindow
, it should terminate itself immediately or post an alert dialog if a user decision is required first (such as when there is an unsaved document); when that condition is resolved the application should then terminate. If the user decides to abort the termination sequence (by clicking Cancel in a Save dialog, for example) the application should respond to the event by returning a userCancelledErr
error.
Note: Cocoa applications do not see the kAEQuitApplication
event directly. The Application Kit notifies your application by calling its applicationShouldTerminate:
delegate method. To abort the termination sequence, implement this method and return NSTerminateCancel; otherwise, termination of your application continues normally.
If a foreground application fails to reply or terminate itself after 45 seconds, loginwindow
automatically aborts the termination sequence. This safeguard is to protect data in various situations, such as when an application is saving a large file to disk and is unable to terminate in the allotted time. If a foreground application is unresponsive and not doing anything, the user must use the Force Quit window to kill it before proceeding.
For user background processes that link with Carbon, Cocoa, or Java, the procedure is a little different. The loginwindow
program notifies the process that it is about to be terminated by sending it a Quit Application Apple event (kAEQuitApplication
) as before. Unlike foreground processes, however, loginwindow
does not wait for a reply. It proceeds to terminate any open background processes, regardless of any returned errors.
During a user logout, loginwindow
does not terminate processes residing in the root context. These processes reside outside the context of the user session and are terminated only during a restart or shutdown sequence. The loginwindow
program also does not kill background processes that are independent of Carbon, Cocoa, or Java, even if they are launched from the user context. (Though launched from a user context, these processes are taken over by the system when the user logs out.) Mac OS X does not send any notifications to system processes before terminating them.
Although the launchd
process owns every other process on the system, a distinction can still be made between user and system processes. Startup items, daemonized processes, and any processes run prior to loginwindow
typically run in the root context. Processes in this context provide services to all users of the system.
Processes that run within the context of an authenticated user session are user processes. User processes are always associated with a particular user session and are usually children of the WindowServer
or loginwindow
processes associated with the user login.
Note: Not all user processes are children of the WindowServer
process. Processes launched as root, and some special system processes, are owned by the user but are children of the launchd
process. You can use the ActivityMonitor application to determine the owner and parent of any process on the system.
At shutdown, Mac OS X first executes the service stop routines in any SystemStarter
startup items such as those described in “Creating a Startup Item.”
Next, as with most UNIX-based and UNIX-like operating systems, Mac OS X sends a SIGTERM
signal to all running processes prior to shutdown. Upon receiving this signal, your daemon should quickly make an orderly shutdown.
Every reasonable attempt will be made to wait for it to exit, but it is ultimately the responsibility of your daemon to keep the amount of unsaved state information to a level that can be reasonably written to disk in the time allotted.
A few seconds later, your daemon will receive a SIGKILL
signal and will be terminated.
© 2003, 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-11-19)