现在的位置: 首页 > 综合 > 正文

网上收集的mac启动过程,学习学习

2013年02月28日 ⁄ 综合 ⁄ 共 9902字 ⁄ 字号 评论关闭

1. 启动过程从用户启动Mac OS X系统到出现登录窗口,Mac OS X执行了一套启动流程来使系统可被使用。如果你想为所有用户提供系统服务,你需要在系统启动的过程中运行一些代码。下面的章节介绍了基本启动流程和应该把你提供服务的代码放到何处。
1.1. BootROM当一台Macintosh被启动时,BootROM固件同时也被激活。BootROM(也是电脑的一个硬件)拥有两个主要职责:初始化(译者注,其实就是启动各个硬件,让其准备好被使用)系统的硬件和选择一个操作系统来启动。BootROM拥有两个部分来帮助它实现这两个职责:

  • POST(Power-On Self Test,开机自检)初始化硬件接口,验证是否有足够可用RAM以支持系统运行,并检查可用RAM是否处于正常状态。
  • 在PowerPC架构的Macintosh电脑上,Open Firmware初始化剩下的硬件,建立最初的设备树(译者注,原文device tree)(类似目录树,一个用层级关系的方式来表示各硬件与主机间的逻辑关系),并且选择操作系统来启动。

在Intel架构的Macintosh电脑上,EFI来处理基本的硬件初始化,并且选择一个操作系统来启动。如果安装有多个可启动的Mac OS X系统,BootROM会选择那个最后被系统预置中启动磁盘设置项选择的操作系统。用户可以在电脑启动时按住Option键来自行选择启动的系统,这个做法会让Open Firmware或者EFI显示一个选择启动宗卷的界面。

注意,在一些遗留机型(译者注,老机型)上,有些版本的BootROM既可以启动Mac OS 9系统也可以启动Mac OS X。而大多数现在的机型只能启动Mac OS X。

1.2. BootX,boot.efi,系统初始化一旦BootROM的工作完成,并且选择了个Mac OS X分区被选择用其启动,控制权就被传递给BootX(PowerPC平台)或者boot.efi(Intel平台)启动引导器。启动引导器的主要工作就是加载内核环境(译者注,原文kernel environment),作此工作时,启动引导器会在屏幕上显示一个启动画面。我们可以在根分区的/System/Library/CoreServices目录下找到BootX和boot.efi。而且,可以找到/usr/standalone/i386/boot.efi这个boot.efi的拷贝。在“exotic”(译者注,字面意思是“外来的,外国的”,但显然这里不是只外接硬盘的意思。)模式下启动的时候,比如说从一个软RAID宗卷上启动的时候,一个启动引导器会保存在一个叫做独立的HFS+的”辅助“(译者注,原文“helper”)宗卷上来启动系统。在一些版本的Mac OS X上,内核和mkext缓存的拷贝亦会保存在辅助宗卷里。也就是,这种情况下,根分区下面的引导器和其他一些部件不起作用。

注意:不推荐用UFS格式做Mac OS X v10.5的引导宗卷。

启动过程最开始,启动引导器尝试加载一个包含了所有设备驱动程序的预链接(译者注,原文prelink,这个词的意思是,为了节省时间而预先把一些动态链接库的连接方式记录在执行档中)的内核版本,其位置在:/System/Library/Caches/com.apple.kernelcaches。预链接这些设备驱动程序可以缩短系统启动时间。如果预链接版本的内核丢失,已经过期,或者已损坏,启动引导器会加载一个包含了与预连接内核所列相同驱动的单独压缩包,此包被称作mkext缓存。如果mkext缓存包过期,丢失,或者已损坏,启动引导器会搜索/System/Library/Extensions,寻找OSBundleRequired属性根据启动类型(例如本地启动或者网络启动)所列的驱动列表来加载驱动。查看I/O Kit Fundamentals(I/O工具纲要)可以获得更多加载驱动的信息。一旦内核和所有为启动而必需的驱动加载成功,启动引导器就启动内核的初始化进程。此时应该有足够的驱动被加载,以找到根设备(译者注,原文root device)来加载内核。也是在此时开始,PowerPC架构的Macintosh电脑上,Open Firmware不再被访问(静默状态)。内核初始化Mach和BSD数据结构(译者注,原文data structure,我也不知道他这里到底指什么意思,应该就是指BSD那一层的东西。)以及I/O Kit。I/O Kit使用设备树(译者注,device tree)作为根据来连接那些已经加载进内核的驱动。一旦内核找到根设备(译者注,原文root device),BSD将把此为根*(译者注,原文Once the kernel finds the root device, it roots(*) BSD off of it.)(来启动)。

