跳到主要内容

Mac OSX 文件系统介绍

OS X系统深入了解--系统文件结构篇

OS X采用的是类UNIX的多用户系统。

    通常我们在启动盘下面都只能看到应用程序、资源库、系统、用户这4个目录。但其实还有很多的隐藏目录,如bin、sbin之类的,这些都是系统的一些资源,一般是不用普通用户去访问,是些比较重要的系统文件及配置文件。

所以我这里就只是探讨一下通常在Finder中可以触及的文件项目和资源。 首先我们来了解一下OS X系统的几大组成部分: 文件系统区域: 作为了一个多用户的操作系统,控制系统资源的访问对于保证系统的稳定性是非常重要的。通过目录的设置,由当前用户的操作权限来决定该用户对每部分资源的访问。 在OS X系统中,存在以下4个文件系统区域: User:这个区域包含了登录到系统的用户可供使用的特定资源。该区域由用户的主目录来定义,在这个区域中,用户具有完全的控制权限。 Local: Local区域包括如文件、程序这些被系统中所有用户共享的资源,但它不是系统运行所必须的。Local区域没有一个相应的单独的目录,它包含于启动卷宗的多个目录中。具有系统管理员权限的用户可以添加、删除或修改此区载的项目。 Network:此区域包含了本地局域网中可被所有用户共享的资源,如文件或应用程序。该区域的代表项目在网络文件服务中的位置,并受网络管理员的控制。 System:包含由Apple安装的系统软件。这此资源是系统正常运行所必须的,位于启动卷宗中,在该区域中,用户不允许添加、删除或更改这些资源。 用户区域包含指定给一个单独的用户的资源。由当前用户的个人目录来表示。每个Mac OS X系统用户必须有一个账号,在文件系统中给每个用户账号指定一个目录空间。目录中包括了用户的应用程序、资源以及文档。用户个人目录以用户账号的短名称来命名,并且是唯一的。 用户区域可以让用户为自己定义一个合理的工作环境,当用户登录时,Finder将恢复用户的工作环境,并按预置设置为用户上次使用时的状态。同样的,应用程序及其它系统软件按程序预置、网络设置、email设置、字体设置及其它设置来进行恢复。 用户的个人目录的位置依赖于用户的账号。如果用户账号是本地账号,那么用户的个人目录则位于启动卷宗的”User”目录中,如果是一个网络账号,则个人目录位于网络服务器中。 无论用户的个人目录实际位置在哪里(实际上,我们还是可以通过终端命令更改个人目录的实际位置的),OS X都使用”~”字符来代表当前登录用户的个人目录。这个符号可以与其它路径来组合使用。

表一:

~ 当前用户目录的顶级目录,相当于”/User/当前用户名”这个目录 /Library/Fonts 当前用户个人目录中的字体储存位置 Steve 用户Steve的个人目录。 说明:这里我们需要注意的是,终端或系统中,我们其实都可以多重登录的,因此,在使用””的时候,连接的是“当前登录用户“的个人目录。所以,当你登录为不同的用户时,””所指的位置并不相当。

表二:

