5. 启动后运行程序时会发生什么?

在启动后和您运行程序之前,您可以将您的计算机想象成包含一个进程动物园,它们都在等待着什么事情发生。它们都在等待事件。一个事件可以是您按下键盘上的一个键或移动鼠标。或者,如果您的机器连接到网络,一个事件可以是通过网络传入的数据包。

内核是这些进程之一。它是一个特殊的进程,因为它控制着其他用户进程何时可以运行,并且通常是唯一可以直接访问机器硬件的进程。实际上,当用户进程想要获得键盘输入、写入屏幕、从磁盘读取或写入磁盘,或者做任何除了在内存中处理位之外的事情时,它们必须向内核发出请求。这些请求被称为系统调用

通常,所有的 I/O 都通过内核,这样内核可以调度操作并防止进程互相干扰。少数特殊的的用户进程被允许绕过内核,通常是通过被赋予直接访问 I/O 端口的权限。X 服务器是这方面最常见的例子。

您将通过两种方式之一运行程序:通过您的 X 服务器或通过 shell。通常,您实际上会两者都做,因为您会启动一个模仿老式文本控制台的终端模拟器,从而为您提供一个 shell 来运行程序。我将描述当您这样做时会发生什么,然后我将回到当您通过 X 菜单或桌面图标运行程序时会发生什么。

shell 被称为 shell 是因为它包裹着并隐藏了操作系统内核。Unix 的一个重要特性是 shell 和内核是独立的程序,通过一小组系统调用进行通信。这使得可以存在多个 shell,以适应不同的界面偏好。

普通的 shell 会给您在登录后看到的 ‘$’ 提示符(除非您已将其自定义为其他内容)。我们在这里不讨论 shell 语法和您可以在屏幕上看到的简单内容;相反,我们将从计算机的角度看看幕后发生了什么。

shell 只是一个用户进程,而不是一个特别的进程。它等待您的击键,(通过内核)监听键盘 I/O 端口。当内核看到它们时,它会将它们回显到您的虚拟控制台或 X 终端模拟器。当内核看到 ‘Enter’ 键时,它会将您的文本行传递给 shell。shell 尝试将这些击键解释为命令。

假设您键入 ‘ls’ 并按下 Enter 键来调用 Unix 目录列表程序。shell 应用其内置规则来确定您想要运行文件中的可执行命令/bin/ls。它发出一个系统调用,请求内核启动 /bin/ls 作为一个新的子进程,并通过内核赋予它访问屏幕和键盘的权限。然后 shell 进入休眠状态,等待 ls 完成。

/bin/ls 完成时,它通过发出一个 exit 系统调用告诉内核它已完成。然后内核唤醒 shell 并告诉它可以继续运行。shell 发出另一个提示符并等待另一行输入。

然而,当您的 ‘ls’ 正在执行时,可能会发生其他事情(我们必须假设您正在列出一个非常长的目录)。例如,您可能会切换到另一个虚拟控制台,在那里登录并开始玩 Quake 游戏。或者,假设您已连接到互联网。您的机器可能在 /bin/ls 运行时发送或接收邮件。

当您通过 X 服务器而不是 shell 运行程序时(也就是说,通过从下拉菜单中选择应用程序,或双击桌面图标),与您的 X 服务器关联的任何几个程序都可以像 shell 一样运行并启动程序。我将在此处忽略这些细节,因为它们既是可变的,也是不重要的。关键点是,与普通的 shell 不同,X 服务器在客户端程序运行时不会进入休眠状态——相反,它位于您和客户端之间,将您的鼠标点击和按键传递给它,并满足其在显示器上绘制像素的请求。