注意:作为一个术语,“启动”(boot)这个词传统上讲是指加载启动引导器和启动硬盘或者分区上的内核。而最近几年,这个词的含义被扩展了第二层意义:指启动系统可以被最终用户使用的整个启动过程。在这里,“启动”这个词是指第一种含义。

在这里,“根”(root)这个词是指把一个分区作为根分区加载,或者是第一层,或者是文件系统(译者注,原文mounting a partition as the root, or top-level, filesystem,不知道是不是指这个逻辑关系。)。因此,系统在根分区上启动的时候,内核将会在运行启动脚本之前,把这个分区认为根分区(译者注,原文Thus, while the OS boots off of the root partition, the kernel roots the OS off of the partition before executing startup scripts from it.)。

Mac OS X v10.4以前,系统初始化一直是交给mach_init和init来处理。初始化过程中,这两个处理进程调用不同的系统脚本(在/ect/rc目录下),启动程序,为用户准备系统。Mac OS X v10.4以后,这些系统脚本和守候进程的调用交由launchd来处理。也就是说,目前,launchd是系统根进程。除了初始化系统已外,launchd进程还协调系统守候进程秩序地调用。就像inetd进程一样,launchd按需启动守候进程(译者注,原文launchd launches daemons on-demand,其实就是指那种launch-on-demand方式。)。以这种方式调用的守候进程可以在不活动期间被关闭或者按需要重启。(当一个服务的请求发送过来的时候,launchd会自动重新启动守候进程去处理请求。)这种方式可以释放守候进程占用的内存和其他相关资源,当守候进程在一段很长的时间闲置的时候,这样做非常值得。但更重要的,这样做相对于人工方式能更有效的处理守候进程间的依赖关系。然后,launchd 启动SystemStarter,后者用来启动那些非按需启动(译者注,原文non-launch-on-demand)的守候进程。

注意,launchd也支持非按需启动的守候进程,但是这种用法并不推荐。launchd守候进程被设计用来消除守候进程之间的依赖关系。如果你不把你的守候进程设置成按需启动(译者注,原文launch-on-demand),你就需要用其他办法处理依赖问题,比如用那种遗留下来的Startup Item机制。

查看Daemons可以获得更多关于按需启动(原文launch-on-demand)和SystemStarter守候进程的信息。系统初始化的最后阶段,launchd启动loginwindow。loginwindow程序控制了用户会话(原文user session)各自的外观(原文aspect)和登录窗口的调整以及用户登录认证。

注意,默认情况下,Mac OS X随着一个图形化的启动屏幕启动。为了调试启动进程,我们也可以禁用它,而显示文字操作台信息。这种模式被称作verbose启动模式。要想使用verbose启动模式,只需要在启动的时候按住command-v键。


1.3. 用户认证Mac OS X要求用户在进入系统前进行验证。loginwindow程序分为登录部分(显示为用户输入用户名和密码的窗口)以及安全部分(处理用户的认证信息)。一旦通过安全系统的认证,loginwindow程序开始配置用户环境。有两种情况loginwindow会忽略通常的登录方式而直接开始用户会话。第一种是当系统管理员设定计算机自动以一个指定的用户登录的时候。另一种是安装软件时,如果installer程序在电脑重启后立即运行的时候。
1.4. 配置用户会话用户成功认证后,loginwindow会马上配置用户环境并且记录这次登录信息。此时会进行如下任务:

  • 对未经授权的远程登录会话采取安全措施。未经注册(译者注,原文reigstered,就是指前面说的未经授权)的应用程序不能使用粘贴板服务(Clipboard)端口。再此情况下,一些标准的功能不能使用,包括复制,剪切,粘贴,Apple events,窗口最小化,还有其他服务。
  • 把登录记录在系统的utmp数据库中。
  • 为控制台终端配置拥有者(译者注,原文owner)和权限。
  • 重置用户偏好,从而加入全局系统默认值。
  • 通过bootstap端口和启动pbs注册粘贴板服务(pbs)。
  • 根据用户偏好设置鼠标,键盘,系统声音。
  • 设置用户组权限(gid)
  • 从目录服务(Directory Services)中检索用户记录,并且将信息加入到此会话中。
  • 加载用户环境(包括偏好设置,环境变量,设备和文件权限,钥匙串访问(keychain access)等等)。
  • 启动Dock,Finder和SystemUIServer。
  • 启动用户在 偏好设置 中的 帐户设置 中 登录项目项 中设置的应用程序。