这里我们列出的是个人目录下一些常见的目录: Applications 包含一些只有当前用户可以使用的程序,比如我们安装了一个程序,安装时选Applications,应用程序将会默认安装到这里! Desktop:包含当前用户显示在Finder桌面上的所有项目。 Documents:用户个人的一些文档。经常会包含一些程序使用的文件或者下载的文件,以及程序安装的纪录文件。 Library:包括应用程序设置、预置及其它用户指定的系统资源或设置(具体内容将在下一章中进行说明)。 Movies:QuickTime或其它格式的影片 Music:数字音乐文件(如.aiff, .mp3, .m4p或其它格式),包括iTunes自动倒入的歌曲。 Pictures:图片文件,包括iPhoto自动导入的数码相机中的图片 Public:你可以把需要与其它用户共享的文件放在这个目录中,默认状态下,这个目录可以被其它所有用户访问。 Sites:用户的个人站点网页文件。在被其它用户访问之前,你必须在“系统预置-共享-Web共享“中打开共享。 当新建账号时,”Applications”目录并不会自动添加到该用户的个人目录中。用户可以自已手工建议一个”Applications”,并把自己的程序放在该目录中,系统会自动搜索该目录中的项目。 在’/User’目录中包含一个叫”Shared”的子目录,这个目录可以被本地的所有用户访问(不过请不要把应用程序放置在该目录中),所有用户都可以从该目录中读取或写入文件,用于本地用户的文件交换及共享。 本地区域包括本地计算机所使用的资源,但它不是系统运行所必须的。比较典型的包括:应用程序、实用工具、自定义字体、自定义的启动项目以及应用程序 全局设置。在”Applications” 以及 “Library”目录中也包含了部分资源,这些资源仅代本地用户使用,而网络用户则无法访问。 如果希望本地所有用户共享资源,那么系统管理员可以安装资源到本地区域,苹果公司开发的应用程序都安装在”/Applications” 及 “/Applications/Utilities “目录中,第三方的程序及工具也可以安装在这些目录中。其它的系统资源,如字体、预置以及插件放置在”/Library”相应的子目录中。 网络部分 网络区域包括本地局域网中的的资源。网络用户可以访问程序、文档以及其它资源,包括AplleShare及 Web共享。 表三: /Network/Applications 包括可以被本地局域网中其它用户运行的一些应用程序。 /Network/Library 包含如:插件,音频文件, 文档, 框架, 色彩,及字体这些供本地局域网用户使用的资源. /Network/Servers 包含本地局域网中提供的NFS文件服务的连接 /Network/Users/ 包括所有本地网用户的个人目录。这是个人目录默认的位置。个人目录也可以存储在其它服务器中。 系统区域 系统区域包括了Mac OS X运行所必须的资源,它全部位置于启动盘的”/System”目录中。这些资源由苹果公司提供并只有’root’用户可以修改其内容。管理员用户以及程序将不会安装任何资源在这个目录或直接修改其内容。 默认时,”/System”仅包括一个”Library”子目录,这个子目录包含了许多与其它Library目录相同类型的资源。 请不要手工添加、删除或者修改此目录的资源,否则有可能导致系统无法正常启动。 Library目录 Library目录被用来存储程序及系统特殊资源的一个特殊目录。每个文件系统都有它自己的Library目录。通常,程序可以用它来存储内部数据或临时文件,但不会存储程序本身或用户的数据文件。 它包括很多标准的子目录,系统通常会认为已经存在这些标准的。所以请不要删除Library中的子目录。当然,程序也可以创建新的子目录来储存程序的特殊数据。 Library可以位于启动盘根目录及用户的个人目录中。虽然位置不同,内容及作用大体相同。 唯一的区别就在于:根目录下的Library是本机所有用户的共同设置,而个人目录中的Library则只是该用户的设置。 下面我们将列出在Library常见的一些子目录,你可以通过这个说明来了解这些目录到底有何用途。从而来决定你要作什么。 Library目录中的子目录: Application Support :包括程序的特殊数据以及支持文件,如第三方插件,帮助程序、模板以及被程序使用但不允许操作的附加资源。通常所有的项目都放置在以程序命名的目录中。例 如Adobe公司的程序,都将放在名叫“Adobe“的子目录中,而苹果公司的程序支持则放置在“Apple“这个子目录中。 Assistants:包括程序用来帮助用户设置或完成其它任务的资源。 Audio:包括音频插件及设备驱动。 Caches:再生所必须的缓存数据。 ColorPickers:采集色彩时所依赖的模式的资源。例如HLS或RGB。 ColorSync:色彩管理预置及脚本。 Components:系统组织和功能扩展。 Contextual Menu Items:附加的系统级关联菜单插件,如阿拉丁的解压缩关联菜单、iGetter的关联菜单。 Desktop Pictures:桌面图片目录。 Documentation:文档及用户和管理员使用的苹果帮助文件包(也有的在”Help子目录中”)。 Extensions:包括设备驱动及其它核心功能。类似于OS 9下的”功能扩展”目录。 Favorites:包括经常访问的目录、文件或网站的替身,仅存在于个人目录的库目录中。 Fonts:显示和打印用的字体文件 Frameworks:框架和共享的资源库,开发者可能会安装自己的框架或资源在该目录中。 Image Capture:通常是扫描仪的驱动。 InputManagers:输入法管理, Internet Plug-ins:网络浏览器使用的插件、库及过滤器。如Flash插件、Realplayer插件。 iTunes:第三方的iTunes的插件及库, Java:如果你安装了Java,那么就会有这个目录,包括了Java的一些功能扩展及其它资源。 Keyboard Layouts:键盘布局 Keychains:系统中各个钥匙串的内容。 Logs:控制台及系统服务的记录文件,你可以通过:应用程序-实用程序-控制台来查看。 Modem Scripts:调制解调器脚本,也就是猫的驱动了。 Mail:用户的电子邮件内容,这只存在于每个用户的个人目录的库目录中。 Perl:Perl程序的功能扩展及库,比如Cocoa Conler就需要这个功能。 Plug-ins:系统插件,比如磁盘工具的磁盘映像。 PreferencePanes:系统预置插件,一般显示在系统预置的最下方。如安装阿拉丁解压缩软件时生成的StuffIt AVR.prefPane Preferences:预置目录,包括系统、应用程序及用户的各种设置。通常如果预置文件损坏,会导致程序或系统的操作失常,这个时候可以通过删除相应的预置来尝试解决问题。 Printers:打印机驱动。PPD插件,以及配置打印机所需要的库文件。 QuickTime:QuickTime的插件及功能扩展。 Receipts:安装过的.pkg安装包的替身,但不是.pkg安装包本身。例如系统升级或安装时的.pkg。或vpc安装时的.pkg包。 Screen Savers:屏幕保护文件。 Scripting:AppleScript附加的脚本及脚本资源。 Sherlock Plug-ins:Sherlock兼容的插件及功能扩展。 Sounds:系统警告提示音 StartupItems:系统运行时自动启动的系统及第三方脚本或程序。一般通过系统预置-账号来进行设定。 User Pictures:用户账号中,用户显示的图片的文件。 WebServer:Web服务内容。也就是个人Web共享的内容。包括CGI脚本及网页文件。网页文件放置在Documents子目录中。 文件系统 从体系结构上看,Mac OS X实现了对多文件系统的支持,其中最为重要的文件系统包括 有:Mac OS Extended (HFS+),Mac OS Standard (HFS),UFS, ISO 9660, NFS和 AFP。但 从用户的角度看,文件系统又是单一的。当用户复制,移动或拖移文件和文件夹时,(会感觉似乎)只存在一个文件系统。 文件系统如何被组织 Mac OS X文件系统中的几乎每个文件都有其适合放置的存储这一类型文件的标准目录区域。而对用户来说,这并不意味着他们就必须把应用程序和 应用程序资源放在被推荐的区域。由于应用程序最终会被打包,因此无论他们被安装在哪里,都能满足自身要求。但假如用户没有把某些内容放在系统软件期望的位 置。他们有可能会丧失Mac OS X的一些优势。例如,Finder首先通过搜索应用程序的标准位置来导入应用程序数据库(见“收集应用程序信息”一 节)。一旦这样做,结果有可能会造成一个隶属于某个应用程序(但不在那一区域)的文档,不能在双击时被立即打开。 文件系统的层次通常被表现为一个以“根(root)”开始的分层结构,在典型的Mac OS X文件系统的根目录中(“根”用起始的“/”符号来表示),它包含以下项目: /Mac OS X/–一个特殊的卷,操作系统由它开始启动,系统文件和资源也被安装在其上。这个卷通常是一个被格式为Mac OS扩展格式 (HFS+,Mac OS Extended)的卷(虽然它也可以是UFS卷)。名称“Mac OS X”是它默认的卷名,但用户也可以修改它。 /Network/–作为装载到用户系统上的本地网络的根目录。无论用户是否连接到网络上,/Network/目录(其图标是一个“地球”)将始终出现。 /OtherVolumes/–显示一个或多个被连接的外部设备或不是启动卷的内部设备。其中可以包括有Zip驱动器,CD-ROM驱动器,数码相机,被 装载的网络服务器以及硬盘和它们的分区等。(“OtherVolumes”只是一个真实名称的代表,被连接的卷的实际名称将会是不同的)。 所有非启动卷在它们被装载时出现,被卸载时消失。对此有一个例外,用户的iDisk卷即使在被卸载后也不会消失。 卷的物理结构与Finder向用户所显示的略有不同。假如用Terminal程序看一下目录结构,您会看到启动卷被装载在根目录层(/),而非启动卷被放 在/Volumes/目录中。Finder提供了这种抽象方式,用来在基本的UNIX 系统上提供一个更加传统的Mac OS界面。 像/usr, /bin和/etc等目录都是标准的BSD目录,它们也存在于根目录层,但Finder向用户隐藏了它们。 系统域 系统域包含了要求由Mac OS X来运行的资源。系统域中的所有资源被放置在启动卷上的/System目录下。这些资源由Apple提供,只有root用户可以修改这个目录的内容。管理用户和应用程序不能在系统域中安装资源或是直接修改它的内容。 默认情况下,/System目录仅包含了一个Library子目录。与系统中的其他Library目录一样,这个子目录中包含了许多相同类型的资 源。然而在系统域中,这个目录还包含了构成Mac OS X系统的许多核心服务,框架和应用户程序。关于Library目录的更多信息,请参见 “Library 目录”一节。 —————————————————————— Library目录 Library是一个特殊的目录,用于存储特定的应用程序和特定的系统资源。每个文件系统域都有其自身Library目录的副本,这些 Library目录具有不同的访问级别以匹配不同的域类型。虽然一个应用程序可以使用这个目录来存储内部数据或临时文件,但将应用程序的束自身或是用户数 据文件存放在Library目录中将是不足取的。应用程序的束应放在一个/Applications目录中,而用户数据应放在用户的home目录中。 Library包含了许多标准的子目录。系统例程要求许多标准子目录必须存在,因此删除Library的子目录决不是一个好主意。然而,当需要存储特定的应用程序数据时,应用程序可以创建一个新的子目录。 Application Support 特定应用程序的第三方插件,帮助程序,模板和其他资源。按规定,这些项目应被放置在以应用程序命名的子目录中。举个列子,应用程序MyApp的第三方资源 将被放在Application Support/MyApp/中。注意,一个由应用程序开发者创建的资源应被放置在自己的应用程序包中。更多信息请参见 “应用程序包”一章节。 Assistants 帮助用户完成配置和其它任务的程序。 Audio 声音插件和设备驱动。 ColorPickers 根据某一模式取色的资源,例如HLS (Hue Angle, Saturation, Lightness) 取色器或RGB 取色器。 ColorSync ColorSync描述和脚本 Components 系统中的插件和扩展。 document.tion 文档文件和Apple 的帮助包(在子目录Help中),计算机上的用户和管理员可以使用它们。在本地域中,这个目录包含了Apple安装的帮助包(包括开发者文档)。 Extensions 设备驱动和其他内部扩展(仅为系统域)。 Favorites 时常被访问的文件夹,文件或Web站点的替身(仅为用户域)。 Fonts 用于显示和打印的字体文件。 Frameworks 框架和共享库。 Internet 用于Internet的插件,库和过滤器。 Keyboards 键盘定义。 Mail 包含了用户的邮箱(仅为用户域)。 Preferences 用户预置,请参见“系统预置”一章中的“用户配置”一节。 Printers 打印驱动(由厂商提供)和PPD插件。 QuickTime QuickTime的插件和扩展。 Scripting Additions 扩充了AppleScript功能的脚本及脚本资源。 Sherlock Plug-ins 扩充了Sherlock功能的插件。 Sounds 系统警告声。 StartupItems 在启动时运行的系统及第三方的脚本和程序,更多信息请参见“引导和登入”一章中“启动项目”一节。 Web Server Web 服务器的内容,这个目录包含了CGI脚本以及所备置的Web页面。 —————————————————————— Developer目录 用于开发Mac OS X软件的应用程序,工具,文档及其他资源是一个可选的软件安装包。当您安装开发工具时,安装程序会把所有软件组件放到位于启动卷(/Mac OS X)的Developer目录中。 Applications 用户管理和建立软件项目(Project Builder),创建用户界面(Interface Builder)和执行调试程序的应用程序。 document.tion 开发者文档 Examples 分类组织的项目实例(Carbon,Java等等)。 Headers 特殊的头文件,诸如:遗留的简单 Carbon头文件。 Java 在Cocoa应用程序环境中用于Java桥接所需的文件。 Makefiles 用于建立和改变项目所需的makefile(.make文件)和jamfile(.jam文件)。 Palettes Apple 提供的Interface Builder的调色板。 PBBundles Project Builder使用的可装载的束。 ProjectBuilder Extras Project Builder的模板和插件。 ProjectTypes Project Builder使用的项目类型的定义 Tools 命令行开发工具,包括那些创建和生成HFS资源分支的工具。 Project Builder定义了一组makefile变量,当您的项目在文件系统域中指定位置时,应该会使用到它们。您应该使用这些变量而不是将目录路径硬编码,因为这些位置可能会被改变。 —————————————————————— Classic环境的目录 Classic环境包含了几个用于支持Classic应用程序的目录。这些Classic环境下的目录是一个Mac OS 9安装版本中的目录。 Mac OS X 需要为Classic环境安装一个 Mac OS 9.1(或更新的版本)。如果一个系统安装了一个比Mac OS 9更早的版本,用 户必须安装一个更新的版本来支持Mac OS X。 一个系统可能有多个Mac OS 9版本安装在不同的分区上。如果是这种情况,系统预置的Classic设置面板将让用户为Classic环境选择 使用其中的一个Mac OS 9版本。用户第一次启动Classic时,系统会将一些必要的文件附加到被选取的Mac OS 9卷的系统文件夹内。您也可 以使用系统预置中的Classic设置面板随时启动或停止Classic运行环境。用户还可以使用“启动磁盘(Startup Disk)”系统预置来改 变启动磁盘,以从Mac OS X变为直接启动进入Mac OS 9。 当您在一个卷上安装了Mac OS 9.1(或更新的版本)时,安装程序会创建几个目录来存储系统文件。表9-6列出了安装程序创建的目录以及关于 其内容的描述。如果您已经安装了一个Mac OS X 和 Mac OS 9.1(或更新)的本版,Mac OS 9 的安装程序可能不会创建所有这些目 录。 Applications (Mac OS 9) 包含了Mac OS 9(Classic)的应用程序和实用工具。 document. 包含了特定应用程序的信息。这个目录只能由Classic应用程序使用。Mac OS X应用程序会在适当的/Library目录中存储预置和其他应用程序文件。用户应该把他们的文档存放在他们自己的home目录当中。 System Folder 包含了Classic环境的系统文件。 当您在一个已经装有Mac OS 9的系统上安装Mac OS X时,安装程序会执行一些额外的任务来支持Classic环境。尤其 Mac OS X安装程序会创建一个Mac OS 9桌面文件夹的替身,并把它放在可以运行安装程序的管理员用户的桌面上。这个替身包含了在 Mac OS X 安装之前Mac OS 9桌面上任何文件的链接。 本地化目录名 如果您的应用程序包安装了任何用户支持的目录,那么您不但可以为应用程序提供本地化名称,而且也可以为这些目录提供本地化名称。本地化您特定的应用 程序目录名是不必要的,而且可能并不是所有情况下都是有效的。如果您想本地化您的应用程序支持的目录,您应该仅为那些您应用程序预先知晓其名称的目录进行 本地化。不建议本地化“用户特定”的目录名。 要本地化目录名,您必须为目录名加上.localized扩展并将其默认设置为隐藏。然后在您的目录中再创建一个名为.localized的子目 录。在这个子目录中,为您想支持的每个本地化版本创建一个strings文件。strings文件包含了目录名的本地化版本的单一入口。举个例子,一个用 English,,Japanese和 German本地化的Release Notes目录将包含以下结构 Release Notes.localized/ .localized/ en.strings de.strings ja.strings 在每个strings文件当中,您要把非本地化目录名转变成本地化目录名。举个例子,要转换目录名“Release Notes”成为一个本地化目录名,每个strings文件都要包含类似以下的条目。 “Release Notes” = ”Localized name” 注意:许多系统定义的目录在他们的名称里并不包含.localized扩展名。因为这些目录在引入本地化文件系统名之前已经存在。对于这些已知的目 录,Mac OS X转而在目录中查找名为.localized的空文件。如果此文件存在,那Mac OS X就会显示其本地化目录名文本。 —————————————————————— HFS+ 和 UFS的不同点 在Mac OS X的两种主要文件系统:HFS+和UFS上,有着许多重要的不同点。在许多情况下,这些不同会与在Mac OS X上开发的程序有关联。以下列表总结了在这两个文件系统中的主要不同点(有些陈述既适用于HFS又适用于HFS+): 大小写敏感:UFS对大小写是敏感的,而HFS+对大小写不敏感,但它可以保留大小写。 多分支:HFS+支持多分支(和附加的元数据)而UFS只支持单一分支(Carbon在不支持多分支的系统“如:UFS”上模似多分支结构)。 路径分隔符:HFS+使用冒号作为路径分隔符,而UFS中使用的则是正斜杠。系统能够在这些分隔符间进行转换。 修改日期:HFS+支持对文件的创建和修改日期的记录,它们将作为文件元数据被保存;而UFS只支持对文件修改日期的记录,不支持对文件创建日期的 记录。如果您用一条命令来复制一个文件,这条命令将会处理修改日期,但不会处理创建日期,当它为一个副本创建一个新的文件时,这条命令将会重设其修改日 期。由于这一原因,很可能会使一个文件的创建日期要比其修改日期更晚。 Sparse文件和零填充:UFS支持sparse文件(稀疏文件),它是一种文件系统存储文件数据的方法,其不存储分配给文件的未被使用的空间。HFS+不支持sparse文件,事实上可以用”零”为文件填充所有未使用的字节直到文件结束。 对文件系统项目的轻量级引用:请见“替身和符号连接”一节。 另外,那些已往与每种文件系统相关联的API有时会具有不同的特性。举个例子,一个使用了BSD (或来源于BSD)API的程序可以删除一个打开着的文件;而另一方面,一个Carbon程序只可以删除一个已关闭的文件。 —————————————————————— 替身和符号连接 替身和符号连接是对文件夹和目录的轻量级引用。替身与Mac OS标准格式(HFS)和Mac OS 扩展格式(HFS+)相关联,而符号连接是 UFS文件系统的一个特征。替身和符号连接都允许对文件夹和目录多次引用,而不需要为这些项目建立多份副本。Mac OS X 10.2之前,当移动或改 变一个被引用的文件或文件夹时,替身和符号连接在处理方式上会有很大不同。 原先,替身首先用文件夹和目录的唯一标识来定位他们,其次才是用他们的路径。如果您在同一个卷上移动一个文件,任何指向那个文件的替身仍会指向原本 那个位置。假如您删除某个文件,并用一个同名的文件代替它,替身仍可以工作,因为他们可以用路径来定位文件。而从Mac OS X 10.2起,替身颠倒 了其搜索顺序,先使用路径后使用文件标识。 因为替身和符号连接都使用一个文件系统路径来断定文件位置,因此他们都提供了类似的基本工作方式。如果您用一个同名文件替换某个文件,把旧文件移到 新的位置上,替身和符号连接都将指向新的文件。然而,如果您移动某个文件而不是替换它,符号连接会产生文件中断,但替身则不会。 在HFS 和HFS+文件系统中,每个文件和目录都会具有一个唯一的固定标识。替身存储了这个唯一标识以及文件或目录的路径信息。如果不能通过替身 中的路径信息来找到文件,替身则会试图使用其唯一标识来定位文件。如果找到了文件,替身会用新的路径信息更新其内部记录。同样,如果路径正确,而唯一标识 有错误,替身也会用新文件唯一标识来更新其内部记录。 如今Finder和其他系统应用程序用先查找路径的方式来使用替身。然而,通过使用Alias Manager(替身管理器)的方法来处置替身时,将仍会使用先根据文件唯一标识来查找的方式。 如果您的应用程序支持Mac OS X 10.2以前的Mac OS X 版本,则当您修改文件时应该遵守某些准则。首先,当需要编辑文件时,可修 改已有的文件。其次,如果您明显需要用一个新版本来替换某个文件,可用FSExchangeObjects来将旧的文件替换成新的。 NSdocument.用一种类似的方法来更新文档文件。因此,无论何时替身都能保持有效。 —————————————————————— 下图对照早期的Mac OS系统描述了Mac OS X中资源是如何存储的。 虽然Apple支持“在同一文件中存储所有资源(all-resources-in-one-file)”的模式,但强烈建议开发者将他们的资源存 放在各自的独立文件中。基于此的一种考虑是为了结合XML的使用来作为来指示资源的一种方式。Carbon具有基于XML的运行时工 具,Interface Builder可以使用XML来输出用户界面。 如同应用程序一样,Mac OS X上的文档也可将其资源存放在数据分支中。其原因与应用程序把资源存放在数据分支中的原因是相同的。它使得在Macintosh系统与非Macintosh系统(包括大部分的Web服务器)间交换文档,而不丢失资源数据成为可能。 存放在HFS 和HFS+文件系统中的文件在独立于资源分支和数据分支以外的一个私有分支中存储了Finder属性。这些属性包含了类型代码和创建 者代码。Mac OS X保留了这些属性,因为这些属性能使Finder增强用户体验。然而同时,Apple强烈鼓励开发人员选择使用文件扩展名作为识别 文件类型的方法。Mac OS X在识别和处理文档扩展名方面做的非常好。正如在“Finder”一章的“复制和移动操作”一节中所描述那样,如果您复制 一个HFS 或HFS+文档到不同平台(包括Web服务器)中时,文件扩展名将有助于保证文档的类型信息。 文件编码和字体 虽然Unicode被认为是Mac OS X的基本编码,但并没有一种文件编码对所有情况都是默认的。使用(或应该使用)何种文件编码,取决于您在所使用的API和底层文件系统上具体想要做什么。 举个列子,用于文件名的编码在不同的文件系统中是不一样的。Mac OS 扩展格式文件系统(HFS+)使用一种Unicode的特殊形式为文件名 编码,即在UTF-16格式(16位编码序列)中被规范出的Unicode 2.1版本。UFS文件系统使用一种不同的Unicode格式来编码文件名。 它包含了Unicode2.1或更新版本中的任何字符,但使用的是UTF-8格式(8位编码序列)。Mac OS标准格式(HFS)使用传统的Mac编 码,诸如MacRoman。注意,由于实现方式不同,在HFS+卷上文件名中不正确的Unicode编码有可能会在Mac OS 9系统上正常显示,但通 常在Mac OS X上又显示成混淆的字符。 而且,所有调用BSD系统例程的代码都应保证这些例程的const *char参数是以UTF-8编码的。所有BSD系统函数期望其字符串参数以 UTF-8编码,而不能是其他的编码。另外要告诫的是文件,路径和其他文件系统实体在作为字符串参数时必须要以规范的UTF-8编码。在规范的UTF- 8 Unicode的字符串参数中,所有可分解的字符会被分解;举个例子,é (0x00E9)被表示为 e (0×0065) + ′ (0×0301)。在使用在Cocoa和 Carbon (包括Core Foundation)中定义的”文件系统表 示”API时,要以规范的UTF-8编码。举个例子,在Cocoa中得到一个规范的UTF-8字符串,要使用NSString的 fileSystemRepresentation方法;而对非正规的UTF-8字符串,使用NSString的UTF8String方法。 如果您使用常规的QuickDraw并想绘制文本,您应注意一些潜在的问题。Carbon文件管理器会产生一些返回Mac编码的调用和其他一些返回 Unicode的调用。如果您有一个Unicode文本,您在用QuickDraw Text对其绘制时会有一些问题,因为其API不直接支持 Unicode。另一方面,如果您得到一个Mac编码的文本并想使用Unicode Imaging (ATSUI) API中 Cocoa 和 Carbon的Apple Type Services,您必须首先将其转换成Unicode。 通常,所使用的编码取决于您使用的API而不是字体。字体并不必须限制于特定的编码。举个例子TrueType字体声明了一组字型,他们实现并提供 了在特定编码中映射那些字型为字符值的编码表。PostScript字体有类似的编码列表。操作系统的各个部分知道如何映射字符从一种编码到另一种编码。 Cocoa 和ATSUI使用Unicode作为一种字体的“目的”映射。Carbon 中的QuickDraw Text使用Mac编码,它是根据字体 的’FOND’资源相对应的语系来选择的。 安装在Mac OS X上的字体拥有大量的字符组,它们支持广泛的编码和语系。举个例子,系统字体Lucida支持扩展的拉丁语 (Latin), 希腊语(Greek), 斯拉夫语(Cyrillic), 阿拉伯语(Arabic), 希伯来语(Hebrew)和泰国语 (Thai)。但如果您通过QuickDraw Text来绘制文本,那您只能访问MacRoman字符表。要访问其余的部分,则您必须使用Cocoa 或 ATSUI。同样日语中的Hiragino字体也有一个巨大的字符表,它超越了MacJapanese所支持的范围,它们只有通过Cocoa 或 ATSUI才可以访问到。当被请求的其他字体中的字型不可用时,Cocoa 和 ATSUI会将其替代;然而,他们替代字体的算法是不同的。 Mac OSX的引导和登录

