MAC OS X
In partial fulfillment with the requirements in CS 23 – Operating System Concepts II
Angelica Carla Cells Jose Udel Dela Cruz Jr. Genevieve Oca Raiza Oropesa Seigi Takada Errol Zuñiga Jr.
BSCS III - A
Noli Lucila Jr.
TABLE OF CONTENTS
Mac OS X Table of Contents History Design Principles Kernel Modules Scheduling Memory Management File System I/O IPC Security References
Page 1 2 3 5 10 11 14 17 20 25 29
Mac OS X HISTORY
As a company, Apple has a very long history but Mac OS X's history is actually more closely tied to its current CEO, Steven P. Jobs. Although Steve Jobs founded Apple Computers, now Apple Inc., with his friend Steve "Woz" Wozniak, he was demoted from his executive position on May 31, 1985 and then resigned on September 13, 1985. During his time away he formed a company by the name of NeXT Inc. Steve Jobs' new company was in business from 1985 until December 20, 1996 when it was bought out by Apple. The seed was planted for Mac OS X's birth in 1985 when Steve Jobs met with Paul Berg, a Nobel Laureate and biochemist from Stanford, at an event held in Silicon Valley. Berg complained to Jobs about the of expense in teaching students about recombinant DNA from textbooks instead of in the wet lab. Berg explained to Jobs that he needed Apple to create something similar to a 3M workstation, due to the fact that they had more than 1MB of RAM, a mega pixel display and over a megaflop of performance. Berg's concept for a workstation was far beyond anything that Apple was offering at the time and the concept of a workstation had Steve Jobs contemplating starting a higher education computer company during his last days at Apple in the fall of 1985. This idea led Jobs to starting his own computer company immediately after resigning from Apple on September 13, 1985. Jobs started Next with his fellow Apple employees Bud Tribble, George Crow, Rich Page, and Susan Barnes who were some of the largest contributors to Apple's early successes. NeXTSTEP was intended to be a highly advanced object-oriented programming environment and user interface, and the original plans for the NeXT computer were to purchase an already available operating system to meet NeXT's demanding specifications. They needed an object-oriented programming environment and a Unix-like Mach-based OS for the toolkit to run on. As a result Steve Jobs went to Carnegie Mellon University and recruited Avie Tevanian, one of the original Mach Engineers, to lead NeXT's team of software development. At this time NeXT began development of their operating system using Objective-C just as Mac OS X still uses today. Objective C is a reflective object-oriented programming language that adds Smalltalk-style messaging to C. Jobs unveiled the first NeXT computer that was running NeXTSTEP 0.8 on October 12, 1988 in San Francisco. It wasn't until a year later though that the final version of the product, NeXTSTEP 1.0shipped on September 18, 1989. NeXTSTEP was based on Mach2.5and 4.3BSD just like OS X which today is based on Mach 3and FreeBSD 5. After NeXT's failure as a hardware company in the late 80's and early 90's it began porting the NeXTSTEP OS to run on Intel systems in 1992. NeXT soon after dropped their hardware business altogether and re-named the company NeXT Software, Inc. NeXTSTEP 3 was eventually ported to four different Platforms, PA-RISC, SPARC, Intel x86, and Motorola 68000. Due to the flexible nature of the NeXT OS it became very popular with some popular organizations such as the CIA and various other government organizations. The final part of NeXTSTEP's development continued under the name OpenStep after NeXT teamed up with Sun Microsystems. OpenStep was basically NeXTSTEP without the Mach Unix kernel. OpenStep was supposed to be a toolkit that ran on top of other OS's much like the NeXT originally intended. On December 20, 1996 Apple purchased NeXT Software, Inc. for $429 million. Apple's purchase of NeXT was primarily for the use of the NeXTSTEP as Apple's next operating system which we all know today as Mac OS X.
Mac OS X is the culmination of Apple Inc.'s decade-long search for an operating system to replace the original Mac OS. It has the following design features: Pre-emptive multitasking and memory protection improved the system's ability to run multiple applications simultaneously without them interrupting or corrupting each other. Designed to be portable—to ease the transition from one platform to another. Includes its own software development tools, most prominently an integrated development environment called Xcode. Xcode provides interfaces to compilers that support several programming languages including C, C++, Objective-C, and Java. To permit a smooth transition from Mac OS 9 to Mac OS X, the Carbon Application Programming Interface (API) was created. Applications written with Carbon can be executed natively on both systems. Support the Java Platform as a "preferred software package"—in practice this means that applications written in Java fit as neatly into the operating system as possible while still being cross-platform compatible. Many software packages written for the BSDs or Linux can be recompiled to run on it. Aqua GUI – A fluid graphical user interface with water-like elements. Anti-aliasing of widgets, text, graphics and window elements. ColorSync color matching built into the core drawing engine, for print and multimedia professionals. Drop shadows around window and isolated text elements to provide a sense of depth. Full-color, scalable icons up to 512x512 pixels Human interface guidelines followed by almost all applications, giving them consistent user interface and keyboard shortcuts. New interface elements including sheets (document modal dialog boxes attached to specific windows) and drawers. OpenGL composites windows onto the screen to allow hardware-accelerated drawing. This technology (introduced in version 10.2) is called Quartz Extreme.
Quartz's internal imaging model correlates well with the Portable Document Format (PDF) imaging model, making it easy to output PDF to multiple devices. PDF viewing is built in. Automator – an application designed to create an automatic workflow for different tasks. Dashboard – A full-screen group of small applications called desktop widgets that can be called up and dismissed in one keystroke. Exposé – A feature which includes three functions to help accessibility between windows and desktop. Its functions are to instantly display all open windows as thumbnails for easy navigation to different tasks, display all open windows as thumbnails from the current application, and hide all windows to access the desktop. FileVault – Optional encryption of the user's files with Advanced Encryption Standard (AES). Front Row – A media viewer interface accessed by the Apple Remote.
Global application services – spell and grammar checker, special characters palette, color picker, font chooser and dictionary. Integrated Sync Services – A system which allows applications to access a centralized extensible database for various elements of user data, including calendar and contact items. The operating system manages conflicting edits and data consistency. Spaces – Desktop organization tool which can create and manage multiple virtual desktops and display them in an Exposé-like interface. Cover Flow – is a three-dimensional graphical user interface included with iTunes, the Finder, and other Apple Inc. products for visually skimming through files and digital media libraries via cover artwork. Time Machine – Automatic backup technology that allows users to view and restore previous versions of files and application data. Screen Sharing – Mac OS X v10.5 has inbuilt screen sharing property which is very useful in networking. Finder - is a file browser allowing quick access to all areas of the computer, which has been modified throughout subsequent releases of Mac OS X. Quick Look - is part of Mac OS X Leopard's Finder. It allows for dynamic previews of files, including videos and multi-page documents, without opening their parent applications. Spotlight search technology - is integrated into the Finder since Mac OS X Tiger, allows rapid real-time searches of: data files; mail messages; photos; and other information based on item properties (Meta data) and/or content. The Dock - holds file and folder shortcuts as well as minimized windows.
LAYERS The pieces of software that constitute Mac OS X can be grouped into logical layers as shown below:
XNU: The Kernel The Mac OS X kernel is called XNU which is monolithic. 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 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. XNU's Mach is responsible for various low-level aspects of the system, such as: preemptive multitasking, including kernel threads (POSIX threads on Mac OS X are implemented using kernel threads) protected memory virtual memory management inter-process communication interrupt management real-time support kernel debugging support (the built-in low-level kernel debugger, ddb, is part of XNU's Mach component, and so is kdp, a remote kernel debugging protocol implementation) console I/O 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: A template thread is filled in, and an initial thread is created from this template. It is set to be the "current" thread. Some CPU housekeeping is done. The "Platform Expert" (see below) is initialized (PE_init_platform()), with a flag indicating that the VM is not yet initialized. This saves the boot arguments, the device tree and display information in a state variable. Another call to PE_init_platform() is made after the VM is initialized. Mach VM is initialized. The function machine_startup() is called. It takes some actions based on the boot arguments, performs some housekeeping, starts thermal monitoring for the CPU, and calls setup_main(). setup_main() performs a lot of work: initializing the scheduler, IPC, kernel extension loading, clock, timers, tasks, threads, etc. and finally creates a kernel thread called startup_thread that creates further kernel threads. startup_thread creates a number of other threads (the idle threads, service threads for clock and device, ...). It also initializes the thread reaper, the stack swapin and the periodic scheduler mechanism. It is here that the BSD subsystem is initialized (via bsd_init()). startup_thread becomes the pageout daemon once it finishes its work. 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.
BSD (Berkeley Software Distribution) 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: process model user ids, permissions, basic security policies POSIX API, BSD style system calls TCP/IP stack, BSD sockets, firewall VFS and file systems System V IPC crypto framework various synchronization mechanisms 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: The kernel memory allocator is initialized. The "Platform Expert" (see below) is called upon to see if there are any boot arguments for BSD. VFS buffers/hash tables are allocated and initialized. Process related structures are allocated/initialized. This includes the list of all processes, the list of zombie processes, hash tables for process ids and process groups. Process 0 is created and initialized (credentials, file descriptor table, audit information, limits, etc.). The variable kernproc points to process 0. The machine dependent real-time clock's time and date are initialized. The Unified Buffer Cache is initialized (via ubc_init(), which essentially initializes a Mach VM Zone via zinit(), which allocates a region of memory from the pagelevel allocator). Various VFS structures/mechanisms are initialized: the vnode table, the filesystem event mechanism, the vnode name cache, etc. Each present filesystem time is also initialized. mbufs (memory buffers, used heavily in network memory-management) are initialized via mbinit(). Facilities/subsystems such as syslog, audit, kqueues, aio, and System V IPC are initialized. The kernel's generic MIB (management information base) is initialized. The data link interface layer is initialized. Sockets and protocol families are initialized.
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. Kernel profiling is started, and BSD is "published" as a resource in the IOKit. Ethernet devices are initialized. A Mach Zone is initialized for the vnode pager. BSD tries to mount the root filesystem (which could be coming over the network, for example, a Mac OS X disk image (.dmg) exported over NFS). devfs is mounted on /dev. A new process is created (cloned) from kernproc (process 0). This newly created process has pid 1, and is set to become init (actually mach_init, which starts init). mach_init is loaded and run via bsdinit_task(), which is called by the BSD asynchronous trap handler (bsd_ast()).
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: Exceptions Multiple inheritance Templates RTTI (run-time type information), although I/O Kit has its own run-time typing system The device driver model provided by the I/O Kit has several useful features (in no particular order): Numerous device families (ATA/ATAPI, FireWire, Graphics, HID, Network, PCI, USB, HID, ...) Object oriented abstractions of devices that can be shared Plug-and-play and hot-plugging Power management Preemptive multitasking, threading, protection and data management symmetric multiprocessing, memory
Dynamic matching and loading of drivers (multiple bus types) A database for tracking and maintaining detailed information on instantiated objects (the I/O Registry) A database of all I/O Kit classes available on a system (the I/O Catalog) An extensive API Mechanisms/interfaces for applications and user-space drivers to communicate with the I/O Kit
Driver stacking 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).
KEXTs I/O-Kit drivers are dynamically linked at runtime, as so-called “KEXTs” (“Kernel Extensions”). KEXT can not only link against the I/O-Kit component, but also against other parts of the kernel. This way, filesystem and networking KEXTs (NKEs) are possible. Every KEXT, which typically resides in /System/Library/Extensions, is a bundle, i.e. a subdirectory which contains the actual binary and an XML description of dependencies and the parts of the kernel it links against.
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: Building the device tree. Parse certain boot arguments. Identify the machine (including processor and bus clock speeds). Initialize a "user interface" to be used in case of kernel panics.
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: Dynamic object allocation, construction, destruction (including data structures such as Arrays, Booleans, Dictionaries, ...). Certain atomic operations, miscellaneous functions (bcmp(), memcmp(), strlen(), ...). Provisions for tracking the number of current instances for each class Ways to avoid the "Fragile Base Class Problem".
Libsa provides functions for miscellaneous purposes: binary searching, symbol remangling, dgraphs, catalogs, kernel extension management, sorting, patching vtables, etc.
SCHEDULING * Mac OS X uses preemptive scheduling preemptive scheduling – takes place when a process switches from running to ready state and switches from waiting to ready Scheduling Automated Tasks 1. Folder Actions Folder Actions are scripts which can be "attached" to specific folders. When files are dropped or saved into a folder, their attached actions will run. For instance, you can set a folder to automatically upload any file placed into it to a certain location. This lets you schedule a task based not on a specific time, but rather on when files are ready for the task.
2. iCal Alarms iCal's alarm feature can be used to schedule tasks on your Mac, though OS X seems to make no mention of it. You can specify to open a file (or launch an application) as your alarm. Using this method, you can schedule any task on your computer, and you have all of the versatility built into iCal for scheduling it.
iCalAlarm dialogue box
3. Cron UNIX includes a program named 'cron' to handle the execution of tasks on a specified schedule, regardless of whether the user is logged in or not. Cron does this through a series of simple text files known as 'crontabs' which control the scheduling of jobs. The system cron tasks are stored in /etc/crontab. You can "cat" this file to get an example of what a crontab looks like: user% cat /etc/crontab # $NetBSD: crontab,v 1.13 1997/10/26 13:36:31 lukem Exp $ # # /etc/crontab - root's crontab # SHELL=/bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin HOME=/var/log #min */10 hour * * mday * month * wday root user command
# do daily/weekly/monthly maintenance 15 3 * * * root sh /etc/daily... 30 4 * * 6 root sh /etc/weekly... 30 5 1 * * root sh /etc/monthly...
Memory Management in Mac OS X
Unlike earlier versions of Mac OS, Mac OS X includes a fully-integrated virtual memory system that you cannot turn off. It is always on, providing up to 4 gigabytes of addressable space per 32-bit process and approximately 18 exabytes of addressable space for 64-bit processes. However, few machines have this much dedicated RAM for the entire system, much less for a single process. To compensate for this limitation, the virtual memory system uses hard disk storage to hold data not currently in use. This hard disk storage is sometimes called the “swap” space because of its use as storage for data being swapped in and out of memory. Virtual Memory in Mac OS X In Mac OS X, each process has its own sparse 32-bit or 64-bit virtual address space. For 32-bit processes, each process has an address space that can grow dynamically up to a limit of four gigabytes. For 64-bit processes, the address space can grow dynamically up to a limit of approximately 18 exabytes. As an application uses up space, the virtual memory system allocates additional swap file space on the root file system. The virtual address space of a process consists of mapped regions of memory. Each region of memory in the process represents a specific set of virtual memory pages. A region has specific attributes controlling such things as inheritance (portions of the region may be mapped from “parent” regions), write-protection, and whether it is “wired” (that is, it cannot be paged out). Because regions contain a given number of pages, they are page-aligned, meaning the starting address of the region is also the starting address of a page and the ending address also defines the end of a page.
The kernel associates a VM object with each region of the virtual address space. The kernel uses the VM object to track and manage the resident and nonresident pages of that region. A region can map either to an area of memory in the backing store or to a specific file-mapped file in the file system. The VM object maps regions in the backing store through the default pager and maps file-mapped files through the vnode pager. The default pager is a system manager that maps the nonresident virtual memory pages to backing store and fetches those pages when requested. The vnode pager implements file mapping. The vnode pager uses the paging mechanism to provide a window directly into a file. This mechanism lets you read and write portions of the file as if they were located in memory. A VM object may point to a pager or to another VM object. The kernel uses this self referencing to implement a form of page-level sharing known as copy-on-write. Copy-on-write allows multiple blocks of code (including different processes) to share a page as long as none write to that page. If one process writes to the page, a new, writable copy of the page is created in the address space of the process doing the writing. This mechanism allows the system to copy large quantities of data efficiently. Allocating and Accessing Virtual Memory Applications usually allocate memory using the malloc routine. This routine finds free space on an existing page or allocates new pages using vm_allocate to create space for the new memory block. Through the vm_allocate routine, the kernel performs a series of initialization steps: 1. It maps a range of memory in the virtual address space of this process by creating a map entry; the map entry is a simple structure that defines the starting and ending addresses of the region. 2. The range of memory is backed by the default pager. 3. The kernel creates and initializes a VM object, associating it with the map entry. At this point there are no pages resident in physical memory and no pages in the backing store. Everything is mapped virtually within the system. When a program accesses the region, by reading or writing to a specific address in it, a fault occurs because that address has not been mapped to physical memory. The kernel also recognizes that the VM object has no backing store for the page on which this address occurs. The kernel then performs the following steps for each page fault: 1. It acquires a page from the free list and fills it with zeroes. 2. It inserts a reference to this page in the VM object’s list of resident pages. 3. It maps the virtual page to the physical page by filling in a data structure called the pmap. The pmap contains the page table used by the processor (or by a separate memory management unit) to map a given virtual address to the actual hardware address. Paging Virtual Memory Out The kernel continuously compares the number of physical pages in the free list against a threshold value. When the number of pages in the free list dips below this threshold, the kernel reclaims physical pages for the free list by swapping inactive pages out of memory. To do this, the kernel iterates all resident pages in the active and inactive lists, performing the following steps: 1. If a page in the active list is not recently touched, it is moved to the inactive list. 2. If a page in the inactive list is not recently touched, the kernel finds the page’s VM object. 3. If the VM object has never been paged before, the kernel calls an initialization routine that creates and assigns a default pager object. 4. The VM object’s default pager attempts to write the page out to the backing store. 5. If the pager succeeds, the kernel frees the physical memory occupied by the page and moves the page from the inactive to the free list.
Paging Virtual Memory In The final phase of virtual memory management moves pages in the backing store back into physical memory. A memory access fault initiates the page-in process. Memory access faults occur when code tries to access data at a virtual address that is not mapped to physical memory. There are two kinds of faults: A soft fault occurs when the page of the referenced address is resident in physical memory but is currently not mapped into the address space of this process. A hard fault occurs when the page of the referenced address is not in physical memory but is swapped out to backing store (or is available from a mapped file). This is what is typically known as a page fault.
When any type of fault occurs, the kernel locates the map entry and VM object for the accessed region. The kernel then goes through the VM object’s list of resident pages. If the desired page is in the list of resident pages, the kernel generates a soft fault. If the page is not in the list of resident pages, it generates a hard fault. For soft faults, the kernel maps the physical memory containing the pages to the virtual address space of the process. The kernel then marks the specific page as active. If the fault involved a write operation, the page is also marked as modified so that it will be written to backing store if it needs to be freed later. For hard faults, the VM object’s pager finds the page in the backing store or from the file-mapped file, depending on the type of pager. After making the appropriate adjustments to the map information, the pager moves the page into physical memory and places the page on the active list. As with a soft fault, if the fault involved a write operation, the page is marked as modified. Shared Memory Shared memory is memory that can be written to or read from by two or more processes. Shared memory can be inherited from a parent process, created by a shared memory server, or explicitly created by an application for export to other applications. Uses for shared memory include the following: sharing large resources such as icons or sounds fast communication between one or more processes
Shared memory is fragile. If one program corrupts a section of shared memory, any programs that also use that memory share the corrupted data. Wired Memory Wired memory (also called resident memory) stores kernel code and data structures that should never be paged out to disk. Applications, frameworks, and other user-level software cannot allocate wired memory. However, they can affect how much wired memory exists at any time. There is memory overhead associated with each kernel resource expended on behalf of a program. As you can see, each thread created, each subprocess forked, and each library linked contributes to the resident footprint of the system. In addition to wired memory generated through user-level requests, the following kernel entities also use wired memory: VM objects
the virtual memory buffer cache I/O buffer caches drivers
Wired data structures are also associated with the physical page and map tables used to store virtualmemory mapping information, Both of these entities scale with the amount of available physical memory. Consequently, when you add memory to a system the wired memory increases even if nothing else changes. When the computer is first booted into the Finder, with no other applications running, wired memory consumes approximately 14 megabytes of a 64 megabyte system and 17 megabytes of a 128 megabyte system. Wired memory is not immediately released back to the free list when it becomes invalid. Instead it is “garbage collected” when the free-page count falls below the threshold that triggers page out events.
File System of Mac OS X
The file system in Mac OS X has at its core a set of directories inherited from the Berkeley Software Distribution (BSD) operating system. While most of these directories are actually hidden by the Finder, many elements of the BSD world are still apparent. The file permissions model, symbolic links, and user home directories are all concepts inherited from BSD. Mac OS X also adds many of its own concepts to provide the user with a secure and elegant environment for managing files and folders. The Mac OS X file system was designed to provide power and flexibility while maintaining the traditional ease-of-use users expect. To this end, the file system provides users with a consistent structure that makes it clear where resources are located. (This consistency also helps developers, whose applications need to know where important resources are located.) Other file system conventions, such as aliases, extension hiding, and display names also enhance the user experience. File-System Domains On a multi-user system, controlling access to system resources is important for maintaining the stability of the system. Mac OS X defines several file-system domains, each of which provides storage for resources in an established set of directories. Access to resources in each domain is determined by the permissions for the current user. There are four file-system domains: User. The user domain contains resources specific to the user who is logged in to the system. This domain is defined by the user’s home directory, which can either be on the boot volume (/Users) or on a network volume. The user has complete control of what goes into this domain. Local. The local domain contains resources such as applications and documents that are shared among all users of a particular system but are not needed for the system to run. The local domain does not correspond to a single physical directory, but instead consists of several directories on the local boot (and root) volume. Users with system administrator privileges can add, remove, and modify items in this domain. Network. The network domain contains resources such as applications and documents that are shared among all users of a local area network. Items in this domain are typically located on network file servers and are under the control of a network administrator. System. The system domain contains the system software installed by Apple. The resources in the system domain are required by the system to run. Items in this domain are located on the local boot (and root) volume. Users cannot add, remove, or alter items in this domain.
The domain for a given resource determines its applicability or accessibility to the users of the system. Supported File Systems
File System HFS HFS Plus UFS WebDAV UDF FAT SMB/CIFS AFP NFS FTP HFS+
Description Mac OS Standard file system. Standard Macintosh file system for older versions of Mac OS. Mac OS Extended file system. Standard Macintosh file system for Mac OS X. Unix File System. A variant of the BSD “Fast File System.” Used for directly accessing files on the web. For example, iDisk uses WebDAV for accessing files. Universal Disk Format. The standard file system for all forms of DVD media (video, ROM, RAM and RW) and some writable CD formats. The MS-DOS file system, with 16- and 32-bit variants. Used for sharing files with Microsoft Windows SMB file servers. AppleTalk Filing Protocol. The primary network file system for all versions of Mac OS. Network File System. A commonly-used BSD file sharing standard. Mac OS X supports NFSv2 and NFSv3 over TCP and UDP. A file system wrapper for the standard Internet File Transfer Protocol.
HFS+(Hierarchical File System Plus) is the preferred filesystem on Mac OS X. It supports journaling, quotas, byte-range locking, Finder information in metadata, multiple encodings, hard and symbolic links, aliases, support for hiding file extensions on a per-file basis, etc. HFS+ uses B-Trees heavily for many of its internals. Like HFS, HFS Plus uses B*-trees to store most volume metadata. HFS+ is architecturally similar to HFS, with several important improvements such as: 32 bits used for allocation blocks (instead of 16). HFS divides the disk space on a partition into equal-sized allocation-blocks. Since 16 bits are used to refer to an allocation-block, there can be at most 216 allocation blocks on an HFS filesystem. Thus, using 32 bits for identifying allocation blocks results in much less wasted space (and more files). Long file names up to 255 characters Unicode based file name encoding File/Directory attributes can be extended in future (as opposed to being fixed size) In addition to a System Folder ID (for starting Apple operating systems), a dedicated startup file that can easily be found (its location and size are stored in the volume header in a fixed location) during startup, is also supported so that non-Apple systems can boot from a HFS+ filesystem Largest file size is 263 bytes
UFS (Unix File System) The Unix file system (UFS) is a file system used by many Unix and Unix-like operating systems. It is also called the Berkeley Fast File System, the BSD Fast File System or FFS. It is a distant descendant of the original filesystem used by Version 7 Unix.
A UFS volume is composed of the following parts: a few blocks at the beginning of the partition reserved for boot blocks (which must be initialized separately from the file system) a superblock, containing a magic number identifying this as a UFS file system, and some other vital numbers describing this file system's geometry and statistics and behavioral tuning parameters a collection of cylinder groups. Each cylinder group has the following components: o a backup copy of the superblock o a cylinder group header, with statistics, free lists, etc, about this cylinder group, similar to those in the superblock o a number of inodes, each containing file attributes o a number of data blocks
Inodes are numbered sequentially. The first several inodes are reserved for historical reasons, followed by the inode for the root directory. Directory files contain only the list of filenames in the directory and the inode associated with each file. All file metadata is kept in the inode. File System Comparisons Feature Case sensitive Supports multiple file forks Path separator character Supports modification dates Supports creation dates Supports sparse files Supports zero-filling of files Supports aliases Supports symbolic links Supports ACLs Supports creation dates HFS+ No Yes “:” Yes Yes No Yes Yes Yes Yes Yes UFS Yes No “/” Yes No Yes No No Yes No No
Mach OS X I/O
I/O Kit 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. I/O Kit Features 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” mode) 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 data-management 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. Design Principles of the I/O Kit Mac OS X is largely the product of two strains of operating-system technology: Mac OS 9 (and its predecessors) and BSD. Given this pedigree, one might have expected Apple to adopt the devicedriver model of Mac OS 9 or FreeBSD. Instead, Apple chose to redesign the model. Several reasons motivated this decision . First, neither the Mac OS 9 driver model nor the FreeBSD driver model offers a set of features rich enough to meet the needs of 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. Although FreeBSD is capable of handling these features, the BSD model does not offer other features expected in a modern operating system, including automatic configuration, driver stacking, power management, and dynamic loading of devices. Thus 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 operatingsystem 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 the upper layers of the operating system. The compelling part of this abstraction is the implementation of behavior common to all device drivers (or types of device drivers) in the classes of the I/O Kit. As an example, consider virtual memory. In Mac OS 9, virtual memory is not a fundamental part of the operating system; it is an option. Because of this, a developer must always take virtual memory into account when creating a driver, and this raises certain complications. In contrast, virtual memory is an inherent capability of Mac OS X and cannot be turned off. Because virtual memory is a fundamental and assumed capability, knowledge of it is incorporated into system software and driver writers do not have to take it into account. The I/O Kit functions as a kind of foundation and coordinator for device drivers. This is a departure from previous driver models. In Mac OS 9, all software development kits (SDKs) are independent of each other and duplicate common functionality. 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. Mac OS X helps developers take advantage of hardware complexity without requiring them to encode software complexity into each new device driver. In most cases, they need only add the specific code that makes their drivers different. Another part of the design philosophy of the I/O Kit is to make the design completely open. Rather than hiding APIs in an attempt to protect developers from themselves, all I/O Kit source code is available as part of Darwin. Developers can use the source code as an aid to designing (and debugging) new drivers. The Anatomy of an I/O Connection 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. Consider Figure 2-1 which illustrates a typical layering of client and provider objects for a PCI-based Ethernet controller driver in the Network family.
As this diagram shows, your driver typically fits between two families, inheriting from a class in the upper-layer family and using the services of the lower-layer family. In the case of the Ethernet controller, the driver participates in a stack of C++ objects comprising instances of classes from the networking and PCI families:
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.
This figure illustrates how a SCSI disk driver, a member of the Storage family, is connected to the PCI bus. As each individual connection is made, the newly created driver or nub is also added to the I/O Registry. The chain of connections takes place in several steps:
1. The PCI bus controller driver, a member of the PCI family, discovers a PCI device and announces its presence by creating a nub (IOPCIDevice). 2. The nub identifies (matches) an appropriate device driver—in this case, a SCSI controller driver—and requests that it be loaded. Loading the SCSI controller driver causes the SCSI Parallel family, and all families that it depends on, to be loaded as well. The SCSI controller driver is given a reference to the IOPCIDevice nub. 3. The SCSI controller driver, which is a client of the PCI family and a provider of SCSI Parallel family services, scans the SCSI bus for devices that might be clients of these services. Upon finding such a device (a disk), the driver announces the device’s presence by creating a nub (IOSCSIDevice). 4. The nub, by going through the matching procedure, finds a device driver (a disk driver) that is appropriate for the device and requests that this driver be loaded. Loading the disk driver causes the Storage family, and all families that it depends on, to be loaded as well. The disk driver is now a client of the SCSI Parallel family and a member of the Storage family. The disk driver is given a reference to the IOSCSIDevice nub. In many cases, applications and other “user space” programs can use the I/O Kit’s device-interface technology to drive devices (including mass storage devices), obviating the need for a kernel-resident driver. The I/O Kit Class Hierarchy 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
Mach OS X IPC
IPC and Notification Mechanisms Mac OS X supports numerous technologies for interprocess communication (IPC) and for delivering notifications across the system. The following sections describe the available technologies.
FSEvents API 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. Mach IPC 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. Kernel Queues and Kernel Events 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 filesystem 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. Shared Memory 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. Apple Events 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. Distributed Objects 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. Distributed Notifications 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 CocoaNSDistributedNotificationCenter 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. Mach Messaging 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. BSD Notifications 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. Sockets, Ports, and Streams 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. BSD Pipes 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. 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. Mach Messaging and Mach Interprocess Communication (IPC) Mach IPC and Mach messaging are the basis for much of the communication in Mac OS X. In many cases, however, these facilities are used indirectly by services implemented on top of one of them. Mach messaging and IPC are fundamentally similar except that Mach messaging is stateless, which prevents certain types of error recovery, as explained later. Except where explicitly stated, this section treats the two as equivalent. The fundamental unit of Mach IPC is the port. The concept of Mach ports can be difficult to explain in isolation, so instead this section assumes a passing knowledge of a similar concept, that of ports in TCP/IP. In TCP/IP, a server listens for incoming connections over a network on a particular port. Multiple clients can connect to the port and send and receive data in word-sized or multiple-word–sized blocks. However, only one server process can be bound to the port at a time. In Mach IPC, the concept is the same, but the players are different. Instead of multiple hosts connecting to a TCP/IP port, you have multiple Mach tasks on the same computer connecting to a
Mach port. Instead of firewall rules on a port, you have port rights that specify what tasks can send data to a particular Mach port. Also, TCP/IP ports are bidirectional, while Mach ports are unidirectional, much like UNIX pipes. This means that when a Mach task connects to a port, it generally allocates a reply port and sends a message containing send rights to that reply port so that the receiving task can send messages back to the sending task. As with TCP/IP, multiple client tasks can open connections to a Mach port, but only one task can be listening on that port at a time. Unlike TCP/IP, however, the IPC mechanism itself provides an easy means for one task to hand off the right to listen to an arbitrary task. The term receive rights refers to a task’s ability to listen on a given port. Receive rights can be sent from task to task in a Mach message. In the case of Mach IPC (but not Mach messaging), receive rights can even be configured to automatically return to the original task if the new task crashes or becomes unreachable (for example, if the new task is running on another computer and a router crashes). In addition to specifying receive rights, Mach ports can specify which tasks have the right to send data. A task with send rights may be able to send once, or may be able to arbitrarily send data to a given port, depending on the nature of the rights. Using Well-Defined Ports Before you can use Mach IPC for task communication, the sending task must be able to obtain send rights on the receiving task’s task port. Historically, there are several ways of doing this, not all of which are supported by Mac OS X. For example, in Mac OS X, unlike most other Mach derivatives, there is no service server or name server. Instead, the bootstrap task and mach_init subsume this functionality. When a task is created, it is given send rights to a bootstrap port for sending messages to the bootstrap task. Normally a task would use this port to send a message that gives the bootstrap task send rights on another port so that the bootstrap task can then return data to the calling task. Various routines exist in bootstrap.h that abstract this process. Indeed, most users of Mach IPC or Mach messaging actually use Mach remote procedure calls (RPC), which are implemented on top of Mach IPC. Since direct use of IPC is rarely desirable (because it is not easy to do correctly), and because the underlying IPC implementation has historically changed on a regular basis, the details are not covered here. You can find more information on using Mach IPC directly in the Mach 3 Server Writer’s Guide from Silicomp (formerly the Open Group, formerly the Open Software Foundation Research Institute), which can be obtained from the developer section of Apple’s website. While much of the information contained in that book is not fully up-to-date with respect to Mac OS X, it should still be a relatively good resource on using Mach IPC. Remote Procedure Calls (RPC) Mach RPC is the most common use for Mach IPC. It is frequently used for user-kernel communication, but can also be used for task to task or even computer-to-computer communication. Programmers frequently use Mach RPC for setting certain kernel parameters such as a given thread’s scheduling policy. RPC is convenient because it is relatively transparent to the programmer. Instead of writing long, complex functions that handle ports directly, you have only to write the function to be called and a small RPC definition to describe how to export the function as an RPC interface. After that, any application with appropriate permissions can call those functions as if they were local functions, and the compiler will convert them to RPC calls. In the directory osfmk/mach (relative to your checkout of the xnu module from CVS), there are a number of files ending in .defs; these files contain the RPC definitions. When the kernel (or a kernel module) is compiled, the Mach Interface Generator (MIG) uses these definitions to create IPC code
to support the functions exported via RPC. Normally, if you want to add a new remote procedure call, you should do so by adding a definition to one of these existing files. Calling RPC From User Applications RPC, as mentioned previously, is virtually transparent to the client. The procedure call looks like any other C function call, and no additional library linkage is needed. You need only to bring the appropriate headers in with a #include directive. The compiler automatically recognizes the call as a remote procedure call and handles the underlying MIG aspects for you.
SECURITY With Mac OS X, a security strategy is implemented that is central to the design of the operating system, ensuring that your Mac is safe & secure. To enhance security on your computer, Mac OS X provides the following features: 1. 2. 3. 4. 5. Open source foundation Secure default settings Modern security architecture Innovative security applications Rapid response
Security Framework *The security framework in Mac OS X is an implementation of the CDSA architecture. It contains expandable set of cryptographic algorithms to perform code signing & encryption operations while maintaining the security of the cryptographic keys. Control Physical Access
*A firmware password prevents a user with physical access to the computer from starting up from an optical disk, a network boot volume, a separate drive connected in Target Disk Mode, or into singleuser mode. It also requires a password to be entered before the system will start up from its regular boot drive.
Locking your screen
*The ability to require a password to unlock the screensaver comes in handy here. It's a checkbox setting in the Security pane in System Preferences Using ACLs (Access Control Lists) * The traditional Unix file permission model is pretty simple. There are three classes of user: you, people in the same group as you, and everybody else. You can restrict the ability to read from, write to, or execute files in a given directory based on those three ownership roles.
If you need total security for your user data, FileVault is about as close as you can get. Integrated into the Mac OS since v10.3, FileVault basically turns your entire home directory into one big encrypted disk image. It's a special type of disk image that can grow or shrink as necessary (although this only happens when you log out or restart), and it prevents anyone from reading through your home directory even if they have physical access to the machine. Firewall – software that protects the network applications running on your server. IP firewall service, which is part of the Mac OS X Server Software, scans incoming IP packets & rejects or accepts these packets based on a set of filters you create
Watch Your Logs It's never a bad idea to keep an eye on what your computer is doing behind your back. Mac OS X makes this easier with Console.app, tucked away in your /Applications/Utilities folder. Like the best Mac applications, it's designed to do one thing and do it well: allow you to see your Mac's log activity at a glance, and search quickly for specific items.
Use a Virus Scanner The viral risk is mitigated by several new and old features of Mac OS X. By default, files created in a user's home directory are not executable, which helps to lower the risk of infection. By default, downloaded files are dropped into a new Downloads folder in a user's home directory, which helps to keep suspicious files in one easy-to-scan location. Previous versions of the OS warned a user when opening an application for the first time; now, 10.5 applies that scrutiny to all downloaded files, pointing out when they were downloaded and asking if it's really, really okay to open them.
ClamAV is available in a specially-built Mac OS X version and receives just as much (if not more) attention as the for-pay alternatives. By setting it to auto-update and keep a close watch on your Downloads and Documents folders, you're already several significant steps up the security ladder.
Pdf files: 986_inside_the_mac_osx_kernel.pdf MHTML files: Architecture of Mac OS X.mhtml Mac OS X - Wikipedia, the free encyclopedia.mhtml Mac OS X System Architecture.mhtml XNU The Kernel.mhtml HTML files: Architecture of Mac OS X - Wikipedia, the free encyclopedia.html http://developer.apple.com/DOCUMENTATION/Performance/Conceptual/ManagingMemory/A rticles/AboutMemory.html www.kernelthread.com/mac/osx/arch_fs.html - 31k developer.apple.com/DOCUMENTATION/MacOSX/Conceptual/BPFileSystem/index.html 14k developer.apple.com/documentation/Performance/Conceptual/FileSystem/Articles/MacOSX AndFiles.html - 16k