多任务处理计算机中发生的事情
简介
通常了解一个事情的发生过程,可以帮助我们优化设计,通过更改功能组件满足不同的需求,让我们再次通过linux系统计算机回顾计算机的计算过程系统。
1 计算机启动时发生了什么
没有程序运行的计算机只是一堆电子器件。
打开计算机时,计算机要做的第一件事是启动一个称为“操作系统(operating system)”的特殊程序。
操作系统的工作是通过处理控制计算机硬件的混乱细节来帮助其他计算机程序运行。
操作系统启动过程称为 引导(booting)(最初是 引导,并指示“通过引导程序”将自己的拉起的过程)。
您的计算机知道如何启动,因为启动说明内置在其芯片之一BIOS(基本输入/输出系统)芯片中。
BIOS芯片告诉它要在固定的位置上查找,通常在编号最小的硬盘(引导盘)上查找称为引导加载程序的特殊程序(在Linux下,引导加载程序称为Grub或LILO)。
引导加载程序被拉入内存并启动。引导加载程序的工作是启动实际的操作系统。
加载程序通过查找 内核,将其加载到内存中并启动它来完成此操作。
如果您使用的是Linux,并且在屏幕上看到“ LILO”,然后是一堆点,则表示它正在加载内核。(每个点表示它已经加载了另一个内核代码的磁盘块。)
(您可能想知道为什么BIOS不会直接加载内核-为什么使用引导加载程序进行两步过程?嗯,BIOS并不是很聪明。
实际上,它非常愚蠢,而Linux并没有在内核上使用它。它最初是为带有小型磁盘的原始8位PC编写的,实际上无法访问足够的磁盘来直接加载内核。)
内核启动后,它必须四处查看,找到其余的硬件,并准备运行程序。它不是通过在普通的内存位置,而是在I / O端口 (特殊的总线地址,可能使设备控制器卡在监听它们的命令)的位置戳来做到这一点的。
内核不会随机戳;它具有很多内在的知识,这些知识可能会在哪里找到,以及控制器在出现时将如何响应。此过程称为 自动探测。
您可能看不到任何这种情况。回到Unix系统使用文本控制台时,随着系统启动,您会看到引导消息在屏幕上滚动。
如今,Unix经常将启动消息隐藏在图形启动画面的后面。您可以通过使用组合键Ctrl-Shift-F1切换到文本控制台视图来查看它们。
如果这样可行,您应该能够使用其他Ctrl-Shift顺序切换回图形引导屏幕。尝试F7,F8和F9。
引导时间发出的大多数消息是内核通过I/O端口自动探测硬件,弄清楚它可以使用什么并使其适应您的计算机。
Linux内核在这方面做的非常好,比大多数其他的Unix更好,甚至比DOS或Windows更好。
实际上,许多Linux的老手认为Linux的引导时间探针的聪明之处(使其相对容易安装)是其摆脱免费Unix实验包以吸引大量用户的主要原因。
但是,使内核完全加载并运行并不是引导过程的结束。这只是第一步(有时称为运行级别1)。
在第一阶段之后,内核将控制权交给一个名为“init”的特殊过程,该过程会产生几个内部管理过程。(最近的一些Linux使用了另一个名为“ upstart”的程序来执行类似的操作)
初始化过程的第一项工作通常是检查以确保您的磁盘正常。磁盘文件系统是脆弱的东西。
如果它们已因硬件故障或突然断电而损坏,则有充分的理由在Unix完全启动之前采取恢复步骤。我们稍后将在讨论文件系统如何出错时将对此进行讨论。
Init的下一步是启动几个守护程序。守护程序是一个程序,例如后台打印程序,邮件侦听器或 互联网网页服务器,它们潜伏在后台,等待事情发生。这些特殊程序通常必须协调几个可能冲突的请求。
它们是守护程序,因为编写一个经常运行并知道所有请求的程序通常比确保一组拷贝(每个请求处理一个请求并且所有请求都同时运行)要容易得多。
彼此。系统启动的特定守护程序集合可能会有所不同,但几乎总是包含一个打印后台处理程序(打印机的网守守护程序)。
下一步是为用户做准备。Init启动一个名为getty的程序的副本,以监视您的屏幕和键盘(也许还有更多副本,以监视拨入串行端口)。
实际上,如今,它通常会启动多个getty副本,因此您拥有多个(通常为7或8个)虚拟控制台,并且屏幕和键盘一次连接到其中一个。但是您可能看不到其中任何一个,因为您的一个控制台将被多个服务器接管(大约还有更多)。
我们还没有完成。下一步是启动支持网络和其他服务的各种守护程序。其中最重要的是您的 X 服务器。X是管理您的显示器,键盘和鼠标的守护程序。它的主要工作 通常是产生在屏幕上看到的彩色像素图形。
当X服务器启动时,在计算机引导过程的最后阶段,它可以有效地从以前控制的任何虚拟控制台接管硬件。届时,您将看到由称为显示管理器的程序为您制作的图形登录屏幕。
1.3 登录计算机时发生了什么
登录时,您可以在计算机中识别自己的身份。在现代Unix上,通常会通过图形显示管理器来执行此操作。
但是也可以使用Ctrl-Shift键序列切换虚拟控制台并进行文本登录。在这种情况下,您将遍历 getty实例,观看该控制台调用程序login。
您确定自己的显示管理器或 登录用的用户名和密码后。一般保存在名为/etc/passwd的文件中,如果丢失可以在此查找该登录名,该文件是一系列行,每个行描述一个用户帐户。
这些字段之一是帐户密码的加密版本(有时,加密的字段实际上以更严格的权限保存在第二个/etc/shadow文件中;这使密码破解更加困难)。
您作为帐户密码输入的内容将以完全相同的方式进行加密,然后登录程序会检查它们是否匹配。此方法的安全性取决于以下事实:虽然很容易将您的明文密码转换为加密版本,但反之则非常困难。
因此,即使有人可以看到您的密码的加密版本,他们也无法使用您的帐户。(这也意味着,如果您忘记了密码,则无法恢复密码,只能将其更改为您选择的其他密码。)
成功登录后,您将获得与所使用的单个帐户相关联的所有特权。您也可能被认为是团体的一部分 。
组是由系统管理员设置的用户的命名集合。组可以独立于其成员的特权而具有特权。
一个用户可以是多个组的成员。(有关Unix特权如何工作的详细信息,请参阅下面有关许可的部分。)
(请注意,尽管通常会按名称引用用户和组,但实际上它们是作为数字ID在内部存储的。密码文件将您的帐户名映射为用户ID;/etc/group 文件将组名映射为数字组ID。
处理帐户和组的命令会自动执行翻译。)
您的帐户条目还包含您的主目录,即个人文件将在Unix文件系统中存放的位置。最后,您的帐户条目还设置了 shell,该命令解释器将启动登录以接受您的命令。
成功登录后会发生什么情况取决于您的操作方式。在文本控制台上,登录将启动一个Shell,然后您就可以运行了。
如果您是通过显示管理器登录的,则X服务器将打开您的图形桌面,您将能够从中运行程序-通过菜单,桌面图标或运行shell的终端仿真器。
1.4.在启动后,程序会怎样运行?
在启动时间之后,在运行程序之前,您可以将计算机视为包含一系列正在等待做某事的进程动物园。
他们都在等待事件。事件可以是您按下键或移动鼠标。
或者,如果您的计算机 挂接到网络,则事件可能是通过该网络传入的数据包。
内核是这些过程之一。这是一个特殊的过程,因为它控制其他用户进程何时可以运行,并且通常是唯一可以直接访问计算机硬件的进程。
实际上,用户进程在想要获取键盘输入,写入屏幕,从磁盘读取或写入磁盘或执行除处理内存中的位以外的任何操作时,都必须向内核发出请求。这些向内核发出的请求称为系统调用。
通常,所有I/O都通过内核,因此它可以调度操作并防止进程相互干扰。通常,通过直接访问I/O端口,可以允许一些特殊的用户进程在内核中移动。X服务器是最常见的示例。
您将以两种方式之一运行程序:通过X服务器或通过Shell。 通常,您实际上会同时执行这两种操作,因为您将启动一个模仿老式文本控制台的终端仿真器,并为您提供运行程序的外壳程序。
我将描述执行此操作时发生的情况,然后再返回通过X菜单或桌面图标运行程序时的情况。
该壳(shell)之所以称为壳,是因为它环绕并隐藏了操作系统内核。
Unix的一个重要功能是外壳程序和内核是独立的程序,它们通过一小组系统调用进行通信。这样就可以有多个外壳,以适应界面中的不同口味。
普通外壳会为您提供登录后显示的“$”提示符(除非您已将其自定义为其他名称)。我们不会在这里讨论shell语法以及您可以在屏幕上看到的简单内容。
取而代之的是,从计算机的角度来看,我们将在幕后看一下所发生的事情。
Shell只是一个用户进程,并不是一个特别的进程。它等待您的击键,(通过内核)侦听键盘I/O端口。当内核看到它们时,它会将它们回显到您的虚拟控制台或X终端仿真器。
当内核看到“ Enter”字样时,它将您的文本行传递给外壳程序。Shell尝试将这些击键解释为命令。
假设您键入“ls”并按Enter来调用Unix目录列表器。外壳程序将使用其内置规则来确定您要在文件/bin/ ls中运行可执行命令 。
它进行系统调用,要求内核将/bin/ ls作为新的子进程启动,并使其通过内核访问屏幕和键盘。然后外壳进入睡眠状态,等待ls完成。
当/bin/ls 完成,它告诉它通过发出完成内核退出系统调用。然后内核唤醒外壳,并告诉它可以继续运行。Shell发出另一个提示,并等待另一行输入。
但是,在执行“ls”时可能还会发生其他事情(我们必须假设您列出的目录很长)。
例如,您可能会切换到另一个虚拟控制台,然后在其中登录并启动Quake游戏。或者,假设您已连接到Internet。 /bin/ ls运行时,您的机器可能正在发送或接收邮件。
当您通过X服务器而非外壳程序运行程序时(也就是说,通过从下拉菜单中选择应用程序,或双击桌面图标),与X服务器关联的多个程序中的任何一个都可以像外壳程序并启动程序。
我将在这里详细介绍这些细节,因为它们既可变又不重要。
关键点是,与普通的shell不同,X服务器不会在客户端程序运行时进入睡眠状态,而是位于您和客户端之间,将鼠标单击和按键传递给客户端,并满足其请求在显示器上显示像素。
1.5 输入设备和中断如何工作?
您的键盘是非常简单的输入设备。因为它会非常缓慢地生成少量数据(按照计算机的标准)。当您按下或释放一个键时,该事件将通过键盘电缆发出信号,以引发硬件中断。
监视此类中断是操作系统的工作。对于每种可能的中断,都会有一个中断处理程序,这是操作系统的一部分,它将存储与之相关的任何数据(例如您的keypress/keyrelease值),直到可以对其进行处理为止。
键盘的中断处理程序实际上所做的是将键值发布到内存底部附近的系统区域中。在那里,当操作系统将控制权传递给当前应该从键盘读取的任何程序时,都可以进行检查。
诸如磁盘或网卡之类的更复杂的输入设备以类似的方式工作。之前,我提到了使用总线的磁盘控制器来发出信号,表明已完成磁盘请求。实际发生的是磁盘引发中断。
然后,磁盘中断处理程序将检索到的数据复制到内存中,以供发出请求的程序以后使用。
每种中断都有一个相关的优先级。较低优先级的中断(如键盘事件)必须等待较高优先级的中断(如时钟滴答或磁盘事件)。Unix旨在为需要快速处理的各种事件赋予较高的优先级,以保持计算机的响应平稳。
在操作系统的启动时消息中,您可能会看到对IRQ信号(中断请求)的引用。您可能已经知道,错误配置硬件的一种常见方法是让两个不同的设备尝试使用相同的IRQ,而又不确切知道原因。
这就是答案。IRQ是“中断请求”的缩写。操作系统需要在启动时知道每个硬件设备将使用哪个编号的中断,因此它可以将适当的处理程序与每个硬件处理程序相关联。
如果两个不同的设备尝试使用相同的IRQ,则有时会将中断分派给错误的处理程序。这通常至少会锁定设备,并且有时会严重混淆操作系统,使其崩溃或崩溃。
1.6 分时共享:我的计算机如何一次执行多项操作?
实际上不是。计算机一次只能执行一项任务(或处理)。但是计算机可以非常快速地更改任务,并且会让人类他们以为自己正在同时执行多项操作。这称为 分时共享。
内核的工作之一是管理时间共享。它有一个叫做调度程序的部分,它可以将动物园中所有其他(非内核)进程的信息保存在内部。每1/60秒,内核中的计时器就会关闭,并产生时钟中断。调度程序将停止当前正在运行的任何进程,将其挂起在适当的位置,然后将控制权交给另一个进程。
1/60秒的时间听起来可能不多。但是在当今的微处理器上,足以运行成千上万的机器指令,这可以完成很多工作。因此,即使您有许多流程,每个流程也可以在其每个时间片中完成相当多的工作。
实际上,程序可能无法获得其整个时间片。如果中断来自I/O设备,则内核有效地停止当前任务,运行中断处理程序,然后返回到当前任务。大量的高优先级中断会挤出正常的处理过程。这种不当行为被称为thrashing,幸运的是,在现代Unix下很难引起这种行为。
实际上,程序的速度很少受到它们所能获得的机器时间的限制(该规则有一些例外,例如声音或3D图形生成)。当程序必须等待来自磁盘驱动器或网络连接的数据时,通常会引起延迟。
可以 并行支持许多同时处理的操作系统称为“多任务处理”。Unix操作系统家族是专为多任务而设计的,并且非常擅长于此—与Windows或旧的Mac OS相比—效率要高得多,后者后来都将多任务插入其中,但是做得相当差。
高效,可靠的多任务处理是使Linux在网络,通信和Web服务方面更胜一筹的重要原因。
2 我的计算机如何防止进程互相踩踏
内核的调度程序负责按时间划分进程。您的操作系统还必须在空间上划分它们,以使进程不会踩在彼此的工作内存上。
即使您假设所有程序都试图协作,您也不希望其中一个程序的错误能够破坏其他程序。操作系统为解决此问题所做的事情称为内存管理。
动物园中的每个进程都需要其自己的内存区域,作为从中运行其代码并保留变量和结果的地方。您可以将这个集合视为由一个只读代码段 (包含该过程的指令)和一个可写数据段 (包含所有进程的变量存储)。
数据段对于每个进程确实是唯一的,但是如果两个进程运行相同的代码,Unix将自动安排它们共享一个代码段,以提高效率。
2.1。虚拟内存:简单版本
效率很重要,因为内存很昂贵。有时您没有足够的空间来容纳机器正在运行的所有程序的全部,尤其是当您使用大型程序(例如X服务器)时。
为了解决这个问题,Unix使用了一种称为虚拟内存。它不会尝试将进程的所有代码和数据保存在内存中。取而代之的是,它只保持相对较小的 工作集。其余过程状态保留在硬盘上的特殊交换空间区域中。
请注意,在过去,上一段中的“有时”在过去是 “几乎总是” -相对于正在运行的程序,内存的大小通常较小,因此交换非常频繁。如今,内存的价格要便宜得多,即使是低端计算机也有很多。
在具有64MB以上内存的现代单用户计算机上,可以在最初将它们加载到内核后运行X和典型的作业混合而无需交换。
2.2。虚拟内存
实际上,最后一节将事情简化了一些。是的,程序将您的大部分内存视为比物理内存更大的地址的一个大的固定存储区,并且磁盘交换用于维持这种错觉。
但是实际上,您的硬件中至少有五种不同的内存,当必须调优程序以达到最大速度时,它们之间的差异会很重要。要真正了解机器中发生的事情,您应该了解它们的全部工作原理。
这五种存储器是:处理器寄存器,内部(或片上)高速缓存,外部(或片外)高速缓存,主存储器和磁盘。
种类繁多的原因很简单:速度要花钱。我以访问时间的递增顺序和成本的递减顺序列出了这些类型的内存。
寄存器,存储器是最快和最昂贵的,可以每秒随机访问约十亿次,而磁盘则是最慢和最便宜的,每秒可以执行约100次随机访问。
以下是一份完整列表,反映了典型台式机2000年代初期的速度。尽管速度和容量都会提高,价格也会下降,但是您可以期望这些比率 保持相当恒定 正是这些比率决定了内存层次结构。
磁碟
大小:13000MB访问量:100KB /秒
主存
大小:256MB访问次数:100M /秒
外部缓存
大小:512KB访问:250M /秒
内部缓存
大小:32KB访问次数:500M /秒
处理器
大小:28个字节访问量:1000M /秒
我们无法利用最快的内存构建所有内容。这太昂贵了-即使不是那样昂贵,快速内存也是易失的。也就是说,当电源关闭时,它会失去记录。
因此,计算机必须具有硬盘或其他类型的非易失性存储设备,这些设备在断电时仍会保留数据。而且,处理器的速度和磁盘的速度之间存在巨大的不匹配。
基本上存在内存层次结构的中间三个级别(内部缓存,外部缓存和主内存)来弥合这种差距。
Linux和其他Unix 具有称为虚拟内存的功能。这意味着操作系统的行为就好像它拥有比实际拥有的更多的主内存。
您实际的物理主内存的行为就像在更大的“虚拟”内存空间上的一组窗口或高速缓存一样,其中大多数在任何给定时间实际上都存储在磁盘上称为交换区的特殊区域中。
在用户程序看不见的情况下,操作系统正在存储器和磁盘之间移动 数据块(称为“页面”)以维持这种错觉。最终结果是您的虚拟内存比真实内存大得多,但不会慢太多。
虚拟内存比物理内存慢多少取决于操作系统的交换算法与程序使用虚拟内存的方式匹配的程度。幸运的是,在时间上靠近的内存读取和写入也倾向于聚集在内存空间中。
这种倾向被称为 本地(locality of reference),或者更正式访问的局部性-这是一件好事。
如果内存引用随机在虚拟空间周围跳转,则通常必须对每个新引用进行磁盘读写,而虚拟内存的速度将与磁盘一样慢。
但是,因为程序确实具有很强的局部性,所以您的操作系统可以对每个引用进行相对较少的交换。
经验发现,用于多种类型的内存使用模式的最有效方法非常简单。它称为LRU或 “最近最少使用”的算法。虚拟内存系统会根据需要将磁盘块放入其工作集中。
当工作集的物理内存用完时,它将转储最近最少使用的块。所有Unix和大多数其他虚拟内存操作系统在LRU上使用较小的变体。
虚拟内存是磁盘和处理器速度之间的桥梁中的第一条链接。它由操作系统明确管理。但是,物理主存储器的速度与处理器访问其寄存器存储器的速度之间仍然存在较大差距。
外部和内部缓存使用类似于我已描述的虚拟内存的技术来解决此问题。
就像物理主内存的行为就像磁盘交换区上的一组窗口或缓存一样,外部缓存也充当主内存上的窗口。外部缓存更快(每秒访问250M,而不是100M)且更小。
硬件(特别是计算机的内存控制器)对从主内存中获取的数据块执行外部高速缓存中的LRU操作。由于历史原因,高速缓存交换的单位称为行而不是页面。
但是我们还没有完成。内部缓存通过缓存部分外部缓存为我们提供了有效速度的最终提升。它更快,更小-实际上,它直接存在于处理器芯片上。
如果您想使程序变得非常快,那么了解这些详细信息将很有用。当程序具有更强的局部性时,它们会变得更快,因为这会使缓存更好地工作。
因此,使程序快速运行的最简单方法是使其变小。如果程序不会因大量磁盘I/O减慢速度或没有等待网络事件,那么它通常会以适合其中的最小缓存的速度运行。
如果您不能使整个程序变小,则可以花一些力气来调整速度关键部分,使它们具有更强的局部性。有关进行此类调整的技术的详细信息不在本教程的讨论范围之内。
到需要它们的时候,您将对某些编译器很熟悉,可以自己解决其中的许多问题。
2.3。内存管理单元
即使您有足够的物理核心来避免交换,操作系统中称为内存管理器的部分 仍然有重要的工作要做。
它必须确保程序只能更改其自己的数据段,也就是说,防止一个程序中的错误或恶意代码破坏另一个程序中的数据。
为此,它保留了一个数据表和代码段表。每当进程请求更多内存或释放内存时(通常在退出时释放后者),表都会更新。
该表用于将命令传递到称为MMU或 内存管理单元的基础硬件的专用部分 。现代处理器芯片在其上内置了MMU。MMU具有在内存区域周围设置围栏的特殊功能,因此超出范围的引用将被拒绝并引起特殊中断。
如果您看到Unix消息显示“ Segmentation fault”(分段错误), “ core dumped”(核心已转储)或类似内容,那么这就是发生了的事情。
正在运行的程序尝试访问其段外部的内存(内核)会引发致命中断。这表明程序代码中有错误;它留下的核心转储是诊断信息,旨在帮助程序员对其进行跟踪。
除了隔离进程访问的内存之外,还有另一个方面可以保护进程彼此。您还希望能够控制他们的文件访问,以便有漏洞的程序或恶意程序不会破坏系统的关键部分。这就是Unix具有 文件权限的原因,我们将在后面讨论。
- 点赞
- 收藏
- 关注作者
评论(0)