This chapter summarizes the fundamental system technologies and facilities that are available to developers in Mac OS X. If you are new to developing Mac OS X software, you should read through this chapter at least once to understand the available technologies and how you might use them in your software. Even experienced developers should revisit this chapter periodically to remind themselves of the available technologies and look for recently introduced technologies.
Darwin
Binary File Architecture
Security
IPC and Notification Mechanisms
Core Foundation
Objective-C
Java Support
Beneath the appealing, easy-to-use interface of Mac OS X is a rock-solid, UNIX-based foundation called Darwin that is engineered for stability, reliability, and performance. Darwin integrates a number of technologies, the most important of which are Mach 3.0, operating-system services based on FreeBSD 5, high-performance networking facilities, and support for multiple, integrated file systems. Because the design of Darwin is highly modular, you can dynamically add such things as device drivers, networking extensions, and new file systems.
The following sections describe some of the key features of Darwin. For pointers to more information, see Getting Started with Darwin.
Mach is at the heart of Darwin because it provides some of the most critical functions of the operating system. Much of what Mach provides is transparent to applications. It manages processor resources such as CPU usage and memory, handles scheduling, enforces memory protection, and implements a messaging-centered infrastructure for untyped interprocess communication, both local and remote. Mach provides many important advantages to Macintosh computing:
Protected memory. The stability of an operating system should not depend on all executing applications being good citizens. Even a well-behaved process can accidentally write data into the address space of the system or another process, which can result in the loss or corruption of data or even precipitate system crashes. Mach ensures that an application cannot write in another application’s memory or in the operating system’s memory. By walling off applications from each other and from system processes, Mach makes it virtually impossible for a single poorly behaved application to damage the rest of the system. Best of all, if an application crashes as the result of its own misbehavior, the crash affects only that application and not the rest of the system.
Preemptive multitasking. With Mach, processes share the CPU efficiently. Mach watches over the computer’s processor, prioritizing tasks, making sure activity levels are at the maximum, and ensuring that every task gets the resources it needs. It uses certain criteria to decide how important a task is and therefore how much time to allocate to it before giving another task its turn. Your process is not dependent on another process yielding its processing time.
Advanced virtual memory. In Mac OS X, virtual memory is “on” all the time. The Mach virtual memory system gives each process its own private virtual address space. For 32-bit applications, this virtual address space is 4 GB. For 64-bit applications, the theoretical maximum is approximately 18 exabytes, or 18 billion billion bytes. Mach maintains address maps that control the translation of a task’s virtual addresses into physical memory. Typically only a portion of the data or code contained in a task’s virtual address space resides in physical memory at any given time. As pages are needed, they are loaded into physical memory from storage. Mach augments these semantics with the abstraction of memory objects. Named memory objects enable one task (at a sufficiently low level) to map a range of memory, unmap it, and send it to another task. This capability is essential for implementing separate execution environments on the same system.
Real-time support. This feature guarantees low-latency access to processor resources for time-sensitive media applications.
Mach also enables cooperative multitasking, preemptive threading, and cooperative threading.
Darwin offers an object-oriented framework for developing device drivers called the I/O Kit framework. This framework facilitates the creation of drivers for Mac OS X and provides much of the infrastructure that they need. It is written in a restricted subset of C++. Designed to support a range of device families, the I/O Kit is both modular and extensible.
Device drivers created with the I/O Kit acquire several important features:
True plug and play
Dynamic device management (“hot plugging”)
Power management (for both desktops and portables)
If your device conforms to standard specifications, such as those for mice, keyboards, audio input devices, modern MIDI devices, and so on, it should just work when you plug it in. If your device doesn’t conform to a published standard, you can use the I/O Kit resources to create a custom driver to meet your needs. Devices such as AGP cards, PCI and PCIe cards, scanners, and printers usually require custom drivers or other support software in order to work with Mac OS X.
For information on creating device drivers, see I/O Kit Device Driver Design Guidelines.
Integrated with Mach is a customized version of the Berkeley Software Distribution (BSD) operating system (currently FreeBSD 5). Darwin’s implementation of BSD includes much of the POSIX API, which higher-level applications can also use to implement basic application features. BSD serves as the basis for the file systems and networking facilities of Mac OS X. In addition, it provides several programming interfaces and services, including:
The process model (process IDs, signals, and so on)
Basic security policies such as file permissions and user and group IDs
Threading support (POSIX threads)
Networking support (BSD sockets)
For more information about the FreeBSD operating system, go to http://www.freebsd.org/. For more information about the boot process of Mac OS X, including how it launches the daemons used to implement key BSD services, see System Startup Programming Topics.
The file-system component of Darwin is based on extensions to BSD and an enhanced Virtual File System (VFS) design. The file-system component includes the following features:
Permissions on removable media. This feature is based on a globally unique ID registered for each connected removable device (including USB and FireWire devices) in the system.
Access control lists (available in Mac OS X version 10.4 and later)
URL-based volume mount, which enables users (via a Finder command) to mount such things as AppleShare and web servers
Unified buffer cache, which consolidates the buffer cache with the virtual-memory cache
Long filenames (255 characters or 755 bytes, based on UTF-8)
Journaling of all file-system types to aid in data recovery after a crash
Because of its multiple application environments and the various kinds of devices it supports, Mac OS X handles file data in many standard volume formats. Table 2-1 lists the supported formats.
Volume format | Description |
---|---|
Also called HFS (hierarchical file system) Plus, or HFS+. This is the default root and booting volume format in Mac OS X. This extended version of HFS optimizes the storage capacity of large hard disks by decreasing the minimum size of a single file. | |
Also called hierarchical file system, or HFS. This is the volume format in Mac OS systems prior to Mac OS 8.1. HFS (like HFS+) stores resources and data in separate forks of a file and makes use of various file attributes, including type and creator codes. | |
Universal Disk Format, used for hard drives and optical disks, including most types of CDs and DVDs. Mac OS X v10.4 supports UDF revisions 1.02 through 1.50 (although you cannot write out Finder Info, resource forks, and other extended attributes in these revisions). Mac OS X v10.5 and later supports reading UDF revisions 1.02 through 2.60 on both block devices and most optical media, and it supports writing to block devices and to DVD-RW and DVD+RW media using UDF 2.00 through 2.50 (except for mirrored metadata partions in 2.50). You can find the UDF specification at http://www.osta.org. | |
The standard format for CD-ROM volumes. | |
The NT File System, used by Windows computers. Mac OS X can read NTFS-formatted volumes but cannot write to them. | |
UNIX File System is a flat (that is, single-fork) disk volume format, based on the BSD FFS (Fast File System), that is similar to the standard volume format of most UNIX operating systems; it supports POSIX file-system semantics, which are important for many server applications. Although UFS is supported in Mac OS X, its use is discouraged. | |
Mac OS X supports the FAT file systems used by many Windows computers. It can read and write FAT-formatted volumes. |
HFS+ volumes support aliases, symbolic links, and hard links, whereas UFS volumes support symbolic links and hard links but not aliases. Although an alias and a symbolic link are both lightweight references to a file or directory elsewhere in the file system, they are semantically different in significant ways. For more information, see “Aliases and Symbolic Links” in File System Overview.
Because Mac OS X is intended to be deployed in heterogeneous networks, it also supports several network file-sharing protocols. Table 2-2 lists these protocols.
File protocol | Description |
---|---|
Apple Filing Protocol, the principal file-sharing protocol in Mac OS 9 systems (available only over TCP/IP transport). | |
Network File System, the dominant file-sharing protocol in the UNIX world. | |
Web-based Distributed Authoring and Versioning, an HTTP extension that allows collaborative file management on the web. | |
SMB/CIFS, a file-sharing protocol used on Windows and UNIX systems. |
Mac OS X is one of the premier platforms for computing in an interconnected world. It supports the dominant media types, protocols, and services in the industry as well as differentiated and innovative services from Apple.
The Mac OS X network protocol stack is based on BSD. The extensible architecture provided by network kernel extensions, summarized in “Networking Extensions,” facilitates the creation of modules implementing new or existing protocols that can be added to this stack.
Mac OS X provides built-in support for a large number of network protocols that are standard in the computing industry. Table 2-3 summarizes these protocols.
Apple also implements a number of file-sharing protocols; see Table 2-2 for a summary of these protocols.
Apple includes the following legacy network products in Mac OS X to ease the transition from earlier versions of the Mac OS.
AppleTalk is a suite of network protocols that is standard on the Macintosh and can be integrated with other network systems. Mac OS X includes minimal support for compatibility with legacy AppleTalk environments and solutions.
Open Transport implements industry-standard communications and network protocols as part of the I/O system. It helps developers incorporate networking services in their applications without having to worry about communication details specific to any one network.
These protocols are provided to support legacy applications, such as those running in the Classic environment. You should never use these protocols for any active development. Instead, you should use newer networking technologies such as CFNetwork.
Mac OS X supports the network technologies listed in Table 2-4.
Mac OS X is a powerful and easy-to-use desktop operating system but can also serve as the basis for powerful server solutions. Some businesses or organizations have small networks that could benefit from the services of a router, and Mac OS X offers IP routing support for just these occasions. With IP routing, a Mac OS X computer can act as a router or even as a gateway to the Internet. The Routing Information Protocol (RIP) is used in the implementation of this feature.
Mac OS X also allows multihoming and IP aliasing. With multihoming, a computer host is physically connected to multiple data links that can be on the same or different networks. IP aliasing allows a network administrator to assign multiple IP addresses to a single network interface. Thus one computer running Mac OS X can serve multiple websites by acting as if it were multiple servers.
Introduced in Mac OS X version 10.2, Bonjour is Apple’s implementation of zero-configuration networking. Bonjour enables the dynamic discovery of computer services over TCP/IP networks without the need for any complex user configuration of the associated hardware. Bonjour helps to connect computers and other electronic devices by providing a mechanism for them to advertise and browse for network-based services. See “Bonjour” for more information.
NetBoot is most often used in school or lab environments where the system administrator needs to manage the configuration of multiple computers. NetBoot computers share a single System folder, which is installed on a centralized server that the system administrator controls. Users store their data in home directories on the server and have access to a common Applications folder, both of which are also commonly installed on the server.
To support NetBoot, applications must be able to run from a shared, locked volume and write a user’s personal data to a different volume. Preferences and user-specific data should always be stored in the Preferences folder of the user’s home directory. Users should also be asked where they want to save their data, with the user’s Documents folder being the default location. Applications must also remember that multiple users may run the application simultaneously.
See Technical Note TN1151, “Creating NetBoot Server–Friendly Applications,” for additional information. For information on how to write applications that support multiple simultaneous users, see Multiple User Environments.
Personal Web Sharing allows users to share information with other users on an intranet, no matter what type of computer or browser they are using. Basically, it lets users set up their own intranet site. Apache, the most popular web server on the Internet, is integrated as the system’s HTTP service. The host computer on which the Personal Web Sharing server is running must be connected to a TCP/IP network.
Darwin offers kernel developers a technology for adding networking capabilities to the operating system: network kernel extensions (NKEs). The NKE facility allows you to create networking modules and even entire protocol stacks that can be dynamically loaded into the kernel and unloaded from it. NKEs also make it possible to configure protocol stacks automatically.
NKE modules have built-in capabilities for monitoring and modifying network traffic. At the data-link and network layers, they can also receive notifications of asynchronous events from device drivers, such as when there is a change in the status of a network interface.
For information on how to write an NKE, see Network Kernel Extensions Programming Guide.
Introduced in Mac OS X version 10.4, network diagnostics is a way of helping the user solve network problems. Although modern networks are generally reliable, there are still times when network services may fail. Sometimes the cause of the failure is beyond the ability of the desktop user to fix, but sometimes the problem is in the way the user’s computer is configured. The network diagnostics feature provides a diagnostic application to help the user locate problems and correct them.
If your application encounters a network error, you can use the new diagnostic interfaces of CFNetwork to launch the diagnostic application and attempt to solve the problem interactively. You can also choose to report diagnostic problems to the user without attempting to solve them.
For more information on using this feature, see the header files of CFNetwork.
Darwin includes all of the scripting languages commonly found in UNIX-based operating systems. In addition to the scripting languages associated with command-line shells (such as bash
and csh
), Darwin also includes support for Perl, Python, Ruby, and others.
In Mac OS X v10.5, Darwin added support for several new scripting features. In addition to adding support for Ruby on Rails, Mac OS X also added scripting bridges to the Objective-C classes of Cocoa. These bridges let you use Cocoa classes from within your Python and Ruby scripts. For information about using these bridges, see Ruby and Python Programming Topics for Mac OS X.
For information about scripting tools, see “Scripting Tools.” For information on using command-line shells, see “Command Line Primer.”
Mac OS X provides full support for creating multiple preemptive threads of execution inside a single process. Threads let your program perform multiple tasks in parallel. For example, you might create a thread to perform some lengthy calculations in the background while a separate thread responds to user events and updates the windows in your application. Using multiple threads can often lead to significant performance improvements in your application, especially on computers with multiple CPU cores. Multithreaded programming is not without its dangers though and requires careful coordination to ensure your application’s state does not get corrupted.
All user-level threads in Mac OS X are based on POSIX threads (also known as pthreads). A pthread is a lightweight wrapper around a Mach thread, which is the kernel implementation of a thread. You can use the pthreads API directly or use any of the threading packages offered by Cocoa, Carbon, or Java, all of which are implemented using pthreads. Each threading package offers a different combination of flexibility versus ease-of-use. All offer roughly the same performance, however.
For more information about threading support and guidelines on how to use threads safely, see Threading Programming Guide.
In Mac OS X v10.3 and later, the X11 windowing system is provided as an optional installation component for the system. This windowing system is used by many UNIX applications to draw windows, controls, and other elements of graphical user interfaces. The Mac OS X implementation of X11 uses the Quartz drawing environment to give X11 windows a native Mac OS X feel. This integration also makes it possible to display X11 windows alongside windows from native applications written in Carbon and Cocoa.
The underlying architecture of Mac OS X executables was built from the beginning with flexibility in mind. This flexibility has become important as Macintosh computers have transitioned from using PowerPC to Intel CPUs and from supporting only 32-bit applications to 64-bit applications in Mac OS X v10.5. The following sections provide an overview of the types of architectures you can support in your Mac OS X executables along with other information about the runtime and debugging environments available to you.
When Mac OS X was first introduced, it was built to support a 32-bit PowerPC hardware architecture. With Apple’s transition to Intel-based Macintosh computers, Mac OS X added initial support for 32-bit Intel hardware architectures. In addition to 32-bit support, Mac OS X v10.4 added some basic support for 64-bit architectures as well and this support was expanded in Mac OS X v10.5. This means that applications and libraries can now support four different architectures:
32-bit Intel (i386
)
32-bit PowerPC (ppc
)
64-bit Intel (x86_64
)
64-bit PowerPC (ppc64
)
Although applications can support all of these architectures in a single binary, doing so is not required. That does not mean application developers can pick a single architecture and use that alone, however. It is recommended that developers create their applications as “universal binaries” so that they run natively on both 32-bit Intel and PowerPC processors. If performance or development need warrants it, you might also add support for the 64-bit versions of each architecture.
Because libraries can be linked into multiple applications, you might consider supporting all of the available architectures when creating them. Although supporting all architectures is not required, it does give developers using your library more flexibility in how they create their applications and is recommended.
Supporting multiple architectures requires careful planning and testing of your code for each architecture. There are subtle differences from one architecture to the next that can cause problems if not accounted for in your code. For example, the PowerPC and Intel architectures use different endian structures for multi-byte data. In addition, some built-in data types have different sizes in 32-bit and 64-bit architectures. Accounting for these differences is not difficult but requires consideration to avoid coding errors.
Xcode provides integral support for creating applications that support multiple hardware architectures. For information about tools support and creating universal binaries to support both PowerPC and Intel architectures, see Universal Binary Programming Guidelines, Second Edition. For information about 64-bit support in Mac OS X, including links to documentation for how to make the transition, see “64-Bit Support.”
Mac OS X was initially designed to support binary files on computers using a 32-bit architecture. In Mac OS X version 10.4, however, support was introduced for compiling, linking, and debugging binaries on a 64-bit architecture. This initial support was limited to code written using C or C++ only. In addition, 64-bit binaries could link against the Accelerate framework and libSystem.dylib
only.
In Mac OS X v10.5, most system libraries and frameworks are now 64-bit ready, meaning they can be used in both 32-bit and 64-bit applications. The conversion of frameworks to support 64-bit required some implementation changes to ensure the proper handling of 64-bit data structures; however, most of these changes should be transparent to your use of the frameworks. Building for 64-bit means you can create applications that address extremely large data sets, up to 128TB on the current Intel-based CPUs. On Intel-based Macintosh computers, some 64-bit applications may even run faster than their 32-bit equivalents because of the availability of extra processor resources in 64-bit mode.
Although most APIs support 64-bit development, some older APIs were not ported to 64-bit or offer restricted support for 64-bit applications. Many of these APIs are legacy Carbon managers that have been either wholly or partially deprecated in favor of more modern equivalents. What follows is a partial list of APIs that will not support 64-bit. For a complete description of 64-bit support in Carbon, see 64-Bit Guide for Carbon Developers.
Code Fragment Manager (use the Mach-O executable format instead)
Desktop Manager (use Icon Services and Launch Services instead)
Display Manager (use Quartz Services instead)
QuickDraw (use Quartz or Cocoa instead)
QuickTime Musical Instruments (use Core Audio instead)
Sound Manager (use Core Audio instead)
In addition to the list of deprecated APIs, there are a few modern APIs that are not deprecated, but which have not been ported to 64-bit. Development of 32-bit applications with these APIs is still supported, but if you want to create a 64-bit application, you must use alternative technologies. Among these APIs are the following:
The entire QuickTime C API (not deprecated, but developers should use QuickTime Kit instead in 64-bit applications)
HIToolbox, Window Manager, and most other Carbon user interface APIs (not deprecated, but developers should use Cocoa user interface classes and other alternatives); see 64-Bit Guide for Carbon Developers for the list of specific APIs and transition paths.
Mac OS X uses the LP64 model that is in use by other 64-bit UNIX systems, which means fewer headaches when porting from other operating systems. For general information on the LP64 model and how to write 64-bit applications, see 64-Bit Transition Guide. For Cocoa-specific transition information, see 64-Bit Transition Guide for Cocoa. For Carbon-specific transition information, see 64-Bit Guide for Carbon Developers.
Mac OS X is capable of loading object files that use several different object-file formats, including the following:
Of these formats, the Mach-O format is the format used for all native Mac OS X application development. The Java bytecode format is a format executed through the Hotspot Java virtual machine and used exclusively for Java-based programs. The PEF format is handled by the Code Fragment Manager and is a legacy format that was used for transitioning Mac OS 9 applications to Mac OS X.
For information about the Mach-O file format, see Mac OS X ABI Mach-O File Format Reference. For additional information about using Mach-O files, see Mach-O Programming Topics. For information about Java support in Mac OS X, see “Java Support.” For information about the PEF format and Code Fragment Manager, see “CFM Runtime Environment”
Whenever you debug an executable file, the debugger uses symbol information generated by the compiler to associate user-readable names with the procedure and data address it finds in memory. Normally, this user-readable information is not needed by a running program and is stripped out (or never generated) by the compiler to save space in the resulting binary file. For debugging, however, this information is very important to be able to understand what the program is doing.
Mac OS X supports two different debug file formats for compiled executables: stabs and DWARF. The stabs format is present in all versions of Mac OS X and until the introduction of Xcode 2.4 was the default debugging format. Code compiled with Xcode 2.4 and later uses the DWARF debugging format by default. When using the stabs format, debugging symbols, like other symbols are stored in the symbol table of the executable; see Mac OS X ABI Mach-O File Format Reference. With the DWARF format, however, debugging symbols are stored either in a specialized segment of the executable or in a separate debug-information file.
For information about the DWARF standard, go to http://www.dwarfstd.org. For information about the stabs debug file format, see STABS Debug Format. For additional information about Mach-O files and their stored symbols, see Mach-O Programming Topics.
Since its first release, Mac OS X has supported several different environments for running applications. The most prominent of these environments is the Dyld environment, which is also the only environment supported for active development. Most of the other environments provided legacy support during the transition from Mac OS 9 to Mac OS X and are no longer supported for active development. The following sections describe the runtime environments you may encounter in various versions of Mac OS X.
The dyld runtime environment is the native environment in Mac OS X and is used to load, link, and execute Mach-O files. At the heart of this environment is the dyld
dynamic loader program, which handles the loading of a program’s code modules and associated dynamic libraries, resolves any dependencies between those libraries and modules, and begins the execution of the program.
Upon loading a program’s code modules, the dynamic loader performs the minimal amount of symbol binding needed to launch your program and get it running. This binding process involves resolving links to external libraries and loading them as their symbols are used. The dynamic loader takes a lazy approach to binding individual symbols, doing so only as they are used by your code. Symbols in your code can be strongly-linked or weakly-linked. Strongly-linked symbols cause the dynamic loader to terminate your program if the library containing the symbol cannot be found or the symbol is not present in the library. Weakly-linked symbols terminate your program only if the symbol is not present and an attempt is made to use it.
For more information about the dynamic loader program, see dyld
. For information about building and working with Mach-O executable files, see Mach-O Programming Topics.
The Java runtime environment consists of the HotSpot Java virtual machine, the “just-in-time” (JIT) bytecode compiler, and code packages containing the standard Java classes. For more information about Java support in Mac OS X, see “Java Support.”
The Code Fragment Manager (CFM) runtime environment is a legacy environment inherited from Mac OS 9. Mac OS X provides this environment to support applications that want to use the modern features of Mac OS X but have not yet been converted over to the dyld environment for various reasons. The CFM runtime environment expects code modules to be built using the Preferred Executable Format (PEF).
Unlike the dyld environment, the CFM runtime environment takes a static approach to symbol binding. At runtime, the CFM library manager binds all referenced symbols when the code modules are first loaded into memory. This binding occurs regardless of whether those symbols are actually used during the program’s course of execution. If a particular symbol is missing, the program does not launch. (An exception to this rule occurs when code modules are bound together using weak linking, which explicitly permits symbols to be missing as long as they are never used.)
Because all system libraries are implemented using Mach-O and dyld, Mac OS X provides a set of libraries to bridge calls between CFM code and system libraries. This bridging is transparent but incurs a small amount of overhead for CFM-based programs. The Carbon library is one example of a bridged library.
Note: The libraries bridge only from CFM to dyld; they do not bridge calls going in the opposite direction. It is possible for a dyld-based application to make calls into a CFM-based library using the CFBundle facility, but this solution is not appropriate for all situations. If you want a library to be available to all Mac OS X execution environments, build it as a dyld-based library.
On Intel-based Macintosh computers, CFM binaries are run under the Rosetta environment.
The Classic compatibility environment (or simply, Classic environment) is called a “software compatibility” environment because it enabled Mac OS X to run applications built for Mac OS 9.1 or 9.2. The Classic environment is not an emulator; it is a hardware abstraction layer between an installed Mac OS 9 System Folder and the Mac OS X kernel environment. Because of architectural differences, applications running in the Classic environment do not share the full advantages of the kernel environment.
The Classic environment is supported only on PowerPC-based Macintosh computers and is deprecated in Mac OS X v10.5 and later. You should not be doing any active development using the Classic environment. If you want to write programs to run in Mac OS X, you should use the dyld environment instead.
The Classic environment is not supported on Intel-based Macintosh computers.
The roots of Mac OS X in the UNIX operating system provide a robust and secure computing environment whose track record extends back many decades. Mac OS X security services are built on top of two open-source standards: BSD (Berkeley Software Distribution) and CDSA (Common Data Security Architecture). BSD is a form of the UNIX operating system that provides basic security for fundamental services, such as file and network access. CDSA provides a much wider array of security services, including finer-grained access permissions, authentication of users’ identities, encryption, and secure data storage. Although CDSA has its own standard API, it is complex and does not follow standard Macintosh programming conventions. Therefore, Mac OS X includes its own security APIs that call through to the CDSA API for you.
In Mac OS X v10.5 several improvements were made to the underlying operating system security, including the addition of the following features:
Adoption of the Mandatory Access Control (MAC) framework, which provides a fine-grained security architecture for controlling the execution of processes at the kernel level. This feature enables the “sandboxing” of applications, which lets you limit the access of a given application to only those features you designate.
Support for code signing and installer package signing. This feature lets the system validate applications using a digital signature and warn the user if an application is tampered with.
Compiler support for fortifying your source code against potential security threats. This support includes options to disallow the execution of code located on the stack or other portions of memory containing data. It also includes some new GCC compiler warnings.
Support for putting unknown files into quarantine. This is especially useful for developers of web browsers or other network-based applications that receive files from unknown sources. The system prevents access to quarantined files unless the user explicitly approves that access.
For an introduction to Mac OS X security features, see Security Overview.
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, the FSEvents API notifies your application when changes occur in the file system. You can use file system events to monitor directories for any changes, such as the creation, modification, or removal of contained files and directories. Although kqueues provide similar behavior, the FSEvents API provides a much simpler way to monitor many directories at once. For example, you can use file system events to monitor entire file system hierarchies rooted at a specific directory and still receive notifications about individual directories in the hierarchy. The implementation of file system events is lightweight and efficient, providing built-in coalescing when multiple changes occur within a short period of time to one or many directories.
The FSEvents API is not intended for detecting fine-grained changes to individual files. You would not use this to detect changes to an individual file as in a virus checker program. Instead, you might use FSEvents to detect general changes to a file hierarchy. For example, you might use this technology in backup software to detect what files changed. You might also use it to monitor a set of data files your application uses, but which can be modified by other applications as well.
For information on how to use the FSEvents API, see File System Events Programming Guide.
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 system and are described in the kqueue
and kevent
man pages.
Starting with Mac OS X version 10.3, applications can take advantage of a system-level notification API. This notification mechanism is defined in the /usr/include/notify.h
system header. BSD notifications offer some advantages over the Core Foundation notification mechanism, including the following:
Clients can receive BSD notifications through several different mechanisms, including Mach ports, signals, and file descriptors.
BSD notifications are more lightweight and efficient than other notification techniques.
BSD notifications can be coalesced if multiple notifications are received in quick succession.
You can add support for BSD notifications to any type of program, including Carbon and Cocoa applications. For more information, see Mac OS X Notification Overview or the notify
man page.
Sockets and ports provide a portable mechanism for communicating between applications in Mac OS X. A socket represents one end of a communications channel between two processes either locally or across the network. A port is a channel between processes or threads on the local computer. Applications can set up sockets and ports to implement fast, efficient messaging between processes.
The Core Foundation framework includes abstractions for sockets (CFSocket/CFRunLoop) and ports (CFMessagePort). You can use CFSocket with CFRunLoop to multiplex data received from a socket with data received from other sources. This allows you to keep the number of threads in your application to an absolute minimum, which conserves system resources and thus aids performance. Core Foundation sockets are also much simpler to use than the raw socket interfaces provided by BSD. CFMessagePort provides similar features for ports.
If you are communicating using an established transport mechanism such as Bonjour or HTTP, a better way to transfer data between processes is with the Core Foundation or Cocoa stream interfaces. These interfaces work with CFNetwork to provide a stream-based way to read and write network data. Like sockets, streams and CFNetwork were designed with run loops in mind and operate efficiently in that environment.
CFSocket and its related functions are documented in CFSocket Reference. For information about Core Foundation streams, see CFReadStream Reference and CFWriteStream Reference. For information about Cocoa streams, see the description of the NSStream class in Foundation Framework Reference.
A pipe is a communications channel typically created between a parent and a child process when the child process is forked. Data written to a pipe is buffered and read in first-in, first-out (FIFO) order. You create unnamed pipes between a parent and child using the pipe
function declared in /usr/include/unistd.h
. This is the simplest way to create a pipe between two processes; the processes must, however, be related.
You can also create named pipes to communicate between any two processes. A named pipe is represented by a file in the file system called a FIFO special file. A named pipe must be created with a unique name known to both the sending and the receiving process.
Note: Make sure you give your named pipes appropriate names to avoid unwanted collisions caused by the presence of multiple simultaneous users.
Pipes are a convenient and efficient way to create a communications channel between related processes. However, in general use, pipes are still not as efficient as using CFStream. The run loop support offered by CFStream makes it a better choice when you have multiple connections or plan to maintain an open channel for an extended period of time.
The interfaces for CFStream are documented in CFNetwork Programming Guide.
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. Among the available options are the functions in /usr/include/sys/shm.h
, the shm_open
and shm_unlink
routines, and the mmap
routine. 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:
Any process with appropriate permissions can read or write a shared memory region.
Data is never copied. Each process reads the shared memory directly.
Shared memory offers excellent performance.
The disadvantage of shared memory is that it is very fragile. When a data structure in a shared memory region becomes corrupt, all processes that refer to the data structure are affected. In most cases, shared memory regions should also be isolated to a single user session to prevent security issues. For these reasons, shared memory is best used only as a repository for raw data (such as pixels or audio), with the controlling data structures accessed through more conventional interprocess communication.
For information about shm_open
, shm_unlink
, and mmap
, see the shm_open
, shm_unlink
, and mmap
man pages.
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 standard suite, you can also define custom events as needed.
Apple events are part of the Application Services umbrella framework. For information on how to use Apple events, see Apple Events Programming Guide. See also Apple Event Manager Reference for information about the functions and constants used to create, send, and receive Apple events.
A distributed notification is a message posted by any process to a per-computer notification center, which in turn broadcasts the message to any processes interested in receiving it. Included with the notification is the ID of the sender and an optional dictionary containing additional information. The distributed notification mechanism is implemented by the Core Foundation CFNotificationCenter object and by the Cocoa NSDistributedNotificationCenter class.
Distributed notifications are ideal for simple notification-type events. For example, a notification might communicate the status of a certain piece of hardware, such as the network interface or a typesetting machine. However, notifications should not be used to communicate critical information to a specific process. Although Mac OS X makes every effort possible, it does not guarantee the delivery of a notification to every registered receiver.
Distributed notifications are true notifications because there is no opportunity for the receiver to reply to them. There is also no way to restrict the set of processes that receive a distributed notification. Any process that registers for a given notification may receive it. Because distributed notifications use a string for the unique registration key, there is also a potential for namespace conflicts.
For information on Core Foundation support for distributed notifications, see CFNotificationCenter Reference. For information about Cocoa support for distributed notifications, see Notification Programming Topics for Cocoa.
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.
For information on how to use distributed objects in your Cocoa application, see Distributed Objects Programming Topics.
Mach port objects implement a standard, safe, and efficient construct for transferring messages between processes. Despite these benefits, messaging with Mach port objects is the least desirable way to communicate between processes. Mach port messaging relies on knowledge of the kernel interfaces, which may change in a future version of Mac OS X.
All other interprocess communications mechanisms in Mac OS X are implemented using Mach ports at some level. As a result, low-level technologies such as sockets, ports, and streams all offer efficient and reliable ways to communicate with other processes. The only time you might consider using Mach ports directly is if you are writing software that runs in the kernel.
The Core Foundation framework (CoreFoundation.framework
) is a set of C-based interfaces that provide basic data management features for Mac OS X programs. Among the data types you can manipulate with Core Foundation are the following:
Raw data blocks
Although it is C-based, the design of the Core Foundation interfaces is more object-oriented than C. As a result, the opaque types you create with Core Foundation interfaces operate seamlessly with the Cocoa Foundation interfaces. Core Foundation is used extensively in Mac OS X to represent fundamental types of data, and its use in Carbon and other non-Cocoa applications is highly recommended. (For Cocoa applications, use the Cocoa Foundation framework instead.)
For an overview of Core Foundation, see Core Foundation Design Concepts. For additional conceptual and reference material, see the categories of Reference Library > Core Foundation.
Objective-C is a C-based programming language with object-oriented extensions. It is also the primary development language for Cocoa applications. Unlike C++ and some other object-oriented languages, Objective-C comes with its own dynamic runtime environment. This runtime environment makes it much easier to extend the behavior of code at runtime without having access to the original source.
In Mac OS X v10.5, an update to the Objective-C language (called Objective-C 2.0) was introduced, adding support for the following features:
Object properties, which offer an alternative way to declare member variables
Support for garbage collection; see Garbage Collection Programming Guide
A new for
operator syntax for performing fast enumerations of collections
Protocol enhancements
Deprecation syntax
For information about the Objective-C language, see The Objective-C 2.0 Programming Language.
The following sections outline the support provided by Mac OS X for creating Java-based programs.
Note: The developer documentation on the Apple website contains an entire section devoted to Java. There you can find detailed information on the Java environment and accompanying technologies for operating in Mac OS X. For an introduction to the Java environment and pointers to relevant documentation on Java programming in Mac OS X, see Getting Started with Java.
The libraries, JAR files, and executables for the Java application environment are located in the /System/Library/Frameworks/JavaVM.framework
directory. The Java application environment has three major components:
A development environment, comprising the Java compiler (javac
) and debugger (jdb
) as well as other tools, including javap
, javadoc
, and appletviewer
. You can also build Java applications using Xcode.
A runtime environment consisting of Sun’s high-performance HotSpot Java virtual machine, the “just-in-time” (JIT) bytecode compiler, and several basic packages, including java.lang
, java.util
, java.io
, and java.net
.
An application framework containing the classes necessary for building a Java application. This framework contains the Abstract Windowing Toolkit (java.awt
) and Swing (javax.swing
) packages, among others. These packages provide user interface components, basic drawing capabilities, a layout manager, and an event-handling mechanism.
Like Carbon and Cocoa applications, a Java application can be distributed as a double-clickable bundle. The Jar Bundler tool takes your Java packages and produces a Mac OS X bundle. This tool is installed along with Xcode and the rest of the Apple developer tools on the Xcode Tools CD.
If you want to run your Java application from the command line, you can use the java
command. To launch a Java application from another program, use the system exec
call or the Java Runtime.exec
method. To run applets, embed the applet into an HTML page and open the page in Safari.
Java applications can take advantage of Mac OS X technologies such as Cocoa and QuickTime through Sun’s Java Native Interface (JNI). For details on using the JNI on Mac OS X, see Technical Note 2147.
© 2004, 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-10-15)