“引导”指系统为准备投入使用而执行的一系列动作。引导流程包括许多不同的任务,例如初始化硬件、启动系统守护程序(system daemon)以及显示登录窗口。当用户登录后,系统将完成另一系列动作,用以为用户建立计算环境。 我在这里将对开发人员在编写软件时可能会遇到的“引导流程(boot sequence)”进行说明。也将说明如何使用各种有效的“钩子”方法来定制引导进程。 注意:man命令帮助页是一种联机文档,对本章所提及的大部分守护程序和实用程序都有效,您可以查阅这些文档以获取更多的信息。欲从终端应用程序显 示man命令帮助页,请在命令行上输入man,接着输入程序名称:例如,> man getty(此处,>为提示符)。您也可从 Project Builder的帮助菜单访问man命令帮助页。 引导流程 在从用户打开Mac OS X系统到登录窗口出现的这个时间段内,Mac OS X将执行一个引导流程,使系统处于准备使用状态。本节将对在此流程期间所发生的事件进行概括。 BootROM 当打开Macintosh计算机的电源后,BootROM固件是被激活的第一个代码。BootROM(它是计算机硬件的一部分) 有两个主要的职责:初始化系统硬件以及选择引导操作系统。BootROM有两个组件帮助其实现这些功能: POST(Power-On Self Test,开电自检)对一些硬件接口进行初始化,并检查是否有足够的RAM存储器可供使用以及是否处于良好状态。 Open Firmware对其余硬件进行初始化、创建初始设备树(一个计算机相关设备的分层表示法)以及选择所使用的操作系统。 相同版本的BootROM可启动Mac OS 9以及Mac OS X。 ———————————————— BootX 当BootROM(或用户)选择Mac OS X作为引导的操作系统后,控制权就传递给了BootX 引导程序(位于/System /Library/CoreServices目录内)。BootX的主要任务是装载内核环境。当执行此任务时,BootX在屏幕上显示 “booting(引导中)”图像。 当装载内核环境时,BootX将首先尝试为涉及引导进程的硬件装入一组预先存储的设备驱动程序(称为mkext缓存)。如果该缓存丢失或遭破 坏,BootX将在/System/Library/Extensions目录内搜索驱动程序和其它的内核扩展,这些驱动程序或内核扩展的 OSBundleRequired属性被设置为一种合适的引导类型(例如,本地或网络引导)的值。关于OSBundleRequired关键字以及系统引 导时装载设备驱动程序的更多信息,请参阅“内核开发人员文档”。 一旦装载了内核以及引导所必需要的所有驱动程序,BootX就开始内核初始化进程。此时,有足够多的驱动程序被装载,以帮助内核来寻找根设备。另外从此时开始,Open Firmware将不再能被访问。 内核将首先初始化Mach和BSD数据结构,然后初始化I/O Kit。通过使用设备树决定链接的驱动程序,I/O Kit将装入的驱动程序与内核连接。一旦内核找到根设备,它将通知BSD。 最后,内核启动mach_init进程。mach_init进程是Mach引导端口服务程序,它启用Mach消息传递。 在安装根文件系统后,系统初始化将继续运行系统启动项目并启动所有系统守护程序(参阅“系统初始化”)。 系统初始化 mach_init进程将启动BSD init进程。后一进程的进程标识符(PID)为1,它“拥有”系统的所有其它进程。尽管具有中心地位,但init进程是简单的,它执行了四个主要任务: 1.确定用户想要进入单用户模式还是通过CD-ROM引导。如果其中任一情况适用,将打印一个询问,并将控制权移交给用户。 2. 运行完成基本初始化任务的系统初始化外壳脚本,即/etc/rc.boot和/etc/rc。详细内容请参阅“rc.boot 和rc脚本”。 /etc/rc脚本运行SystemStarter程序,它处理更多被指定为“启动项目”的特定初始化任务。详细内容请参阅“启动项目”。 3. 通过getty命令,init将启动loginwindow应用程序,它将显示登录窗口并管理用户登录过程。详细内容请参阅“管理用户会话”。 4.作为所有进程的父进程, init在这些系统进程终止时,将对它们进行所有必要的清理。 尽管init进程拥有系统的所有其它进程,但仍然可区分用户进程和系统进程。启动项目以及所有在loginwindow应用程序以前运行的应用程序 构成了系统进程组。这些应用程序为系统的所有用户提供服务,它们通常是init进程的子进程。在启动loginwindow后被创建的进程构成了用户进程 组。用户进程总是与一个特定的用户会话相关联,它们通常是用户会话的窗口管理器(Window Manager)进程的子进程。 注意:并非所有的用户进程都是窗口管理器(Window Manager)进程的子进程。用户可以是由root启动的进程和某些特殊系统进程的拥有 者,这些进程是init进程的子进程。您可使用进程显示程序(Process Viewer)应用程序来确定系统任何进程的拥有者和父进程。 当用户注销会话时,loginwindow应用程序将终止在该用户会话期间内运行的所有进程,这是完全结束会话的必要条件。而系统进程将不受用户注销的影响,只有当系统本身关闭或重启动时系统进程才被终止。关于注销、重启动或关机流程的更多信息,请参阅“注销”。 ———————————————— rc.boot和rc脚本 /etc中的rc.boot和rc Bourne外壳脚本执行了基本的初始化任务。rc.boot脚本首先执行一次文件系统一致性检验(file- system consistency check ,fsck),并使存储器与文件系统同步(sync)。然后,rc脚本将完成下列动作: 启动设备驱动程序的装载程序(kextd)。 启动ATS服务程序。 启动窗口服务程序。 运行更新后台进程,它周期性地刷新文件系统缓存。 为虚拟存储系统创建交换文件并启动动态页面调度程序。 最后,rc脚本启动SystemStarter程序,处理本地与系统启动项目(请参阅“启动项目”)。 由于rc脚本是简单的Bourne外壳脚本,您可以直接阅读其源代码,以确切地了解所发生的事情。关于在系统安装期间所启动的守护程序的更多信息,请参阅“系统守护程序”。 ———————————————— 启动项目 启动项目是为Mac OS X系统正常运转而在引导的最后阶段运行的过程。它们由程序(包括外壳脚本)组成,这些程序执行诸如清除临时文件和启动系统守护程序等任务。 Apple提供的系统启动项目位于/System/Library/StartupItems中。您不可修改在此目录中的项目。然而,您可定义自己 的启动项目并将它们存放在/Library/StartupItems中。关于如何创建自己的启动项目的说明,请参阅“创建定制启动项目”。 SystemStarter程序是由rc脚本运行的最后程序,它协调所有启动项目的执行。了解SystemStarter的功能对理解什么是启动项目是有帮助的。启动项目是一个包含至少两个文件的文件夹: 一个程序(一般为一个外壳脚本),其名称与文件夹名称一致。 一个配置属性列表文件 每一个启动项目的配置属性列表都被命名为StartupParameters.plist。此属性列表指定了启动项目的名称,更重要的是,多层次地 指定了启动项目间的相互依赖关系。属性列表中的值指明该启动项目可以提供何种服务,在启动该项目前应首先运行何种服务,以及该启动项目本身需要使用何种服 务(如果需要)。SystemStarter使用这些相互依赖关系的信息来决定所有启动项目的启动次序。 SystemStarter程序并行地启动尽可能多的启动项目。将启动项目根据它们的相关性组织成不同的组。只有当同一组的项目都被启动后,下一组的项目才开始被启动。 关于StartupParameters.plist中键值对的更多信息,请参阅“创建定制启动项目”。关于属性列表的一般信息,请参阅“属性列表”。 表4-1列出了由Mac OS X提供的核心启动项目,以及关于它们功能的简要说明。其它启动项目可由第三方应用程序或由诸如QuickTime这类系统组件来安装。表中给出的次序是执行这些项目的通常次序。准确的次序由SystemStarter程序在引导时决定。 表4-1 核心系统启动项目 启动项目 说明 SystemTuning 系统调制 基于诸如可用内存等因素,为系统设置性能参数。 SecurityServer 安全服务 启动检查系统授权、验证及钥匙串(keychain)访问的安全服务程序。 ConfigServer 配置服务 为依赖于configd守护程序的启动项目充当一个占位符。现在该守护程序在启动项目阶段之前就被启动,所以不推荐使用此启动项目,在今后的版本中它也可能会被删除。 Disks 磁盘 启动自动磁盘装载(autodiskmount)守护程序,用于检查及安装本地磁盘。 Accounting 帐号管理 启动帐号管理系统(accton),为启动的每一个进程将帐号信息写入/var/account/acct。 Network 网络 根据/etc/iftab中的数据,配置本地网络接口、设置机器的主机名、配置网络路由(如果被指定)、打开或关闭IP路由(如果被指定)、在内核中设置机器的主机标识符,以及装载可在所有应用程序环境(包括Classic环境)中共享一个IP地址的共享IP内核扩展。 NetworkExtensions 网络扩展 装入若干网络相关的内核扩展。 BIND 启动本地DNS服务程序。 mDNSResponder 启动多址广播DNS应答程序,它支持Rendezvous及Apple的零配置联网工具。 Portmap 端口映射 启动端口映射(portmap)守护程序。 SystemLog 系统日志 启动系统日志(syslogd)守护程序。 AppleTalk 以路由器模式、多重连接(非路由器)模式或在单一端口(如同在/etc/hostconfig中定义的那样)运行AppleTalk启动程序。 CrashReporter 崩溃报告 如果崩溃报告功能被设置为可用,则启动崩溃报告程序(CrashReporter)。 LDAP 启动LDAP服务。 NetInfo 启动NetInfo服务程序(netinfod和nibindd)。 NIS 启动网络信息服务(Network Information Services)。 DirectoryServices 目录服务 启动名字解析器(lookupd)守护程序 NetworkTime 网络时间 启动使用网络时间协议(Network Time Protocol,NTP)的网络时间服务。 LoginWindow 登录窗口 标记系统具有它需要用于启动loginwindow应用程序的服务。当SystemStarter在后台继续载入其他启动项目时,init进程将启动此应用程序。 SSH 如果远程访问被设置为可用,则启动sshd守护程序。根据需要,此启动项目也会按需要产生安全外壳加密键(secure shell encryption key)。 NFS 启动网络文件系统(NFS)服务,用于执行异步块I/O(nfsiod),安装远程文件系统,和启动自动装载程序(automounter),如果NetInfo数据库显示计算机应导出一使用NFS的文件系统,则启动NFS服务程序。 Samba 启动Samba服务程序(smbd),它通过服务程序信息块(Server Message Block,SMB)协议提供网络联通。 AuthServer 验证服务 启动验证服务程序。 AppServices 应用服务 启动核心服务(coreservicesd)守护程序。 PrintingServices 打印服务 启动CUPS打印服务(cupsd)守护程序。 IPServices IP服务 启动TCP/IP协议服务(inetd)、主机配置服务(BOOTP)以及netboot客户机管理服务程序。 AppleShare 如果检测到网络连接,则启动AppleShare服务。 SendMail 启动外发邮件服务(sendmail)守护程序,整理外发邮件队列目录。 Apache 如果网络共享被设置成可用,则运行Apache HTTP服务程序httpd。 Cron 运行cron守护程序。 “系统守护程序” 一节将对上表提到的一些守护程序和服务进行简要说明。 对于存在于/System/Library/StartupItems文件夹中的各启动项目,并不能保证它们的服务对于用户都是可用的。每个启动项 目都可以通过访问/etc/hostconfig中的配置信息,并使用此信息来评估是否需要启动其服务。许多启动项目都使用此配置信息(尽管也有一些必需 的启动项目并不如此),检查此配置信息的启动项目 有:AppleTalk,AppleShare,AuthServer,Disks,SSH,SendMail,IP Services以及 Apache。 ———————————————— 系统守护程序 当用户登录到Mac OS X系统时,许多进程已处于运行状态。这些进程的大多数是由系统创建并运行于后台的守护程序或服务程序。少数是由 loginwindow应用程序和窗口管理守护程序为用户创建的。在登录后立即启动进程显示程序(Process Viewer)(位于 /Applications/Utilities),将引出一个类似图4-1中显示的窗口。 表4-2对一些标准的守护程序和服务程序进行说明。由于取决于系统配置和用户预置,一些守护程序可能被禁用或根据需要被启动(请参阅“根据需要启动守护程序”)。相反地,由于安装了附加服务,系统也可以运行其它守护程序。 表4-2 常用的系统守护程序和服务程序 守护程序 说明 ATSServer ATS服务 Apple Type Solution服务程序,启用系统范围内的字体管理。 autodiskmount 自动磁盘装载 自动装载所有设备,包括硬盘及可移动介质。 automount 自动装载 当NFS文件系统被首次访问时自动装载它们,而以后当它们闲置时则将它们卸载。虚拟文件系统的装载点首先作为本地文件系统的符号链接出现。读取此符号链接将触发相关远程文件系统的自动装载。 configd 自动地配置并维持网络。 cron 定时执行预定的命令或脚本。 dynamic_pager 与内核默认页面调度程序通信,以创建或删除交换文件(在/private/var/vm内);这些文件被用作为虚拟内存的后备存储器。 inetd 用来侦听某些socket连接的互联网“超级服务程序”。当发生连接时,inetd可确定该socket符合何种服务,并调用适当的程序满足其需求。 init 系统初始化进程。此进程是大多数系统级别进程的父进程。 kextd 设备驱动装载程序。在系统启动期间,此守护程序装载未被BootX装入的所有剩余的设备驱动程序。启动后,kextd负责动态地装载及卸载设备驱动程序。 lookupd 一个名字解析器,它向诸如NetInfo和DNS的网络信息服务发出查找请求。 mach_init Mach引导端口服务程序,通过它来启用Mach消息传递。同时,它也启动init进程。 mDNSResponder 多址广播-DNS应答器守护程序。 netinfod NetInfo服务程序,为每一个域提供服务。 nfsiod 针对一个NFS服务器的异步请求。大多数系统都具有运行此守护程序的多个实例。 nibindd 查找、创建及清除NetInfo服务程序(请参阅“netinfo”)。 pbs 粘贴板服务程序(类似于Mac OS 9中的剪贴板)可实现应用程序之间的数据交换。同时,它也是用于拖曳操作的数据转移机构。请参阅“剪贴板” 以获取更多信息。 portmap 将RPC程序号转换为互联网(DARPA协议)端口号。它必须在进行PRC调用前运行。 syslogd 记录系统错误日志和状态消息。 update 更新 定时地刷新文件系统缓存,以防系统崩溃引起数据丢失。 Window Manager 窗口管理器 窗口服务程序。请参阅“Quartz Compositor”以获取更多信息。此进程是大多数用户进程的父进程。 为获取更多的信息,请参阅“可供大多数守护程序使用的man命令帮助页”。 ———————————————— 根据需要启动守护程序 Mac OS X为系统守护程序的随选启动提供支持,并将此特性用于一些系统启动项目中。通过推迟启动所有非急需的守护程序,随选启动可改进系统性能。即使在非活动阶段,守护程序也能被关闭以保存系统资源。 随选启动对于它所支持服务的客户端是透明的。当客户端将一条消息发送至当前被关闭的守护程序时,mach_init将自动地装载该守护程序所需要的 任何服务,然后启动该守护程序。一旦该守护程序被启动并运行,它将用mach_init来登记,并要求对其Mach端口的接收权。一旦具有对其端口的接收 权,守护程序就可对来自那些端口的消息作出正常反应。 由于涉及与内核的交互作用,如何创建随选守护程序已超出本书的范围。关于内核和Mach端口消息传递的更多内容,请参阅“Inside Mac OS X:Kernel Programming(内核编程)”。 ———————————————— 管理用户会话 在系统初始化周期内,init进程将启动loginwindow应用程序来管理用户会话。loginwindow应用程序显示登录窗户,并为用户提供若干服务。本节将讨论loginwindow应用程序所提供的服务以及由loginwindow提供的用户环境。 ———————————————— 登录 通过调用其它所需的系统服务,loginwindow应用程序将协调登录进程和用户会话。依赖于用户的登录预置,loginwindow可提示用户 使用一个有效的登录名和口令,或使用缓存值来自动登录。当用户的登录名和口令被验证(请参阅“验证用户”)后, loginwindow将继续装载用户环 境。 当用户登录时,loginwindow进行如下工作: 安装用户计算环境(包括预置、环境变量、设备和文件权限以及钥匙串访问等)。 请参阅“建立用户环境”以获取更多信息。 启动Dock,Finder以及SystemUIServer。 如果正在安装,则启动安装助手(Setup Assistant)。 自动启动在登录项目系统预置中指定的应用程序。 当所有指定的应用程序被启动及运行后,登录过程结束。 loginwindow应用程序使用启动服务(Launch Services)启动所有的应用程序,包括 Finder, Dock,SystemUIServer以及用户指定的应用程序。用户会话中的大多数应用程序是作为窗口管理器进程的子进程(而不是作为 loginwindow的子进程)来运行的。 如果Finder或Dock进程由于某种原因而终止,loginwindow将自动重新启动它们。同样地,如果loginwindow应用程序终止,init进程也将自动重新启动它。 一旦用户会话被启动并运行,loginwindow将以下列方式监视会话和用户应用程序: 管理注销、重启动及关闭进程。请参阅“注销系统”以获取更多的信息。 管理强制退出(Force Quit)窗口,它包括监视当前正在使用的应用程序、对强制退出应用程序以及重新启动Finder的用户请求作出响应。(用户可从Apple菜单或通过按Command-Option-Escape打开此窗口。) 从隐含的应用程序(即,看不到用户界面的应用程序)接收到通知后,即显示报警对话框。 将所有标准错误(stderr)输出写入一个log文件(/var/tmp/console.log)中,而控制台(Console)应用程序将以此文件作为输入。 ———————————————— 验证用户 用户在进入系统以前,Mac OS X要求进行用户验证。尽管loginwindow应用程序管理用户验证进程,但它本身并不验证用户。 loginwindow应用程序获取在登录屏幕上指定的用户信息,然后将其它传递给目录服务以作验证。一旦目录服务完成用户验证,loginwindow 就将启动用户会话。 如果选择了“自动登录”选项, loginwindow应用程序将不为用户提示登录信息。每次只能有一个用户可以从“帐号(Accounts)”系 统预置中的“用户(Users)”页中启用此选项。同时,用户也必须通过点击“设置自动登录(Set Auto Login)”控件来输入一组正确的登录 口令。 ———————————————— 建立用户环境 当用户登录到系统时,loginwindow应用程序将建立用户环境以及记录有关登录的信息。下列项目概括了由loginwindow执行的用于恢复用户会话的任务: 1.为了保护登录会话免遭未被授权的远程访问,系统不允许用粘贴板服务(即剪贴板)的端口来注册远程启动的应用程序。这样,对于这些进程的一些标准功能会被阻塞,例如:拷贝、剪切、粘贴、Apple事件、窗口最小化及其它服务。 2.将登录信息记录在系统的utmp数据库中。 3.为控制台终端设置所有者和权限。 4.重新设置包括全局系统默认值(NSRegistrationDomain)的用户预置参数。 5.用引导端口注册粘贴板服务程序(pbs)并启动pbs。 6.按照用户预置来配置鼠标、键盘及系统声音。 7.设置用户分组权限(gid)。 8.从目录服务检索用户记录并将该信息用于会话。 ———————————————— 注销 注销、重启动系统及关闭系统的过程具有相似的语义。前台进程通常启动这些过程以响应用户从Apple菜单中选择的项目;然而,通过程序方式将一个适 当的Apple事件发送至loginwindow应用程序,其进程也能启动这个过程。另外,在loginwindow应用程序执行此过程中,它会发出警报 及通知来使各应用程序在关闭前有机会对它们自身进行清理。 一个典型的注销/重启动/关机过程如下: 1.用户从Apple菜单中选择注销、重启动或关机。 2.通过将一个Apple事件发送至loginwindow应用程序,前台应用程序启动用户请求。(关于事件列表,请参阅“应用程序职责”。) 3.loginwindow应用程序给要求确认此操作的用户显示一警报。 4.如果用户确认此操作,loginwindow将一个Quit Application Apple事件(kAEQuitApplication)发送至每个前台和后台用户进程。 5.loginwindow应用程序停止用户会话并继续此操作。 在注销操作中,loginwindow将取消事件队列中的所有事件,启动注销钩子程序(如果定义了一个的话),记录注销信息,将设备权限和用户预置参数重置为它们的默认值,并将控制权交还给登录窗口。(关于注销钩子程序的更多信息,请参阅“定制登录和注销过程”。) 重启动时,loginwindow将设备权限和用户预置参数设置为默认值、关闭系统,然后重新打开电源启动引导进程。 关机时,loginwindow关闭系统电源。 当接收到Quit Application事件时,前台进程也可以选择不终止。请参阅“终止进程” 以获取更多信息。 ———————————————— 应用程序职责 为实现注销、重新启动或关机流程,前台应用程序必须将一个适当的Apple事件发送至loginwindow应用程序。一旦接收到该事 件,loginwindow应用程序就开始关闭用户会话的进程。依赖于由该进程所发送的Apple事件,loginwindow可能会(也可能不会)用一 个警报来通知用户,以让用户有机会中止这一流程。 以下所列各项是在注销、重新启动及关机过程中首选的Apple事件。这些事件不需要参数。 kAELogOut kAEShowRestartDialog kAEShowShutdownDialog 一旦收到其中之一的事件后,loginwindow将发出一个警报,把即将发生的动作通知用户。此时,用户可以使动作继续或中断。如果用户使动作继续,loginwindow会将一个Apple事件发送至每个请求它退出的应用程序。请参阅“终止进程”。 除了首选的Apple事件外,还有两个附加事件可命令loginwindow立即进行重新启动或关机流程。kAERestart和 kAEShutDown Apple事件可进行温和的系统重启或关机。然而,这些事件应该被明智地使用,因为它们都不会给用户发送信息或允许用户中断流 程。 注意 如果注销、重新启动或关机事件源自Classic环境中的一个应用程序,那么此事件仅仅影响Classic环境和它的应用程序。用户会话的其余部分将继续运行。 ———————————————— 终止进程 在执行注销、重新启动或关机流程以前,loginwindow应用程序将会试图终止所有前台及后台用户进程。loginwindow应用程序给每个 进程发送一个kAEQuitApplicationApple事件,以便让它们得以温和地关闭。对于前台进程,loginwindow将等候一个答复。对 于后台进程,loginwindow将发送一个kill命令来终止此进程,而不管任何答复。 当前台进程从loginwindow收到Quit Application Apple事件(kAEQuitApplication)时,它会立即 终止自身或在要求用户先做出决定时发出一警报对话框(例如,当有一个未保存的文件时);当这些情况被解决后,应用程序既被终止。如果用户决定中断终止流程 (例如通过在保存对话中点击取消按钮),应用程序将返回一个userCancelledErr错误,以对此事件作出反应。如果前台应用程序没有在45秒内 作出反应或终止它自身,loginwindow将自动地中断终止流程。此安全措施将在各种状况下保护数据,例如:当应用程序正在将一个大文件保存到磁盘, 以及在所分配时间内不能完成终止时。如果前台应用程序无反应且不在做任何事情,则用户必须在继续进行此过程前使用Force Quit窗口将其杀除。 对于链接Carbon、Cocoa或Java的用户后台进程,过程略有不同。通过给它们发送一个Quit Application Apple事件 (kAEQuitApplication),Loginwindow通知即将被终止的进程。然而,它并不等待该进程的答复。Loginwindow将继续 终止任何打开的后台进程,而不管任何返回的错误。 loginwindow应用程序不会终止驻留在系统环境中的进程。此规则适用于在引导时系统启动的所有守护程序和系统启动项目。这些进程驻留在用户 会话的环境外,仅仅在重新启动或关机时才被终止。Loginwindow也不会清除独立于Carbon、Cocoa或Java的后台进程,即使它们是从用 户环境中启动的。(尽管是从用户环境中启动的,当用户注销时这些进程将被系统接管。)Mac OS X不会在终止系统进程前给它们发送任何通知。 定制技术 Mac OS X引导进程包含开发人员可用来定制进程的若干切入点。开发人员可创建在引导时被启动的新的系统守护程序和服务。开发人员和系统管理员也可创建在用户登录到系统时被运行的初始化脚本。 创建定制启动项目 通过创建新的启动项目,您可把专用的功能加入引导流程。在“启动项目”中描述的启动项目是一个程序或外壳脚本,它们在首次登录会话以前执行各种服务,例如启动系统守护程序、删除旧文件或任何其它维护任务。 启动项目在引导流程的最后阶段运行(通过SystemStarter程序)。此时,SystemStarter在/System/Library /StartupItems和/Library/StartupItems目录中搜寻启动项目。它从每个启动项目的属性列表中收集信息,并且使用那些信息 决定项目的执行次序。然后以基于项目的相关性形成的组来执行启动项目。 /System/Library/StartupItems目录是为Mac OS X装载的启动项目而保留的。所有其它的启动项目应被放置在/Library/StartupItems目录中。注意这个目录并非默认存在,可能需要在安装启动项目时创建。 为了创建一个新的启动项目,您必须创建一个程序或脚本来执行您的代码,并且必须创建一个包含启动项目信息的属性列表文件。以下几节将更详尽地描述这些技术。 注意 尽管单个启动项目能执行多个任务并启动多个守护程序,但建议您最好将一个启动项目限制于一个任务。每个项目执行一个任务可使相关性的分离更为容易,并可加快启动项目的装入。 ———————————————— 创建启动项目可执行文件 启动项目可执行文件包含了您的启动项目的代码,它可作为命令行程序或外壳脚本来被执行。通常,仅在系统启动时才调用这些可执行文件。但实际上,SystemStarter具有在此以后调用这些可执行文件的能力(请参阅“启动和停止启动项目”)。 创建启动项目的步骤如下: 1.为启动项目创建一个目录。目录名称应与您提供的功能相符。 例如:MyDBServer 2.将可执行文件加入目录中。可执行文件的名称应与目录名称完全相同。 例如:MyDBServer/MyDBServer 3.创建名为StartupParameters.plist的属性列表并将其加入目录。请参阅“指定启动项目功能”。 例如:MyDBServer/StartupParameters.plist 4.创建安装程序,将启动项目放置在/Library/StartupItems目标系统的目录中。(安装程序可能需要首先创建此目录。) Mac OS X提供一些外壳脚本代码,以简化创建启动项目的过程。文件/etc/rc.common定义了一些例程,对于处理命令行变量和收集系 统设置是有用的。为使用这些例程,如下例所示,在一个外壳脚本中引用rc.common文件,并调用RunService例程,将第一个命令行参数传递给 它: #!/bin/sh . /etc/rc.common

