目录
在计算机的学习和开发过程中,操作系统是我们必须要掌握的知识,从这里,我们开始对操作系统进行学习!
一台电脑的诞生!
Step1:厂家组装一台裸机,所谓裸机就是说只包含 CPU 、内存、硬盘、主板等。纯硬件。
Step2:出售前安装操作系统。出售一台电脑肯定是不能只包含硬件的,需要在出售之前安装操作系统,我们通常使用的就是 Windows 10
Step3:用户安装应用程序。我们拿到电脑之后都需要在操作系统的基础之上安装一些应用程序,如 QQ、刀塔、英雄联盟、绝地求生等。
Step4:使用 QQ 聊天,玩刀塔、英雄联盟、绝地求生等游戏。这部分功能是建立在我们下载完应用程序的基础之上,这部分功能需要根据用户的需求来实现。
细心的可以发现:用户和操作系统之间是有联系的,应用程序和操作系统之间也是有联系的,我们接着往下看:
1. 操作系统的基本概念
在信息化时代,软件是计算机系统的灵魂,作为软件核心的操作系统,与现代计算机系统密不可分、融为一体。计算机系统自上而下可大致分为 4 部分:硬件、操作系统、应用程序和用户。操作系统管理各种计算机硬件,为应用程序提供基础,并充当计算机硬件与用户之间的中介。
硬件如中央处理器、内存、输入/输出设备等,提供基本的计算资源。应用程序如字处理程序、电子制表软件、编译器、网络浏览器等,规定按何种方式使用这些资源来解决用户的计算问题。操作系统控制和协调各用户的应用程序对硬件的分配和使用。在计算机系统的运行过程中,操作系统提供了正确使用这些资源的方法。
综上所述,操作系统(Operating System,OS)是指控制和管理整个计算机系统的硬件和软件资源,合理的组织、调度计算机的工作与资源的分配,进而为用户和其他软件提供方便接口与环境的程序集合。操作系统是计算机系统中最基本的系统软件。
简单来说,操作系统是系统资源的的管理者。管理着硬件和软件。
举个直观的例子:Windows 操作系统下:Ctrl + Alt + Delete 启动任务管理器。
同时操作系统要给用户和其他软件提供方便的接口和环境的意思是说:操作系统要向上层提供方便易用的服务。操作系统的上层就是指用户和应用程序(软件)。
1.1 操作系统的特征
操作系统是一种系统软件,但与其他系统软件和应用软件有很大的不同,它有自己的特殊性即基本特性。操作系统的基本特性包括:并发、共享、虚拟和异步。
1.1.1 并发(Concurrence)
并发是指两个或多个事件在同一时间间隔内发生。操作系统的并发性是指计算机系统中同时存在多个运行的程序,因此它具有处理和调度多个程序同时执行的能力。在操作系统中,引入进程的目的是使程序能并发执行。(并发性是指计算机系统中可以同时存在多个运行的程序,但是注意,在同一时刻,只能有一个程序运行,不同程序之间是存在时间间隔的,这个一定要注意!)
注意:同一时间间隔(并发)和同一时刻(并行)的区别
在多道程序环境下,一段时间内,宏观上有多道程序在同时执行,而在每个时刻,单处理机环境下实际仅能有一道程序执行,因此微观上这些程序仍是分时交替执行的。操作系统的并发性是通过分时得以实现的。
并行性是指系统具有同时进行运算或操作的特性,在同一时刻能完成两种或两种以上的工作。并行性需要有相关硬件的支持,如多流水线或多处理机硬件环境。
举个例子:
我们以现实生活中的一个直观例子来学习并发性和并行性。
比如说:如果你在 9:00~9:10 仅吃面包,在 9:10~9:20 仅写字,在 9:20~9:30 仅吃面包,在 9:30~10:00 仅写字,那么在 9:00~10:00 吃面包和写字这两种行为就是并发执行的;再如,如果你在 9:00~10:00 右手写字,左手同时拿着面包吃,那么这两个动作就是并行执行的。
注意:
单核 CPU 同一时刻只能执行一个程序,各个程序只能并发的执行;
多核 CPU 同一时刻可以同时执行多个程序,多个程序可以并行的执行;
比如说 Intel 的第八代 i3 处理器就是 4 核 CPU,意味着可以并行的执行 4 个程序;
比如说,四核 CPU 现在同时运行着微信、QQ、Word、谷歌;四核 CPU 并行的执行着 4 个程序;
如果说现在还想再运行着QQ音乐的话,因为是 4 核 CPU,不可能并行的执行着 5 个程序,所以有其中一个程序就需要和 QQ音乐 进行轮换;这个时候,轮换的程序和 QQ音乐就是并发的执行;
对于 4 核 CPU 来说,只要有 4 个以上的程序需要 “同时” 运行,那么并发性依然是必不可少的,因此并发性是操作系统的一个最基本的特性。
1.1.2 共享(Sharing)
资源共享即共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。共享可分为以下两种资源共享方式。
(1)互斥共享方式
系统中的某些资源,如打印机、磁带机,虽然可供多个进程使用,但为了使所打印或记录的结果不至于造成混淆,应规定在一段时间内只允许一个进程访问该资源。
为此,当资源 A 访问某个资源时,必须先提出请求,若此时该资源空闲,则系统便将之分配给进程 A 使用,此后有其他进程也要访问该资源时(只要 A 未用完)就必须等待。仅当进程 A 访问完并释放该资源后,才允许另一个进程对该资源进行访问。我们把这种资源共享方式称为互斥式共享,而把在一段时间内只允许一个进程访问的资源称为临界资源。计算机系统中的大多数物理设备及某些软件中所用的栈、变量和表格,都属于临界资源,它们都要求被互斥地共享。
举个例子:
互斥共享方式:使用 QQ 和微信视频,同一时间段内摄像头资源只能分配给其中一个进程。这个我们在使用手机的过程中可以发现,当一个进程在使用该资源时,另一个进程若也想使用该资源,系统会提示,该资源正在被另一个进程所使用。
(2)同时访问方式
系统中还有另一类资源,这类资源允许在一段时间内由多个进程 “同时” 访问。这是所说的 “同时” 通常是宏观上的。而是微观上,这些进程可能是交替地对该资源进行访问即 “分时共享” 的。(也可以理解为通过一个个时间片,可能时间片的时间间隔非常小)。可供多个进程 “同时” 访问的典型资源就是磁盘设备,一些用重入码编写的文件也可被 “同时” 共享,即允许若干个用户同时访问该文件。
举个例子:
同时共享方式:比如说我们使用 QQ 发送文件 A,同时使用微信发送文件 B。从宏观上来讲,两边都是同时读取并发送文件。我们知道,要发送文件,操作系统首先要先访问磁盘资源,将该文件放置到内存中,然后才能发送文件;宏观上,也就是从我们的角度来看,发送文件的进程是一步一步在推进的,说明两个进程都在访问硬盘资源,从中读取数据。
但是从微观上来看,两个进程是交替的访问磁盘的;也就是说同一个精确的时间点,只有一个进程在运行,可能这个时间片非常非常的小,也就是这个时间片发送文件 A,下一个时间片发送文件 B,发送文件 A 和发送文件 B 从微观上来看是交替进行的。
注意:互斥共享要求一种资源在一段时间内(哪怕是一段很小的时间)只能满足一个请求,否则就会出现严重的问题,(你能想象打印机第一行打印 A 文档的内容、第二行打印 B 文档的内容的效果吗?)。而同时访问共享通常要求一个请求分几个时间片段间隔地完成,其效果与连续完成的效果相同。
并发和共享是操作系统两个最基本的特征,两者之间互为存在的条件:①资源共享是以程序的并发为条件的,若系统不允许程序并发执行,则自然不存在资源共享问题;②若系统不能对资源共享实施有效的管理,则必将影响到程序的并发执行,甚至根本无法并发执行。
举个例子:
通过上面的例子我们来看并发和共享的关系:
使用 QQ 发送文件 A,同时使用微信发送文件 B。
1. 两个进程正在并发地执行(并发性)
2. 需要共享的访问硬盘资源(共享性)
试想一下,如果失去并发性,那么意味着两个进程不能并发的执行,也就是说系统中只能有一个程序正在运行,那共享性就变的毫无意义;因为系统中只能有一个程序运行,那个这个资源就是这个程序所独占的,自己独占的不存在共享;比如我们周围的共享单车,在众多共享单车中有一个私人的山地车,那么上一个人骑完这个共享单车,锁上车,我还可以骑这辆车;私人的山地车就是锁上了,别人也不能骑;
如果失去了共享性,也就是说两个进程只能有其中一个访问硬盘资源,我们知道,要发送一个文件,操作系统首先需要访问硬盘资源,然后将该程序对应的文件程序放到内存中,然后才能实现文件的发送;如果操作系统不能访问硬盘资源,那么发送文件的这个进程就不能被执行,也就无法实现同时发送文件,并发性也就不复存在;
1.1.3 虚拟(Virtual)
首先需要知道一段程序需要放入内存并给它分配 CPU 才能执行。
虚拟是指把一个物理上的实体变为若干逻辑上的对应物。物理实体(前者)是实的,即实际存在的;而后者是虚的,是用户感觉上的事物。(也就是说把实际存在的实物变为逻辑上并不存在的虚拟物)用于实现虚拟的技术,称为虚拟技术。操作系统中利用了多种虚拟技术来实现虚拟处理器、虚拟内存和虚拟外部设备等。
虚拟处理器技术是通过多道程序设计技术,采用让多道程序并发执行的方法,来分时使用一个处理器的。此时,虽然只有一个处理器,但它能同时为多个用户服务,使每个终端用户都感觉有一个中央处理器(CPU)在专门为它服务。利用多道程序设计技术把一个物理上的 CPU 虚拟为多个逻辑上的 CPU,称为虚拟处理器。
举个例子:
某单核 CPU 的计算机中,用户打开了以下软件:
问题:我们知道一段程序需要被放入内存中并且给分配 CPU 程序才会被运行,那么既然一个程序需要被分配 CPU 才能运行,那么为什么单核 CPU 的电脑可以同时运行这么多个程序呢?
这就应用了虚拟处理器技术。实际上只有一个单核 CPU,但是在用户看来似乎有 6 个 CPU 在同时为自己服务。
在虚拟存储器技术中,操作系统将主存划分为一系列大小相等的页(页框),并且对辅助存储器也进行类似划分,每个存储页的大小可以是固定的(通常为4KB)。当程序需要访问主存中的某个地址时,操作系统会首先检查该地址是否已经在主存中。如果地址已经在主存中,则程序可以直接访问该地址的数据。如果地址不在主存中,则操作系统会根据一定的算法将存储在辅助存储器中的某个页换出,并将所需的页加载到主存中,然后程序再次尝试访问该地址。
虚拟存储器技术的核心思想在于,操作系统将主存看作一个逻辑上连续的存储空间,而不论实际上物理内存中的页是否连续存放。这样可以方便地将程序的地址空间映射到主存中,并且可以灵活地进行页的置换和加载操作。通过使用虚拟存储器技术,计算机可以运行更大规模的程序,而不受物理内存大小的限制。
总结起来,虚拟存储器技术通过将主存和辅助存储器结合起来,扩展了计算机的有效内存大小。它通过将主存划分为固定大小的页,并使用页面置换算法进行管理,使得程序可以访问不断加载和换出的页,从而实现对计算机内存的有效利用。
举个例子:
游戏 GTA5 需要 4GB 的运行内存,QQ 需要 256M的内存,迅雷需要 256M的内存,网易云音乐需要 256M的内存……
但是电脑只有 4GB的运行内存;
问题:这些程序同时运行需要的内存远大于 4GB,那么为什么以上这些还可以在我的电脑上同时运行?
其实这就是应用了虚拟存储器技术。实际只有 4GB的内存,在用户看来似乎远远大于 4GB。
类似地,可以采用虚拟存储器技术将一台机器的物理存储器变为虚拟存储器,以便从逻辑上扩充存储器的容量。当然,这时用户所感觉到的内存容量是虚的。我们把用户感觉到(但实际不存在)的存储器称为虚拟存储器。
还可采用虚拟设备技术将一台物理 I/O 设备虚拟为多台逻辑上的 I/O 设备,并允许每个用户占用一台逻辑上的 I/O 设备,使原来仅允许在一段时间内由一个用户访问的设备(即临界资源)变为在一段时间内允许多个用户同时访问的共享设备。
因此,操作系统的虚拟技术可归纳为:时分复用技术,如处理器的分时共享;空分复用技术,如虚拟存储器。
显然,如果失去了并发性,则一个时间段内系统只能运行一个程序,这样也就不存在实现虚拟性的意义了,因为系统实现虚拟性的优点就是为了实现单核 CPU 运行多个程序。单个程序没有并发性,就谈不上虚拟性。
1.1.4 异步(Asynchronism)
多道程序环境允许多个程序并发执行,但由于资源有限,进程的执行并不是一贯到底的,而是走走停停的,它以不可预知的速度向前推进,这就是进程的异步性。
异步性使得操作系统运行在一种随机的环境下,可能导致进程产生与时间有关的错误(就像对全局变量的访问顺序不当会导致程序出错一样)。然而,只要运行环境相同,操作系统就须保证多次运行进程后都能获得相同的结果。
举个例子:
一个男孩同时和两个女孩进行约会,女孩记为 女孩 A,女孩 B(只是个简单的例子,无特殊含义):
女孩 A 的指令 1 是:男孩陪我吃饭;指令 2 是:男孩把心给我。记为第一道程序;
女孩 B 的指令 1 是:男孩把心给我;指令 2 是:男孩陪我吃饭。记为第二道程序; 系统并发的执行第一道程序和第二道程序;
异步的定义规定:多个程序并发执行;资源有限在这个例子中体现在男孩的心;
现在假设有两种约会方式:
甲:
8点 ~ 9点:女孩 A 指令 1 :男孩陪我吃饭
9点 ~ 10点:女孩 A 指令 2 :男孩把心给我,这里注意男孩的心是有限的资源,给出去之后就不能再给了
10点 ~ 11点:女孩 B 指令 1 :男孩把心给我 这里注意,在上一个时间段中,男孩已经把心给到女孩 A 了,现在女孩 B 的指令无法完成,程序就会陷入停顿状态;
11点 ~ 12 点:女孩 B 指令 2 :男孩陪我吃饭
乙:
8点 ~ 9点:女孩 A 指令 1 :男孩陪我吃饭
9点 ~ 10点:女孩 B 指令 1 :男孩把心给我,这里注意男孩的心是有限的资源,给出去之后就不能再给了
10点 ~ 11点:女孩 A 指令 2 :男孩把心给我 这里注意,在上一个时间段中,男孩已经把心给到女孩 B 了,现在女孩 A 的指令无法完成,程序就会陷入停顿状态;
11点 ~ 12 点:女孩 B 指令 2 :男孩陪我吃饭
由于并发运行的程序会争抢着使用系统的资源,但是系统中的资源是有限的,因此不管是出现上述甲还是乙的第三步骤,程序都会陷入停顿状态,因此程序的执行不是一贯到底的,而是走走停停的,并且以不可预知的速度向前推进。很明显,如果失去了并发性,那么程序只能一个一个的运行,运行完上一个程序才能运行下一个程序,这样一来每个程序的执行都会一贯到底;
所以说只有系统拥有了并发性,才有可能导致异步性。
1.2 操作系统的目标和功能
为了给多道程序提供良好的运行环境,操作系统应具有以下几方面的功能:处理机管理、存储器管理、设备管理和文件管理。为了方便用户使用操作系统,还必须向用户提供接口。同时,操作系统可用来扩充机器,以提供更方便的服务、更高的资源利用率。
我们用一个直观的例子来理解这种情况。例如,用户是雇主,操作系统是工人(用来操作机器),计算机是机器(由处理机、存储器、设备、文件几个部分构成),工人有熟练的技能,能够控制和协调各个部件的工作,这就是操作系统对资源的管理;同时,工人必须接受雇主的命令,这就是 “接口”;有了工人,机器就能发挥更大的作用,因此工人就成了 “扩充机器”。(简单来说就是: 操作系统必须满足用户的要求,操作系统和用户之间通过接口进行命令的传输。操作系统必须能够协调和控制各个部件之间的工作)
1.2.1 操作系统作为计算机系统资源的管理者
这里我们通过一个例子来学习操作系统作为系统资源管理者的功能:
现在我们出门在外,很方便的可以通过微信和家人、朋友进行聊天、通话以及视频。这里我们来看一下微信和朋友进行视频聊天的过程:
Step1:首先在各个文件夹下找到微信的安装目录,这里当然有人会说,我的微信就在电脑桌面上,不用找,事实上,我们在操作系统上下载的所有应用程序都是在磁盘中的,包括桌面也属于磁盘范畴。(如 D:\WeChat )
逐层打开文件夹,找到 WeChat 这个程序(可执行文件)的存放位置。事实上,我们只是在点击鼠标,而电脑找到文件的过程就是操作系统在执行的,这就体现了操作系统的功能:文件管理。
Step2:双击打开 WeChat.exe 文件
首先我们要明白,计算机执行一个程序之前是要将该程序放到内存中的,才能被 CPU 处理。将程序放到内存的过程实际上是操作系统在完成的,并且这些数据需要放到操作系统的什么位置也是操作系统在帮我们完成的,这就体现了操作系统的功能:存储器管理。
Step3:微信程序正常运行
对应的微信进程被处理机(CPU)处理,也可以说是什么时候进程需要被 CPU 处理,什么时候进程不需要被 CPU 处理,这都是操作系统在背后替我们完成的。这就体现了操作系统的功能:处理机管理。
Step4:开始和朋友视频聊天
我们都知道,使用微信开始和朋友进行视频聊天时,肯定需要将摄像头功能供微信使用,像摄像头这类设备资源也都是操作系统在背后进行管理的。这就体现了操作系统的功能:设备管理。
(1)处理机管理
在多道程序环境下,处理机的分配和运行都以进程(或线程)为基本单位,因而对处理机的管理可归纳为对进程的管理。并发是指计算机内同时运行多个进程,因此进程何时创建、何时撤销、如何管理、如何避免冲突、合理共享就是进程管理的最主要的任务。进程管理的主要功能包括进程控制、进程同步、进程通信、死锁处理、处理机调度等。
(2)存储器管理
存储器管理是为了给多道程序的运行提供良好的环境,方便用户使用及提高内存的利用率,主要包括内存分配与回收、地址映射、内存保护与共享和内存扩充等功能。
(3)文件管理
计算机中的信息都是以文件的形式存在的,操作系统中负责文件管理的部分称为文件系统。文件管理包括文件存储空间的管理、目录管理及文件读写管理和保护等。
(4)设备管理
设备管理的主要任务是完成用户的 I/O 请求,方便用户使用各种设备,并提高设备的利用率,主要包括缓冲管理、设备分配、设备处理和虚拟设备等功能。
这些工作都是由工人负责的。
1.2.2 操作系统作为用户与计算机硬件系统之间的接口
为了让用户方便、快捷、可靠地操纵计算机硬件并运行自己的程序,操作系统还提供了用户接口。操作系统提供的接口主要分为两类:一类是命令接口,用户利用这些操作命令来组织和控制作业的执行;另一类是程序接口,编程人员可以使用它们来请求操作系统服务。
简单来说就是:计算机裸机(纯硬件)只听得懂二进制指令,比如说:010111110001101010101 ,硬件对外直接进行交互暴露了其不友好的缺点。
但是在硬件之上安装了操作系统,用户不再需要和裸机(纯硬件)进行交互,用户转而和操作系统进行直接交互,用户将所需的服务传达至操作系统,操作系统再传达给裸机(纯硬件),操作系统对外暴露了非常友好的交互接口。这就体现了操作系统作为用户与计算机硬件系统之间的接口的功能。
这就类似于封装的思想:操作系统把一些丑陋的硬件功能封装成简单易用的服务,使用户能够更方便的使用计算机,用户无需关心底层硬件的原理,只需要对操作系统发出命令即可。
(1)命令接口
使用命令接口进行作业控制的主要方式有两种,即联机控制方式和脱机控制方式。按作业控制方式的不同,可将命令接口分为联机命令接口和脱机命令接口。
联机命令接口又称交互式命令接口,适用于分时或实时系统的接口。它由一组键盘操作命令组成。用户通过控制台或终端输入操作命令,向系统提出各种服务要求。用户每输入一条命令,控制权就转给操作系统的命令解释程序,然后由命令解释程序解释并执行输入的命令,完成指定的功能。之后,控制权转回控制台或终端,此时用户又可输入下一条命令。联机命令接口可以这样理解∶"雇主"说一句话,"工人"做一件事,并做出反馈,这就强调了交互性。
举个例子:
Windows 操作系统下打开命名解释器:
Step1:Win 键 + R
Step2:输入 Cmd ,回车,就会弹出命令解释器
Step3:尝试使用各种命令,比如说 time 命令
这就是 Windows 操作系统下典型的联机命令接口,典型的特点就是:用户说一句,系统跟着做一句;
脱机命令接口又称批处理命令接口,适用于批处理系统,它由一组作业控制命令组成。脱机用户不能直接于预作业的运行,而应事先用相应的作业控制命令写成一份作业操作说明书.连同作业一起提交给系统。系统调度到该作业时,由系统中的命令解释程序逐条解释执行作业说明书上的命令,从而间接地控制作业的运行。脱机命令接口可以这样理解;"雇主"把要"工人"做的事写在清单上,"工人"按照清单命令逐条完成这些事,这就是批处理。
同样举个例子:
在 Windows 操作系统下,借助搜索功能,在 C 盘中搜索 *.bat 文件,这类文件都是 Windows 操作系统下的批处理文件。
打开这些文件,你会发现每个文件中都包含着一批命令,其实这一批命令中的每一个命令都是联机命令接口所提供的每一个单一的命令。
这就是 Windows 操作系统下典型的脱机命令接口,典型的特点就是:按照一批命令逐个完成其中的每一个命令。用户说一堆,系统跟着做一堆;
(2)程序接口
程序接口由一组系统调用(也称广义指令)组成。用户通过在程序中使用这些系统调用来请求操作系统为其提供服务,如使用各种外部设备、申请分配和回收内存及其他各种要求。这类接口是专门供程序员使用的。普通用户不能直接使用程序接口,只能通过程序代码间接使用。
举个例子:
我们在 C 语言中写 “Hello World!” 时,用到了 printf 函数,其实在调用 printf 函数时,底层就使用到了操作系统提供的显式相关的 “系统调用” 。
程序员通过调用 C 语言库函数,printf 函数就属于 C 语言库函数,printf 这个函数的实现其实是通过系统调用来实现的,操作系统收到系统调用的命令后,会在硬件(显示器)上显示出 printf 函数所要显示的 “Hello World!”。
系统调用类似于函数调用,是应用程序请求操作系统服务的唯一方式。
当前最为流行的是图形用户界面(GUI),即图形接口。GUI最终是通过调用程序接口实现的,用户通过鼠标和 键盘在图形界面上单击或使用快捷键,就能很方便地使用操作系统。严格来说,图形接口不是操作系统的一部分,但图形接口所调用的系统调用命令是操作系统的一部分。比如说在 Windows 操作系统下,要删除一个文件只需要把文件 “拖拽” 到回收站即可。
1.2.3 操作系统实现了对计算机资源的扩充
没有任何软件支持的计算机称为裸机,它仅构成计算机系统的物质基础,而实际呈现在用户面前的计算机系统是经过若干层软件改造的计算机。裸机在最里面,其外面是操作系统。操作系统所提供的资源管理功能和方便用户的各种服务功能,将裸机改造成功能更强、使用更方便的机器;因此,我们通常把覆盖了软件的机器称为扩充机器或虚拟机。
“工人” 操作机器,机器就有了更大的作用,于是 “工人” 便成了 “扩充机器”。
举个例子:
比如说一台汽车:
发送机——只会转;轮胎——只会滚;
但是如果在原始的硬件机器上覆盖一层传动系统——让发动机带着轮子转——使原始的硬件机器得到拓展
操作系统对硬件机器的拓展:将 CPU、内存、磁盘、显示器、键盘 等硬件合理地组织起来,让各种硬件能够相互协调配合,实现更多更复杂的功能。
2. 操作系统运行环境
2.1 处理器运行模式
程序是如何在底层硬件中运行的?
像我们写的 C 语言代码会首先通过编译器 “翻译” 为计算机可以识别的二进制指令,也称作机器指令。
“指令” 就是处理器(CPU)能识别、执行的最基本的命令。
比如说上图中的例子,C语言写出的程序为 lnt x = 1; x++; 但是转换成二进制后变成了一段计算机可以识别的代码,程序执行的过程其实就是 CPU 执行一条一条的机器指令的过程。也就是说不管是多么复杂的代码,最后执行的时候都会变成 CPU 可以识别的二进制代码;
计算机系统中,通常 CPU 执行两种不同性质的程序:一种是操作系统内核程序;另一种是用户自编程序(即系统外层的应用程序,或简称 “应用程序”)。对操作系统而言,这两种程序的作用不同,前者是后者的管理者,因此 “管理程序” (即内核程序)要执行一些特权指令,而 “被管理程序”(即用户自编程序)出于安全考虑不能执行这些指令。
区分应用程序和内核程序:
所谓的应用程序就是跑在操作系统之上的程序,我们将这类程序称之为应用程序。我们普通程序员写的程序就是 “应用程序”。
直接的说:比说微软、苹果有一帮人负责实现操作系统,他们所写的程序就是 “内核程序”。
由很多内核程序组成了 “操作系统内核”,或简称 “内核(Kernal)”。
内核是操作系统最重要最核心的部分,也是最接近硬件的部分。
操作系统最重要的功能就是作为系统资源的管理者,操作系统实现系统资源的管理的代码就是在内核中的。
甚至可以说,一个操作系统只要有内核就够了。
操作系统的功能未必都在内核中,比如说图形化界面 GUI。
(1)特权指令,是指不允许用户直接使用的指令,如 I/O 指令、置中断指令,存取用于内存保护的寄存器、送程序状态字到程序状态字寄存器等的指令。
操作系统内核作为 “管理者”,有时会让 CPU 执行一些 “特权指令”,如:内存清零指令。这些指令影响重大,只允许 “管理者” ——也就是操作系统内核来使用。
(2)非特权指令,是指允许用户直接使用的指令,它不能直接访问系统中的软硬件资源,仅限于访问用户的地址空间,这也是为了防止用户程序对系统造成破坏。
应用程序只能使用 “非特权指令”,如:加法指令、减法指令等。
在 CPU 设计和生产的时候就划分了特权指令和非特权指令,因此 CPU 执行一条指令前就能判断出其类型。
那么问题来啦:CPU 能判断出指令类型,但是它是怎么区分此时正在运行的是内核程序还是应用程序呢?
这里就用到了接下来需要介绍的 “用户态” 和 “内核态” 了。
CPU 有两种状态,“内核态” 和 “用户态”
处于内核态时,说明此时正在运行的是内核程序,此时可以执行特权指令
处于用户态时,说明此时正在运行的是应用程序,此时只能执行非特权指令
CPU 中有一个寄存器叫 程序状态字寄存器(PSW),其中有个二进制位,1 表示 “内核态”,0 表示 “用户态” 。
别名:内核态 = 核心态 = 管态;用户态 = 目态;
在具体实现上,将 CPU 的运行模式划分为用户态(目态)和核心态(又称管态、内核态)。可以理解为 CPU 内部有一个小开关,当小开关为 0 时,CPU 处于核心态,此时 CPU 可以执行特权指令,切换到用户态的指令也是特权指令。当小开关为 1 时,CPU 处于用户态,此时 CPU 只能执行非特权指令。用户自编程序运行在用户态,操作系统内核程序运行在核心态。
在软件工程思想和结构化程序设计方法影响下诞生的现代操作系统,几乎都是分层式的结构。操作系统的各项功能分别被设置在不同的层次上。一些与硬件关联较紧密的模块,如时钟管理、中断处理、设备驱动等处于最低层。其次是运行频率较高的程序,如进程管理、存储器管理和设备管理等。这两部分内容构成了操作系统的内核。这部分内容的指令操作工作在核心态。
通过一个故事我们来看内核态和用户态究竟是如何进行切换的?
① 计算机刚开机,CPU 为 “内核态” ,计算机会加载操作系统,操作系统会进行某些初始化的工作,操作系统内核程序先在 CPU 上进行运行。
② 开机完成后,用户可以根据自己的需求运行某个应用程序。
③ 操作系统内核程序在合适的时候主动让出 CPU 的使用权,让该应用程序进入 CPU 进行运行。(因为开机时加载操作系统是在内核态下完成的,但是应用程序属于非特权指令,需要在用户态下完成,这个时候就需要进行内核态和用户态之间的切换)内核程序如果想让应用程序进入 CPU 运行,也可以说是主动的让出 CPU 的使用权,那么操作系统内核会在让出 CPU 之前,用一条特权指令把程序状态字寄存器(PSW)的标志位设置为 “用户态”。这个时候 CPU 就会进入 “用户态”,也就可以执行用户程序了。
④ 应用程序运行在 “用户态”。这个时候 CPU 会执行应用程序的一条一条的指令。
⑤ 此时,一位黑客在应用程序中植入了一条特权指令,企图去破坏系统……
这个时候 CPU 正在一条一条的执行用户程序,但是掺杂了一条由黑客植入的特权指令,当这条指令在 CPU 上运行时,CPU 马上就能识别这条指令是特权指令,但是 CPU 又检查了自己的 PSW 寄存器发现自己处于用户态,是运行不了特权指令的,所以 CPU 坚决不会让这条指令运行。
⑥ CPU 发现接下来要执行的这条指令是特权指令,但是自己又处于 “用户态”。
⑦ 这是一个非法事件,会引起一个中断信号
CPU 检测到中断信号后,会立即强制变为 “核心态”,并停止运行当前的应用程序,转而去运行处理中断信号的内核程序。 接下来 CPU 就在内核态下执行一系列的处理中断信号的内核程序。
⑧ “中断” 使得操作系统再次夺回 CPU 的控制权
⑨ 操作系统会对引发中断的事件进行处理,处理完了再把 CPU 使用权交给别的应用程序
内核态 -> 用户态:执行了一条特权指令——修改 PSW 的标志位为 “用户态”,这个动作意味着操作系统将主要让出 CPU 使用权。用户态 -> 内核态:由 “中断” 触发,硬件自动完成状态变换的过程,触发中断信号意味着操作系统将强行夺回 CPU 的使用权
内核是计算机上配置的底层软件,它管理着系统的各种资源,可以看作是连接应用程序和硬件的一座桥梁,大多数操作系统的内核包括 4 方面的内容。
1. 时钟管理
在计算机的各种部件中,时钟是最关键的设备。时钟的第一功能是计时,操作系统需要通过时钟管理,向用户提供标准的系统时间。另外,通过时钟中断的管理,可以实现进程的切换。例如,在分时操作系统中采用时间片轮转调度,在实时操作系统中按截止时间控制运行,在批处理系统中通过时钟管理来衡量一个作业的运行程度等。因此,系统管理的方方面面无不依赖于时钟。
2. 中断机制
引入中断技术的初衷是提高多道程序运行环境中 CPU 的利用率,而且主要是针对外部设备的。后来逐步得到发展,形成了多种类型,成为操作系统各项操作的基础。例如,键盘或鼠标信息的输入、进程的管理和调度、系统功能的调用、设备驱动、文件访问等,无不依赖于中断机制。可以说,现代操作系统是靠中断驱动的软件。
中断机制中,只有一小部分功能属于内核,它们负责保护和恢复中断现场的信息,转移控制权到相关的处理程序。这样可以减少中断的处理时间,提高系统的并行处理能力。
3. 原语
按层次结构设计的操作系统,底层必然是一些可被调用的公用小程序,它们各自完成一个规定的操作。它们的特点是:
1. 处于操作系统的最低层,是最接近硬件的部分。
2. 这些程序的运行具有原子性,其操作只能一气呵成(出于系统安全性和便于管理考虑)。也就是说这段程序要么一气呵成全部运行,要么一点也不运行,不可以被 “中断”(也就是在执行原语这段程序的过程中,哪怕有中断过来了,也要先执行完原语,在进入中断)。
3. 这些程序的运行时间都较短,而且调用频繁。
通常把具有这些特点的程序称为原语。定义原语的直接方法是关闭中断,让其所有动作不可分割地完成后再打开中断。系统中的设备驱动、CPU 切换、进程通信等功能中的部分操作都可定义为原语,使它们成为内核的组成部分。
4. 系统控制的数据结构及处理
系统中用来登记状态信息的数据结构很多,如作业控制块、进程控制块(PCB)、设备控制块、各类链表、消息队列、缓冲区、空闲区登记表、内存分配表等。为了实现有效的管理,系统需要一些基本的操作,常见的操作有以下三种:
1. 进程管理。进程状态管理、进程调度和分派、创建与撤销进程控制块等。
2. 存储器管理。存储器的空间分配和回收、内存信息保护程序、代码对换程序等。
3. 设备管理。缓冲区管理、设备分配和回收等。
核心态指令实际上包括系统调用类指令和一些针对时钟、中断和原语的操作指令。
2.2 中断和异常的概念
CPU 上会运行两种程序,一种是操作系统内核程序(是整个系统的管理者),一种是应用程序。只不过在合适的情况下,操作系统内核会把 CPU 的使用权主动让给应用程序。总之,一个应用程序上 CPU 上进行运行,那么就会一直运行下去,除非发生中断,“中断” 是让操作系统内核夺回 CPU 使用权的唯一途径。“中断” 会使 CPU 由用户态变为内核态,使操作系统重新夺回对 CPU 的控制权。
试想一下,如果没有 “中断” 机制,那么一旦应用程序上 CPU 运行,CPU 就会一直运行这个应用程序;只有一个程序,这样一来,“并发” 的概念就不复存在;所以说中断是实现并发的必要条件。
内核态 -> 用户态:内核主动让出 CPU 的使用权,内核执行一条特权指令——修改 PSW 寄存器的标志位为 “用户态”,这个动作意味着操作系统将主动让出 CPU 使用权。用户态 -> 内核态:内核想要重新夺回 CPU 的使用权,由 “中断” 触发,硬件自动完成变换状态的过程,触发中断信号意味着操作系统将强行夺回 CPU 的使用权。
在操作系统中引入核心态和用户态这两种工作状态后,就需要考虑这两种状态之间如何切换。操作系统内核工作在核心态,而用户程序工作在用户态。系统不允许用户程序实现核心态的功能,而它们又必须使用这些功能。因此,需要在核心态建立一些 “门” ,以便实现从用户态进入核心态。在实际操作系统中,CPU 运行上层程序时唯一能进入这些 “门” 的途经就是通过中断或异常。发生中断或异常时,运行用户态的 CPU 会立即进入核心态,这是通过硬件实现的(例如,用一个特殊寄存器的一位来表示 CPU 所处的工作状态,0 表示核心态,1 表示用户态。若要进入核心态,则只需要将该位置置 0 即可)。中断是操作系统中非常重要的一个概念,对一个运行在计算机上的实时操作系统而言,缺少了中断机制,将是不可想象的。原因是:操作系统的发展过程大体上就是一个想方设法不断提高资源利用率的过程,而提高资源利用率就需要在程序并未使用某种资源时,把它对那种资源的占有权释放,而这一行为就需要通过中断实现。
2.2.1 中断和异常的定义
中断(Interruption)也称外中断,是指来自 CPU 执行指令外部的事件,通常用于信息输入/输出,如设备发出的 I/O 结束中断,表示设备输入/输出处理已经完成。时钟中断,表示一个固定的时间片已到,让处理机处理计时、启动定时运行的任务等。
异常(Exception)也称内中断,是指来自 CPU 执行指令内部的事件,如程序的非法操作码、地址越界、运算溢出、虚存系统的缺页及专门的陷入指令等引起的事件。异常不能被屏蔽,一旦出现,就应立即处理。
内中断:和当前执行的指令有关,中断信号来源于 CPU 内部
举个例子:
CPU 正在执行用户程序,此时 CPU 处于用户态,只能执行非特权指令;如上图所示:CPU 一条一条的执行着非特权指令,但是会发现指令 3 是特权指令,当执行指令 3 时,CPU 会立刻发现该指令是特权指令,通过查询 PSW 寄存器发现自己处于用户态,那么特权指令是万万不能执行的;CPU 会触发一条中断信号,硬件强制的进入内核态;
进入内核态以后,会执行处理中断信号的内核程序;这就是内中断的例子;
例子 1 :试图在用户态下执行特权指令(上图的例子就是试图在用户态下执行特权指令)
例子 2 :执行除法指令时发现除数为 0
总的来说:
若当前执行的指令是非法的,则会引发一个中断信号。
例子 3 :有时候应用程序想要请求操作系统内核的服务,此时会执行一条特殊的指令(注意:特殊指令并不意味着特权指令)——陷入指令,该指令会引发一个内部中断信号。
这个指令会引发一个内部中断信号,CPU 会由用户态进入内核态;转而去执行处理中断信号的内核程序。
也可以说:如果一个应用程序执行陷入指令的话,那么意味着用户态主动把 CPU 的使用权让给内核态使用。“系统调用” 其实就是通过陷入指令来完成的,用户态的应用程序请求操作系统内核来为其服务。
外中断:与当前执行的指令无关,中断信号来源于 CPU 外部
例子 1 :时钟中断——由时钟部件发来的中断信号
时钟部件是一个硬件资源(这也体现了与当前执行的指令无关,中断信号来源于 CPU 外部的硬件资源),就像我们单片机上的时钟一样,通过设置一个时间片(比如 50ms),那么时钟部件每隔一个 50ms 就会给 CPU 发送一个时钟中断信号。
例子 2 :I/O 中断——由输入/输出设备发来的中断信号
比如说打印机,在 CPU 运行过程中,打印机发送的中断信号属于输入/输出设备产生的中断信号。
2.2.2 中断和异常的分类
外中断可分为可屏蔽中断和不可屏蔽中断。
可屏蔽中断是指通过 INTR 线发出的中断请求,通过改变屏蔽字可以实现多重中断,从而使得中断处理更加灵活。
不可屏蔽中断是指通过 NMI 线发出的中断请求,通常是紧急的硬件故障,如电源掉电等。此外,异常也是不能被屏蔽的。
异常可分为故障、自陷和终止。
故障(Fault)通常是由指令执行引起的异常,如非法操作码、缺页故障、除数为 0、运算溢出等。由错误条件引起的,可能被内核程序修复。内核程序修复故障后会把 CPU 的使用权还给应用程序,让它继续执行下去。比如说:缺页故障。
自陷(Trap)是一种事先安排的 “异常” 事件,用于在用户态下调用操作系统内核程序,如条件陷阱指令。由陷入指令引发,用于请求操作系统的服务,是应用程序故意引发的。
终止(Abort)是指出现了使得 CPU 无法继续执行的硬件故障,如控制器出错、存储器校验错等。由致命错误引起的,内核程序无法修复该错误,因此一般不再将 CPU 使用权还给引发终止的应用程序,而是直接终止该应用程序。如:整数除 0 、非法使用特权指令。
故障异常和自陷异常属于软件中断(程序性异常),终止异常和外部中断属于硬件中断。
2.2.3 中断和异常的处理过程
中断和异常处理过程的大致描述如下:当 CPU 在执行用户程序的第 i 条指令时检测到一个异常事件,或者执行第 i 条指令后发现了一个中断请求信号,则 CPU 打断当前的用户程序,然后转到相应的中断或异常处理程序去执行。若中断或异常处理程序能够解决相应的问题,则在中断或异常处理程序的最后,CPU 通过执行中断或异常返回指令,回到被打断的用户程序的第 i 条指令或第 i+1 条指令继续执行;若中断或异常处理程序发现是不可恢复的致命错误,则终止用户程序。通常情况下,对中断和异常的具体处理过程由操作系统(和驱动程序)完成。
中断机制的基本原理:
不同的中断信号,需要用不同的中断处理程序来处理。当 CPU 检测到中断信号后,会根据中断信号的类型去查询 “中断向量表”,以此来找到相应的中断处理程序咋内存中的存放位置。
显然,中断处理程序一定是内核程序,需要运行在 “内核态”。
2.3 系统调用
所谓系统调用,是指用户在程序中调用操作系统所提供的一些子功能,系统调用可视为特殊的公共子程序。系统中的各种共享资源都由操作系统统一掌管,因此在用户程序中,凡是与共享资源有关的操作(如存储分配、进行 I/O 传输及管理文件等),都必须通过系统调用的方式向操作系统提出服务请求,并由操作系统代为完成(简单的可以理解为:共享资源大家是公平享有的,如果没有操作系统协调分配各个资源,那么系统就乱套了;各个应用程序如果想要使用某个资源必须向操作系统发出请求)。通常,一个操作系统提供的系统调用命令有几十条乃至百条之多。“系统调用” 是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以通过系统调用来请求获得操作系统内核的服务。这些系统调用按功能大致可分为如下几类。
- 设备管理。完成设备的请求或释放,以及设备启动等功能。
- 文件管理。完成文件的读、写、创建及删除等功能。
- 进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。
- 进程通信。完成进程之间的消息传递或信号传递等功能。
- 内存管理。完成内存的分配、回收以及获取作业占用内存区大小及始址等功能。
举个例子来看为什么系统调用是必须的?
去学校打印店打印论文,当你按下了 WPS 的 “打印” 选项,打印机开始工作。
当你的论文打印到一半时,另一位同学按下了 Word 的 “打印” 选项,开始打印他自己的论文。
我们知道计算机中的 WPS 和 Word 是两个不同的进程,此时电脑并发的执行这两个应用程序;试想一下,如果两个进程可以随意地、并发地共享打印机资源,那么两个进程并发运行,打印机设备交替地收到 WPS 和 Word 两个进程发来的打印请求,最终结果两篇论文混淆在一起了,你能想象打印一下 A 同学的第一行,再打印 B 同学的第二行吗?
解决方法:由操作系统内核对共享资源(这里的共享资源就是打印机)进行统一地管理,并向上提供 “系统调用”,用户进程想要使用打印机这种共享资源,只能通过系统调用向操作系统发出请求。内核会对各个请求进行协调处理。
显然,系统调用相关功能涉及系统资源管理、进程管理之类的操作,对整个系统的影响非常大,因此必定需要使用某些特权指令才能完成,所以系统调用的处理需要由操作系统内核程序负责完成,要运行在核心态。用户程序可以执行陷入指令(又称访管指令或 trap 指令)来发起系统调用,请求操作系统提供服务。
可以这么理解:用户程序执行 “陷入指令” ,相当于把 CPU 的使用权主动交给操作系统内核程序(CPU 状态会从用户态进入核心态),之后操作系统内核程序再对系统调用请求做出相应处理。处理完成后,操作系统内核程序又会把 CPU 的使用权还给用户程序(即 CPU 状态会从核心态回到用户态)。这么设计的目的是:用户程序不能直接执行对系统影响非常大的操作,必须通过系统调用的方式请求操作系统代为执行,以便保证系统的稳定性和安全性,防止用户程序随意更改或访问重要的系统资源,影响其他进程的运行。
这样,操作系统的运行环境就可以理解为:用户通过操作系统运行上层程序(如系统提供的命令解释程序或用户自编程序),而这个上层程序的运行依赖于操作系统的底层管理程序提供服务支持,当需要管理程序服务时,系统则通过硬件中断机制进入核心态,运行管理程序;也可能是程序运行出现异常情况,被动地需要管理程序的服务,这时就通过异常处理来进入核心态。管理程序运行结束时,用户程序需要继续运行,此时通过相应的保存的程序现场退出中断处理程序或异常处理程序,返回断点处继续执行。
在操作系统这一层面上,我们比较关心的是系统核心态和用户态的软件实现与切换。
下面列举一些由用户态转向核心态的例子:
- 用户程序要求操作系统的服务,即系统调用。
- 发生一次中断。
- 用户程序中产生了一个错误状态。
- 用户程序中企图执行一条特权指令。
- 从核心态转向用户态由一条指令实现,这条指令也是特权指令,一般是中断返回指令。
注意:由用户态进入核心态,不仅状态需要切换,而且所用的堆栈也可能需要由用户堆栈切换为系统堆栈,但这个系统堆栈也是属于该进程的。
若程序的运行由用户态转到核心态,则会用到访管指令,访管指令是在用户态使用的,所以它不可能是特权指令。
操作系统访管指令通常是用于管理和监控计算机操作系统的命令。以下是一些常见的操作系统访管指令:
Windows操作系统:
- tasklist:显示当前正在运行的进程列表。
- taskkill:终止指定的进程。
- netstat:显示网络连接和端口状态。
- ipconfig:显示和管理网络配置信息。
- chkdsk:检查磁盘上的错误并修复它们。
- sfc /scannow:扫描并修复操作系统文件的完整性。
Linux操作系统:
- ps:显示当前正在运行的进程列表。
- kill:终止指定的进程。
- netstat:显示网络连接和端口状态。
- ifconfig:显示和管理网络接口配置信息。
- df:显示磁盘空间使用情况。
- fsck:检查和修复文件系统上的错误。
系统调用的过程:
3. 操作系统结构
随着操作系统功能的不断增多和代码规模的不断扩大,提供合理的结构,对于降低操作系统复杂度、提升操作系统安全与可靠性来说变得尤为重要。
3.1 分层法
分层法是将操作系统分为若干层,最底层( 层 0 )为硬件,最高层( 层 N )为用户接口,每层只能调用紧邻它的低层的功能和服务(单向依赖)。
分层法的优点:① 便于系统的调试和验证,简化了系统的设计和实现。第一层可先调试而无须考虑系统的其他部分,因为它只使用了基本硬件。第一层调试完且验证成功之后,就可以调试第二层,如此向上。如果在调试某层时发现错误,那么错误应在这一层上,这是因为它的低层都调试好了。② 易扩充和易维护。在系统中增加、修改或替换一层中的模块或整层时,只要不改变相应层间的接口,就不会影响其他层。
分层法的问题:① 合理定义各层比较困难。因为依赖关系固定后,往往就显得不够灵活。② 效率较差。操作系统每执行一个功能,通常要自上而下地穿越多层,各层之间都有相应的层间通信机制,这无疑增加了额外的开销,导致系统效率降低。(简单来说就是 A 要和 D 通话,那么 A 首先需要和 B 通话,B 再和 C 进行通话,C 再和 D 进行通话;反过来,D 和 A 进行通话也是如此!)A 和 D 之间不可以直接进行通信!
3.2 模块化
模块化是将操作系统按功能划分为若干具有一定独立性的模块。每个模块具有某方面的管理功能,并规定好各模块间的接口,使各模块之间能够通过接口进行通信。还可以进一步将各模块细分为若干具有一定功能的子模块,同样也规定好各子模块之间的接口。这种设计方法被称为模块-接口法。
内核 = 主模块 + 可加载内核模块
在划分模块时,如果将模块划分得太小,虽然能降低模块本身的复杂性,但会使得模块之间的联系过多,造成系统比较混乱;如果模块划分的过大,又会增加模块内部的复杂性,显然应在两者间进行权衡。此外,在划分模块时,要充分考虑模块的独立性问题,因为模块独立性越高,各模块间的交互就越少,系统的结构也就越清晰。
衡量模块的独立性主要有两个标准:
内聚性:模块内部各部分间联系的紧密程度。内聚性越高,模块独立性越好。
耦合性:模块间相互联系和相互影响的程度。耦合性越低,模块独立性越好。
模块化的优点:① 提高了操作系统设计的正确性、可理解性和可维护性;② 增强了操作系统的可适应性;③ 加速了操作系统的开发过程。
模块化的缺点:① 模块间的接口规定很难满足对接口的实际需求。② 各模块设计者齐头并进,每个决定无法建立在上一个已验证的正确决定的基础上,因此无法找到一个可靠的决定顺序。
3.3 宏内核
从操作系统的内核架构来划分,可分为宏内核和微内核。
宏内核,也称为单内核或大内核,是指将系统的主要功能模块都作为一个紧密联系的整体运行在核心态,从而为用户程序提供高性能的系统服务。因为各管理模块之间共享信息,能有效利用相互之间的有效特性,所以具有无可比拟的性能优势。
随着体系结构和应用需求的不断发展,需要操作系统提供的服务越来越复杂,操作系统的设计规模急剧增长,操作系统也面临着 “软件危机” 困境。就像一个人,越胖活动起来越困难。所以就出现了微内核技术,就是将一些非核心的功能移到用户空间,这种设计带来的好处是方便扩展系统,所有新服务都可以在用户空间增加,内核基本不用去做改动。
从操作系统的发展来看,宏内核获得了绝对的胜利,目前主流的操作系统,如 Windows、Android、iOS、macOS、Linux 等,都是基于宏内核的构架。但也应注意到,微内核和宏内核一直是同步发展的,目前主流的操作系统早已不是当年纯粹的宏内核构架了,而是广泛吸取微内核构架的优点而后揉合而成的混合内核。当今宏内核构架遇到了越来越多的困难和挑战,而微内核的优势似乎越来越明显,尤其是谷歌的 Fuchsia 和华为的鸿蒙 OS , 都瞄准了微内核构架。
3.4 微内核
3.4.1 微内核的基本概念
微内核构架,是指将内核中最基本的功能保留在内核,而将那些不需要在核心态执行的功能移到用户态执行,从而降低内核的设计复杂性。那些移出内核的操作系统代码根据分层的原则被划分为若干服务程序,它们的执行相互独立,交互则都借助于微内核进行通信。
微内核结构将操作系统划分为两大部分:微内核和多个服务器。
微内核是指精心设计的、能实现操作系统最基本核心功能的小型内核,通常包含:① 与硬件处理紧密相关的部分;② 一些较基本的功能;③ 客户和服务器之间的通信。这些部分只是为构建通用操作系统提供一个重要基础,这样就可以确保将内核做的很小。操作系统中的绝大部分功能都放在微内核外的一组服务器(进程)中实现,如用于提供对进程(线程)进行管理的进程(线程)服务器、提供虚拟存储器管理功能的虚拟存储器服务器等,它们都是作为进程来实现的,运行在用户态,客户和服务器之间是借助微内核提供的消息传递机制来实现交互的。
在微内核结构中,为了实现高可靠性,只有微内核运行在内核态,其余模块都运行在用户态,一个模块中的错误只会使这个模块崩溃,而不会使整个系统崩溃。例如,文件服务代码运行时出了问题,宏内核因为文件服务是运行在内核态的,系统直接就崩溃了。而微内核的文件服务是运行在用户态的,只要把文件服务功能强行停止,然后重启,就可以继续使用,系统不会崩溃。
3.4.2 微内核的基本功能
微内核结构通常利用 “机制与策略分离” 的原理来构造 OS 结构,将机制部分以及与硬件紧密相关的部分放入微内核。微内核通常具有如下功能:
① 进程(线程)管理。进程(线程)之间的通信功能是微内核 OS 最基本的功能,此外还有进程的切换、进程的调度,以及多处理机之间的同步等功能,都应放入微内核中。举个例子:为实现进程调度功能,需要在进程管理中设置一个或多个进程优先级队列,这部分属于调度功能的机制部分,应将它放入微内核中。而对用户进程如何分类,以及优先级的确认方式,则属于策略问题,可将它们放入微内核外的进程管理服务器中。
② 低级存储器管理。在微内核中,只配置最基本的低级存储器管理机制,如用于实现将逻辑地址变换为物理地址等的页表机制和地址变换机制,这一部分是依赖于硬件的,因此放入微内核中。而实现虚拟存储器管理的策略,则包含应采取何种页面置换算法,采用何种内存分配与回收的策略,应将这部分放在微内核外的存储器管理服务器中。
③ 中断和陷入处理。微内核 OS 将与硬件紧密相关的一小部分放入微内核,此时微内核的主要功能是捕获所发生的中断和陷入事件,并进行中断响应处理,在识别中断或陷入事件后,再发送给相关的服务器来处理,故中断和陷入处理也应放入微内核。
微内核操作系统将进程管理、存储器管理以及 I/O 管理这些功能一分为二,属于机制的很小一部分放入微内核,而绝大部分放入微内核外的各种服务器实现,大多数服务器都要比微内核大。因此,在采用客户/服务器模式时,能把微内核做得很小。
3.4.3 微内核的特点
微内核结构的优点主要有:
① 扩展性和灵活性。许多功能从内核中分离出来,当要修改某些功能或增加新功能时,只需在相应的服务器中修改或新增功能,或再增加一个专用的服务器,而无须改动内核代码。
② 可靠性和安全性。
③ 可移植性。与 CPU 和 I/O 硬件有关的代码均放在内核中,而其他各种服务器均与硬件平台无关,因而将操作系统移植到另一个平台上所需做的修改是比较小的。
④ 分布式计算。客户和服务器之间、服务器和服务器之间的通信采用消息传递机制,这就使得微内核系统能很好地支持分布式系统和网络系统。
微内核结构的主要问题是性能问题,因为需要频繁地在核心态和用户态之间进行切换,操作系统的执行开销偏大。为了改善运行效率,可以将那些频繁使用的系统服务移回内核,从而保证系统性能,但这又会使微内核的容量明显地增大。
举个例子:
虽然宏内核在桌面操作系统中取得了绝对的胜利,但在微内核在实时、工业、航空及军事应用中特别流行,这些领域都是关键任务,需要有高度的可靠性。
3.4.4 外核
不同于虚拟机克隆真实机器,另一种策略是对机器进行分区,给每个用户整个资源的一个子集。这样,某个虚拟机可能得到磁盘的 0 至 1023 盘块,而另一个虚拟机会得到磁盘的 1024 至 2047 盘块,等等。在底层中,一种称为外核(exokernel)的程序在内核态运行。它的任务是为虚拟机分配资源,并检查使用这些资源的企图,以确保没有机器会使用他人的资源。每个用户层的虚拟机可以运行自己的操作系统,但限制只能使用已经申请并且获得分配的那部分资源。
外核机制的优点是减少了映射层。在其他的设计中,每个虚拟机都认为它有自己的磁盘,其盘块号从 0 到最大编号,这样虚拟机监控程序就必须维护一张表格以重映像磁盘地址(或其他资源),有了外核,这个重映射处理就不需要了。外核只需要记录已经分配给各个虚拟机的有关资源即可。这种方法还有一个优点,它将多道程序(在外核内)与用户操作系统代码(在用户空间内)加以分离,而且相应的负载并不重,因为外核所做的只是保持多个虚拟机彼此不发生冲突。
上图中 Exokernel 就是外核。内核负责进程调度、进程通信等功能,外核负责为用户进程分配未经抽象的硬件资源,且由外核负责保证资源使用安全。
4. 操作系统引导
操作系统引导是什么?
操作系统引导(boot)——简单来说就是在计算机开机的时候,怎么让操作系统运行起来。
操作系统(如 Windows、Linux 等)是一种程序,程序以数据的形式存放在硬盘中,而硬盘通常分很多区,一台计算机中又有多个或多种外部存储设备。操作系统引导是指计算机利用 CPU 运行特定程序,通过程序识别硬盘,识别硬盘分区,识别硬盘分区上的操作系统,最后通过程序启动操作系统,一环扣一环地完成上述过程。
磁盘是有哪些数据?
如果我们刚花钱买一个磁盘,那么刚开始的磁盘就跟我们的钱包是一样的,空空如也!
但是我们应该都具备向磁盘中装入操作系统的能力。
装完操作系统后的磁盘应该如上图所示:
操作系统应该是装在 C 盘的;
其实除了我们能够看到的 C 盘、D 盘、E 盘、F 盘 之外,在磁盘的开始部分还有一段主引导记录部分,英文简称 MBR,主要包含两部分:磁盘引导程序和分区表;
分区表实际上是一个数据结构,包含了电脑分为哪几个区,每个区的地址范围是什么。
C 盘(是这个磁盘的活动分区,安装了操作系统):并且会使用这个 C盘 来启动操作系统;
首先 C 盘内有一个引导记录 PBR(负责找到 “启动管理器”)
根目录:简单来说就是我们双击打开 C 盘以后看到的就叫做根目录;
接下来我们来看:
安装在 C 盘里面的操作系统究竟是如何一步一步的运行起来的?
常见操作系统的引导过程如下:
① 激活 CPU。激活的 CPU 读取 ROM 中的 boot 程序,将指令寄存器置为 BIOS(基本输入/输出系统)的第一条指令,即开始执行 BIOS 的指令。
② 硬件自检。启动 BIOS 程序后,先进行硬件自检,检查硬件是否出现故障。如有故障,主板会发出不同含义的蜂鸣,启动中止;如无故障,屏幕会显示 CPU、内存、硬盘等信息。
③ 加载带有操作系统的硬盘。硬件自检后,BIOS 开始读取 Boot Sequence(通过 CMOS 里保存的启动顺序,或者通过与用户交互的方式),把控制权交给启动顺序排在第一位的存储设备,然后 CPU 将该存储设备引导扇区的内容加载到内存中。
④ 加载主引导记录 MBR。硬盘以特定的标识符区分引导硬盘和非引导硬盘。如果发现一个存储设备不是可引导盘,就检查下一个存储设备。若无其他启动设备,就会死机。主引导记录 MBR 的作用是告诉 CPU 去硬盘的哪个主分区去找操作系统。
⑤ 扫描硬盘分区表,并加载硬盘活动分区。MBR 包含硬盘分区表,硬盘分区表以特定的标识符区分活动分区和非活动分区。主引导记录扫描硬盘分区表,进而识别含有操作系统的硬盘分区(活动分区)。找到硬盘活动分区后,开始加载硬盘活动分区,将控制权交给活动分区。
⑥ 加载分区引导记录 PBR。读取活动分区的第一个扇区,这个扇区称为分区引导记录(PBR),其作用是寻找并激活分区根目录下用于引导操作系统的程序(启动管理器)。
⑦ 加载启动管理器。分区引导记录搜索活动分区中的启动管理器,加载启动管理器。
⑧ 加载操作系统。
如果你的电脑是 Windows 系统,可以去自己的电脑上打开 C 盘,C 盘目录下有个文件名为 Windows 的文件,双击打开,找到文件名为 boot 文件,双击打开,这个文件中的内容就是操作系统初始化一系列程序。
也就是上图中我们在根目录下找到启动管理器的过程;
我们在开机的时候,启动 Windows 系统时,会出现一个转圈的现象,Windows 下面有个虚线的圈圈一直在转,实际上,这个过程就是在运行 boot 文件下程序的过程,也就是在初始化我们操作系统的过程;
5. 虚拟机
5.1 虚拟机的基本概念
在传统的计算机中,一台物理的机器上只能运行一个操作系统,操作系统运行在内核空间,在操作系统之上可以运行多个进程,如下图所示:
假设,我们同时开启王者和吃鸡,那么在传统的计算机中,王者和吃鸡的服务器必然要运行在一个操作系统下运行,这样可能会存在一定的危险,王者和吃鸡可能会出现争夺操作系统资源的问题。
一个解决方法是:将其中一个进程拿到另一台机器上运行,另一台机器有另一个单独的操作系统,但是这样又会造成物理资源的极大浪费,工业计算机的性能是很强的,本来我的计算机可以运行两个进程,但是为了不出现争夺资源的现象,现在要用另外一个计算机,这么会造成资源的极大浪费;
为此,引入了虚拟机的概念;
接下来,我们就来学习虚拟机:
虚拟机(Virtual Machine,VM)是一台逻辑计算机,是指利用特殊的虚拟化技术,通过隐藏特定计算平台的实际物理特性,为用户提供抽象的、统一的、模拟的计算环境。有两类虚拟化方法。使用虚拟化技术,将一台物理机器虚拟化为多台虚拟机器,每个虚拟机器都可以独立运行一个操作系统;
1. 第一类虚拟机管理程序
从技术上讲,第一类虚拟机管理程序就像一个操作系统,因为它是唯一一个运行在最高特权级的程序。它在裸机上运行并且具备多道程序功能。虚拟机管理程序向上层提供若干台虚拟机,这些虚拟机是裸机硬件的精确复制品。由于每台虚拟机都与裸机相同,所以在不同的虚拟机上可以运行任何不同的操作系统。第一类虚拟机管理程序如下图所示:
虚拟机作为用户态的一个进程运行,不允许执行敏感指令。然而,虚拟机上的操作系统认为自己运行在内核态(实际上不是),称为虚拟内核态。虚拟机中的用户进程认为自己运行在用户态(实际上确实是)。当虚拟机操作系统执行了一条 CPU 处于内核态才允许执行的指令时,会陷入虚拟机管理程序。在支持虚拟化的 CPU 上,虚拟机管理程序检查这条指令是由虚拟机中的操作系统执行的还是由用户程序执行的。如果是前者,虚拟机管理程序将安排这条指令功能的正确执行。否则,虚拟机管理程序将模拟真实硬件面对用户态执行敏感指令时的行为。
在过去不支持虚拟化的 CPU 上,真实硬件不会直接执行虚拟机中的敏感指令,这些敏感指令被转为对虚拟机管理程序的调用,由虚拟机管理程序模拟这些指令的功能。
2. 第二类虚拟机管理程序
第二类虚拟机管理程序如下图所示:
第二类虚拟机管理程序是一个依赖于 Windows、Linux 等操作系统分配和调度资源的程序,很像一个普通的进程。第二类虚拟机管理程序仍然伪装成具有 CPU 和各种设备的完整计算机。VMware Workstation 是首个 X86 平台上的第二类虚拟机管理程序。
宿主操作系统:宿主操作系统就是我们电脑运行的操作系统,比如 Windows 、Linux、MacOS 等;
第二类虚拟管理程序:第二类虚拟管理程序就是虚拟机,比如国内比较流行的 VirtualBox 、VMware ;
客户操作系统:客户操作系统就是我们想要我们想要运行的操作系统,也就是在虚拟机中下载的操作系统,可以是 Linux、Windows ;这样就可以在我们的电脑上同时启动两个操作系统;
运行在第二类虚拟机管理程序上的操作系统都称为客户操作系统。对于第二类虚拟机管理程序,运行在底层硬件上的操作系统称为宿主操作系统。
首次启动时,第二类虚拟机管理程序就像一台刚启动的计算机那样运行,期望找到的驱动器可以是虚拟设备。然后将操作系统安装到虚拟磁盘上(其实只是宿主操作系统中的一个文件)。客户操作系统安装完成以后,就能启动并运行。
虚拟化在 Web 主机领域很流行。没有虚拟化,服务商只能提供共享托管(不能控制服务器的软件)和独占托管(成本较高)。当服务商提供租用虚拟机时,一台物理服务器就可以运行多个虚拟机,每个虚拟机看起来都是一台完整的服务器,客户可以在虚拟机上安装自己想用的操作系统和软件,但是只需支付较低的费用。
6. 疑难点
1. 并行性和并发性的区别和联系
并行性和并发性是既相似又有区别的两个概念。并行性是指两个或多个事件在同一时刻发生,并发性是指两个或多个事件在同一时间间隔内发生。
在多道程序环境下,并发性是指在一段时间内,宏观上有多个程序同时运行,但在单处理器系统中每个时刻却仅能有一道程序执行,因此微观上这些程序只能分时的交替执行。若在计算机系统中有多个处理器,则这些可以并发执行的程序便被分配到多个处理器上,实现并行执行,即利用每个处理器来处理一个可并发执行的程序。
2. 特权指令和非特权指令
所谓特权指令,是指有特殊权限的指令,由于这类指令的权限最大,使用不当将导致整个系统崩溃、如清内存、置时钟、分配系统资源、修改虚存的段表或页表、修改用户的访问权限等。若所有程序都能使用这些指令,则系统一天死机 n 次就不足为奇。为保证系统安全,这类指令只能用于操作系统或其他系统软件,不直接提供给用户使用。因此,特权指令必须在核心态执行。实际上,CPU 在核心态下可以执行指令系统的全集。形象地说,特权指令是那些少儿不宜的东西,而非特权指令是老少皆宜的东西。
为了防止用户程序中使用特权指令,用户态下只能使用非特权指令,核心态下可以使用全部指令。在用户态下使用特权指令时,将产生中断以阻止用户使用特权指令。所以把用户程序放在用户态下执行,而操作系统中必须使用特权指令的那部分程序在核心态下运行,保证了计算机系统的安全可靠。从用户态转换为核心态的唯一途经是中断或异常。
3. 访管指令和访管中断
访管指令是一条可以在用户态下执行的指令。在用户程序中,因要求操作系统提供服务而有意识地使用访管指令,从而产生一个中断事件(自愿中断),将操作系统转换为核心态,称为访管中断。访管中断由访管指令产生,程序员使用访管指令向操作系统请求服务。
为什么要在程序中引入访管指令呢?这是因为用户程序只能在用户态下运行。若用户程序想要完成在用户态下无法完成的工作,要靠访管指令。访管指令本身不是特权指令,其基本功能是让程序拥有 “自愿进管” 的手段,从而引起访管中断。
处于用户态的用户程序使用访管指令时,系统根据访管指令的操作数执行访管中断处理程序,访管中断处理程序将按系统调用的操作数和参数转到相应的例行子程序。完成服务功能后,退出中断,返回到用户程序断点继续执行。
4. 定义微内核结构 OS 的四个方面
1. 足够小的内核。
2. 基于客户/服务器模式。
3. 应用 “机制和策略分离” 原理。机制是指实现某一功能的具体执行机构。策略则是在机制的基础上借助于某些参数和算法来实现该功能的优化,或达到不同的功能目标。在传统的 OS 中,将机制放在 OS 内核的较低层中,把策略放在内核的较高层中。而在微内核 OS 中,通常将机制放在 OS 的微内核中。正因如此,才可以将内核做得很小。
4. 采用面向对象技术。基于面向对象技术中的 “抽象” 和 “隐蔽” 原则能控制系统的复杂性,进一步利用 “对象” “封装” 和 “继承” 等概念还能确保操作系统的正确性、可靠性、易扩展性等。正因如此,面向对象技术被广泛应用于现代操作系统的设计之中。