一旦用户会话启动并开始运行,loginwindow通过一下方式监视会话和用户的应用程序。

  • 管理用户登出,重启和关闭过程。查看“Logout Responsibilities“以获得更多信息。
  • 管理强制退出窗口,包括监视当前活动的应用程序,并且响应用户对强制退出某应用程序或者重启Finder的请求(用户可以从苹果菜单或者按下Command-Option-Escape键来启动强制退出窗口)。
  • 将标准错误输出(stderr)写入日志文件。日志文件储存在/资源库(Library)/Logs/Console/ <uid> /console.log文件里,<uid>表示当前登录用户的ID。

如果Finder,Dock或者SystemUIServer进程因为某种原因死掉了,loginwindow会自动重启他们。同样,如果loginwindow进程死掉了,launchd进程会将其重启。
1.5. 注销(Logout Rrsponsibilities)注销,系统重启,关机,这些过程都有着相似语义。前端进程往往因用户在苹果菜单中选择上述一项而启动这些过程。然而,一个进程也可以以编程的方法向loginwindow发送一个响应的Apple event来启动这些过程。loginwindow程序执行这个过程(译者注,指注销,系统重启,关机这些中的一项),发送报警(alert)以及通知应用程序,让他们有机会在关闭前做调整。以下是一个典型的注销/系统重启/关机过程:

  • 用户在苹果菜单中选择注销,重新启动,或者关机项。
  • 前端程序根据用户请求向loginwindow发送一个Apple event。
  • loginwindow程序向用户显示一个警示对话框向用户求证是否要执行此操作。
  • 如果用户确定执行此操作,则loginwindow向每一个前端和后端的用户进程发送一个“Quit Application Apple event“(kAEQuitApplication)。
  • 一旦所有进程退出,loginwindow关闭用户会话,并继续执行:
    • 对于注销操作,loginwindow将事件队列中的所有事件出列,启动logout-hook程序(如果有定义),记录注销操作,将设备权限和用户偏好重设为默认值,并退出。随后launchd会启动一个新的登录。(查看“Customizing Login and Logout“以获得更多关于loginwindow hook的信息。)
    • 对于重新启动操作,longinwindow将设备权限和用户偏好设置为默认值并重启系统。
    • 对于关机操作,loginwindow将系统关闭。

前端进程在接收到Quit Application event的时候可以选择不终止程序。查看“Terminating Processes“以得到更多信息。
1.5.1. 应用程序(Application Responsibilities)要想以程序的方式启动一个注销,重新启动,或者关机过程,前端应用程序必须向loginwindow发送一个相应的Apple event。接收到event后,loginwindow开始关闭用户会话。根据发送过来的Apple event,loginwindow会选择是否展示一个警示对话框并给用户一个取消此过程的机会。下表显示了注销,重新启动,关闭过程对应的Apple event。这些event不需要参数。

  • kAELogOut
  • kAEShowRestartDialog
  • kAEShowSutdownDialog

接收到这些event后,loginwindow显示一个警示对话框通知用户计算机即将执行的操作。此时,用户可以选择继续此操作或者终止它。如果用户继续此操作,loginwindow向每个应用程序发送一个要求其退出的Apple event。查看“Terminating Processes.“以获得更多信息。这里还有两个event用来通知loginwindow立即重新启动或是关闭:

  • kAERestart
  • kAEShutDown

这些event被处理时不会向用户展示警示对话框。因此,如果你这些event给loginwindow,用户没有机会去取消操作,所以这些event要被谨慎地使用。

重要信息:注意,如果一个注销,重新启动或者关机event是被一个Classic环境中的应用程序发送的,这些event只会对Classic环境和其中的应用程序起作用。剩下的用户会话将会继续运行。