Your startup item code

RunService ”$1″ RunService例程在外壳脚本中搜寻StartService、StopService以及RestartService例程,根据需要来调用它们以启动、停止或重新启动您的服务。而您必须为所有三个例程提供具体实现(当然您的服务也可以不支持其中的某个例程)。 如果启动项目可执行文件包含可能需要一点时间完成的代码,那么您应该考虑将该代码作为守护程序或后台进程来运行。直接从脚本执行冗长的启动任务将推迟系统启动。启动项目脚本应尽可能快地执行,然后退出。 ———————————————— 指定启动项目属性 除了启动项目可执行文件以外,每个启动项目还必须在启动项目目录中包含一名为StartupParameters.plist的属性列表。此属性列 表包含启动项目信息以及此项目与其它启动项目之间的所有相关性描述。在启动任何启动项目以前,SystemStarter程序读取每个启动项目的属性列 表,并且使用此相关性信息决定启动项目的启动次序。 表4-3列出了包含在启动项目的StartupParameters.plist文件中的键值对。所有数组和字典中都包含字符串类型的值。您可使用 /Developer/Applications中的属性列表编辑器(Property List Editor)应用程序来创建此属性列表。 表4-3 StartupParameters.plist中的键值对 关键字 类型 值 Description 字符串 启动项目的简短说明,它可由管理工具来使用。 Provides 数组 由此启动项目所提供的服务。尽管一个启动项目可提供多项服务,但一般它只提供一项。 Requires 数组 在此启动项目启动前必须运行的其它启动项目所提供的服务。如果得不到所要求的服务,则此启动项目不能被运行。 Uses 数组 在此启动项目启动前应该但并非需要强制启动的其它启动项目所提供的服务。没有这些服务,此启动项目也可启动。 OrderPreference 字符串 对于那些具有相同执行次序(由Requires及Uses的值来决定)的启动项目,它们应被启动的相对顺序。有五个次序预置值:First,Early,None,Late以及Last,默认值为None。次序预置值只是一个建议值,可以被忽略。 为Requires及Uses属性指定的值应与启动项目依赖的服务名称相一致。服务名称可能并非总是与提供该服务的启动项目的名称直接对应。 Provides属性指定由启动项目所提供的服务的名称。通常当此名称与启动项目的名称一致时,就没有必要再这样做了。特别需要说明的是,启动多项服务的 启动项目最多只能具有其名称与启动项目相一致的一项服务。 如果两个启动项目提供了名称相同的一项服务,SystemStarter只运行按此名称找到的第一个启动项目。所以,除非启动代码中的codependencies绝对要求这样做,建议启动项目不要提供多项服务。 Requires、Uses及OrderPreference关键字的值不能保证一个特定的启动次序。 ———————————————— 启动和停止启动项目 当SystemStarter执行启动项目时,它将一个指示所需动作的参数传递给可执行文件。启动时,SystemStarter将一个启动参数传 递给可执行文件。启动后,SystemStarter也可将重新启动或终止参数传递给启动项目。启动项目的可执行文件应该检查所获得的参数,并且据此启 动、重新启动或停止相应的服务。 如果想通过自己的脚本启动、重新启动或停止启动项目,您可用SystemStarter程序来这样做。在使用SystemStarter时,您必须 使用两个参数来执行它:所需的动作以及目标启动项目所在目录的完整路径。例如,为了重新启动Apache Web服务程序,您应在命令提示符下输入: /sbin/SystemStarter restart /System/Library/StartupItems/Apache 注意: 您必须具有root用户的权限才能启动、重新启动或停止启动项目。 启动项目应始终考虑SystemStarter传入的参数。然而,对于那些参数作出的反应取决于启动项目。停止与重新启动选项可能在任何情况下都没有意义。通过使用现有的用于停止和启动其服务的代码,启动项目也能支持重新启动选项。 在运行时手动处理启动项目的应用程序也可以通过使用SystemConfiguration框架来实现这些功能。这个框架可以用来获取指向一个所需启动项目的引用,并将其执行。 关于启动项目的更多信息,请参阅“创建定制启动项目”。. ———————————————— 定制登录和注销过程 通过系统预置的“登录(Login)”页,管理员已可以配置loginwindow的若干属性。帐号系统预置的“登录选项(Login Options)”页(如图4-2所示)为计算机管理员显示了一些附加的选项。 [ 相关贴图 ] 图4-2 帐号系统参数选择的登录选项窗格 除了这些功能特性以外,loginwindow应用程序还提供了一组用于定制登录过程的可用于编程的钩子。在每次登录或注销时,您可使用这些钩子来 运行附加的程序或脚本。与在“登录选项(Login Options)”页中所提供的选项相类似,也存在一个指向停用“重新启动(Restart)”和 “关机(Shut Down)”按钮的钩子。 为了使用loginwindow钩子,必须修改启动loginwindow的代码(位于/etc/ttys中)。以下是此文件的程序行: console ”/System/Library/CoreServices/loginwindow.app/loginwindow” vt100 on secure window=/System/Library/CoreServices/WindowServer onoption=”/usr/libexec/getty std.9600″ 这些程序行命令init程序在控制台终端上启动loginwindow,并将WindowServer(它是连接窗口管理器进程的一个符号链接)作 为视窗系统进程来使用。在这些程序行中,您可以为loginwindow进程添加附加参数。表4-4列出了当前由loginwindow支持的参数。 表4-4 loginwindow参数 参数 值的说明 -LoginHook 当用户成功登录后,所运行的脚本或工具的完整路径。 -LogoutHook 当用户成功注销后,所运行的脚本或工具的完整路径。 -PowerOffDisabled 若为“YES”,将不能使用登录窗口中的关机和重新启动按钮;同样,按计算机的电源按钮将注销Finder及Dock应用程序,但不会关闭系统。此特性可防止用户无意中关闭系统,而系统需要提供诸如打印服务或文件服务等这些共享服务。 -LoginHook和-LogoutHook参数特别有用,因为通过这个方法可以用来定制系统管理、帐号管理或安全程序,并可将它们作为登录和注销过程的一部分来运行。例如,在/etc/ttys中修改的控制台定义可能看起来会和下面的情况相类似: console ”/System/Library/CoreServices/loginwindow.app/loginwindow -PowerOffDisabled YES -LoginHook /Users/Administrator/Scripts/mailLoginToAdmin” vt100 on secure window=/System/Library/CoreServices/WindowServer onoption=”/usr/libexec/getty std.9600″ 使用环境变量 Mac OS X支持基于单独用户的UNIX格式的环境变量。在登录时,loginwindow应用程序将寻找一个名为environment.plist特殊的属性列表文件。此文件必须位于用户home目录根部的一个名为.Mac OSX的目录中。此文件的路径如下: ~/.Mac OSX/environment.plist 如果存在一个environment.plist文件,loginwindow将从此文件中读取关键字,并将它们作为用户环境变量来进行注册。此文 件只支持环境变量的定义,您不能使用此文件执行其它形式的脚本代码。与其它属性列表文件一样,它的文件格式为XML格式,文件中的每一关键字包含一个字符 串值。 ———————————————— 替换Finder 在登录时,Mac OS X也支持启动除Finder系统应用程序以外的程序。此功能是为想在登录时启动一个不同的默认应用程序的用户而设计的。例如,在登录时您可启动终端(Terminal)应用程序来取代Finder,以显示一个命令行界面。 为了替换Finder系统应用程序,可使用defaults实用工具来修改loginwindow的预置参数。Loginwindow预置参数被存 储在com.apple.loginwindow中。所需要更改的关键字是Finder关键字。使用下列语法为此关键字定义新值,并为所替换的应用程序指 定完整路径: defaults write com.apple.loginwindow Finder path 用户可在终端应用程序中执行这条命令,以改变当前用户的默认设置。为了使所有用户都改变此设置,必须在终端中以root用户来执行此命令。您也可修改/etc/ttys脚本或创建自己的登录钩子,这样可在每个用户登录时执行此钩子。 使用此命令后,并不阻止用户在登录后手动启动Finder。但如果发生意外崩溃或用户从强制退出(Force Quit)窗口中将其杀除,那么它确实可阻止loginwindow自动地重新启动Finder。