1.5.2. 终止进程作为注销,重新启动,关机过程中的一部分,loginwindow尝试终止所有的前台和后台的用户进程。它向每个进程发送Quit Application Apple event(kAEQuitApplication),并且出于礼貌(译者注,原文as a courtesy,看着有点搞笑,但确实是这个意思)它会给每个进程优雅的关闭的机会。对于前端进程,loginwindow发送event并且等待回复。对于后端进程,loginwindow发送event,而不等待回复。它会用kill命令终止拖延的后端进程。当一个前端进程接收到loginwindow发送过来的Quit Application Apple event时,它会立即终止自己,或者在用户需要时显示一个警示对话框(例如此时正有一个未保存的文档),等问题解决后再终止自己。如果用户决定取消终止(例如在保存对话框中点取消按钮)应用程序会给发送过来的event返回一个userCancelledErr错误。

注意:Cocoa应用程序不支持kAEQuitApplication event,取而代之的,Application Kit通过调用delegate方法applicationShouldTerminalte来实现终止程序。要想取消此操作,可以实现这个方法并返回NSTerminateCancel;不然,应用程序的终止操作将会继续执行。

如果一个前端应用程序响应失败或者超过45秒钟仍未终止,loginwindow自动取消终止操作。这个保护措施可以在很多情况下保护数据,例如当一个应用程序正在保存一个大文件到磁盘中并且此时不能在要求的时间内终止程序的时候。如果一个前端应用程序反应迟钝或者没有做任何事情,用户必须使用“强制退出”来强制退出(kill)该程序。对于使用了(link with)Carbon,Cocoa,Java的后端进程,操作方式将会有一点不一样。loginwindow程序通过发送Quit Application Apple event(kAEQuitApplication)通知进程将被终止。不同于对待前端进程那样,loginwindow不等待后端进程回应,它直接终止开放的后端进程,不管任何被返回的错误信息。用户注销的过程中,loginwindow不会终止root层的进程。这些进程不属于用户会话,他们只会在重新启动或者关机的时候被终止。loginwindow程序也不会杀死(kill)不依赖Carbon,Cocoa,Java的后端进程,尽管他们是用户层进程。(尽管在用户层面被启动,这些进程在用户登出的时候被系统接管。)Mac OS X在终止系统进程的时候不会向其发送任何通知。
1.6. 进程作用域(Identifying the Scope of Processes)尽管launchd进程是所有其他系统进程的拥有者,用户和系统进程间仍然会被区分。“startup item“,守候进程,以及其它在loginwindow之前运行的进程一般是运行于root层。这一层次的进程为系统的所有用户提供服务。运行于已认证的用户会话中的进程被称作“用户进程”(user processes)。用户进程往往附属于用户会话,往往也是WindowServer和loginwindow进程的子进程。

注意:不是所有的用户进程都是WindowServer进程的子进程。那些root层启动的进程,特殊的系统进程,这些进程拥有者是用户,但他们是launchd的子进程。你可以通过活动监视器来判断系统中一个进程的拥有者和父进程。


1.7. 关机(The Shutdown Process)关机时,Mac OS X首先关闭SystemStarter启动的项目,比如在“Creating a Startup Item“中描述的项目。然后,就像大多数基于UNIX或者类UNIX操作系统那样,Mac OS X在关机前发送一个SIGTTERM信号给所有在运行的进程。一旦接收到这个信号,你的守候进程会迅速合理地关闭自己。允许合理的尝试等待进程退出,不过你的守候进程的最终责任是把未保存的信息在分配的时间内保存在磁盘上。几秒钟后,你的守候进程会接收到一个SIGKILL信号,并被终止。

 

启动过程:
1、 电源开启。
2、 执行固件中的代码。
3、 收集硬件信息并初始硬件。
4、 选择启动项(通常是选择 OS ,但有时会选择硬件测试等类似情况。)。用户可能会被提示进行启动选择。
5、 控制权交给 /System/Library/CoreServices/BootX (启动引导器)。 x86为boot.efi
6、 执行内核中的 init 例程。决定要启动之系统的根设备。从此刻起,将不再使用固件中的程序。
7、 由内核初始各种 Mach/BSD 数据结构。
8、 初始 I/O (输入输出)设备。

9、 内核开始运行 /sbin/mach_init ,Mach 服务命名(引导程序)后台。mach_init 为服务名和要准备访问其它服务所用的 Mach 端口提供映射。
到这步时,启动开始转为用户等级:
10、 mach_init 开始 /sbin/init,传统的 BSD 初始化(init)进程。初始化将决定运行等级,并运行 /etc/rc.boot (设置让机器能够运行单用户-single user 模式)。
在此步中,将执行: rc.boot 与其它 rc 脚本源程序 /etc/rc.common,一个包含实用功能的 shell 脚本,如 CheckForNetwork() (检查如网络已启动), GetPID(), purgedir() (仅删除目录内容,而非结构),等。
11、 rc.boot 会显示要启动的类型(多用户,安全模式,光驱,网络等等)。网络启动的情况下( sysctl 的变量 kern.netboot 将会为何种情况而设之为 1 ),其将用一个启动参数来运行 /etc/rc.netboot 。
/etc/rc.netboot 会处理网络启动的参数特征。例如:执行网络和(如有)本地挂载。其还会呼叫 /usr/bin/nbst 来关联当作根设备使用的磁盘镜像到一个影子文件(shadow file)。此方法是将那个希望处于本地存储器的文件(磁盘)重定向写入到影子文件。
12、 rc.boot 会在必须进行文件系统一致性检查(file system consistency check, fsck)时,显示图形。单用户模式和用光盘启动时不会运行 fsck。安全模式启动时总会运行 fsck。rc.boot 也会处理 fsck 的返回状态。
13、 如果 rc.boot 成功退出, /etc/rc 多用户启动脚本将会运行。如果正在从一个光驱启动,脚本将切换到 /etc/rc.cdrom (安装)。
14、 /etc/rc 挂载本地文件系统 (HFS+、HFS、UFS、/dev/fd、/.vol),确保目录 /private/var/tmp 存在,然后运行 /etc/rc.installer_cleanup 如果有(重启前,会由安装器离开)。
15、 /etc/rc.cleanup 运行。其将“清理”一定数量的 Unix 与 Mac 特殊目录/文件。
16、 启动缓存 (BootCache)开始。
17、 各种 sysctl 变量被设置(如:vnodes 的最大值、System V IPC 等)。如果 /etc/sysctl.conf 已存在 (在 Mac OS X Server 中为 /etc/sysctl-macosxserver.conf),它将读取和设置 sysctl 变量为已包含在其中的。
18、 syslogd 开始。
19、 创建机器检查符号文件(Mach symbol file)。
20、 /etc/rc 开始 kextd 后台进程,用来从内核或委托进程 (client processes)加载所需的内核扩展。
21、 /usr/libexec/register_mach_bootstrap_servers 将运行以加载包含在 /etc/mach_init.d 中的各种 Mach 引导程序所基于的服务。
22、 portmap 与 netinfo 开始。
23、 如 /System/Library/Extensions.mkext 旧于 /System/Library/Extensions, /etc/rc 将删除已存在的 mkext 并创建一个新的(不存在时,会创建)。
24、 /etc/rc 启动 /usr/sbin/update,一个后台程序,用来频繁地清空磁盘上的互联网文件系统缓存。
25、 /etc/rc 启动虚拟内存系统。 设置 /private/var/vm 为一个交换目录。/sbin/dynamic_pager 以适当的参数启动(交换文件名路径模板、已创建的交换文件大小、当创建额外交换文件或删除已存在文件时,指定高、低水平的警报切换开关。)
26、 /etc/rc 启动 /usr/libexec/fix_prebinding 以修复错误地预连编二进制文件 (prebound binaries)
27、 /etc/rc 执行 /etc/rc.cleanup 以清除并重置文件与设备。
28、 /etc/rc 最后将启动 /sbin/SystemStarter ,处理启动项从下列位置: /System/Library/StartupItems 与 /Library/StartupItems。一个启动项是一个程序、一个 shell 脚本、匹配一个文件夹名的名称。文件夹包含一个属性列表文件含有一些配对的关键值,如: Description、Provides、Requires、 OrderPreference、启动与停止信息等等。您可以运行 SystemStarter -n -D 以作为根用户 (root) 来进行程序打印调试与从属信息(不包含现在已经在运行的任何项目)。
29、 CoreGraphics 启动开始 Apple 类型服务后台(ATSServer) 和 Window 服务器 (WindowServer)。
默认下,loginwindow 程序 (loginwindow.app 位于 /System/Library/CoreServices 目录下) 已为控制设备执行。如果您不想运行到图形登录,可以修改 /etc/ttys 中相关的行。

抱歉!评论已关闭.