首先来一张图来看看计算机系统的层次结构:
可以看到的是,操作系统扮演这一个连接硬件和软件、用户的角色。
由此可以得出操作系统的定义:
操作系统(Operating System, OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境,它是计算机系统中最基本的系统软件。
这张图可以很直观的展示操作系统所干的事情。
首先结合上面操作系统的层次结构图,思考操作系统在以下三个方面的功能实现:
这三个问题对应的层次如何所示:
补充知识
- 进程:表示一个程序的执行过程。执行前需要将该程序放到内存中,才能被CPU处理
首先解决第一个问题:操作系统作为资源的管理者,需要提供/实现哪些功能。
我们拿QQ进行视频聊天的工作过程来讲解:
使用QQ的第一步,是在各个文件夹中找到QQ安装的位置,操作系统将逐层打开文件夹,这一步涉及文件管理;第二步,就是运行QQ.exe,在这一步,操作系统会把该程序的相关数据放入到内存中,并决定放在内存中的位置,这一步涉及存储器管理(内存管理);第三步就是将QQ程序放入等待队列中,之后对应的进程将被放进处理机(CPU)中处理,这一步涉及处理机管理;最后一步,当我们需要打开摄像头跟朋友聊天的时候,操作系统会将摄像头设备分配给该进程,在摄像头使用完成后还要进行资源回收,这一步涉及设备管理。对于整个流程,操作系统必须保证这些行为都是安全高效的
其次是第二个问题:操作系统作为用户与计算机硬件之间的接口,要为其上层的用户、应用程序提供简单易用的服务,需要实现什么功能。
想要解决这一个问题,操作系统需要提供以下三个功能:
命令接口和程序接口可以统称为用户接口,在考研当中,这两种功能经常考察
以下是图示:
命令接口是允许用户直接使用的,其分为联机命令接口和脱机命令接口。
其中,联机命令接口的特点是:用户说一句,系统做一句。而脱机命令接口的特点是:用户说一堆,系统做一堆。
下面拿两个例子来解释联机命令接口和脱机命令接口:
例1:在Windows操作系统中,我们可以打开cmd窗口,输入time指令,窗口会返回当前系统时间,并且将操作权限返还给用户,用户随后可以设置一个新的时间。这就是一个典型的联机命令接口,或者叫交互式命令接口。
例2:还是以Windows为例,使用Windows的搜索功能,在C盘中搜索并随便打开一个*.bat文件,可以看到里面编写着一系列的指令,文件本身就相当于一个指令清单,双击该文件,操作系统就会根据用户给出的这些一系列的指令,一条一条往下执行。这种就是典型的脱机命令接口实例,脱机命令接口也可以叫批处理命令接口。
聊完了命令接口,接下来我们聊聊程序接口。
再拿Windows为例,我们在操作系统中能经常看见*.dll文件,例如C:\Windows\System32目录下的user32.dll,允许程序员在程序中调用该文件,实现创建窗口等功能。该功能不是由程序员实现的,而是通过程序员编写的程序进行调用,实现间接使用。详细的调用过程就是调用系统调用的过程(关于系统调用的相关概念将会在后面学习到)。
程序接口就是由一组系统调用组成的,大部分情况可以认为程序接口=系统调用。
注意,系统调用也可以称为广义指令、系统调用命令
图形用户界面这里不多赘述,其目标就是为了用户能够更加方便地操作计算机。
最后我们聊聊第三个问题:操作系统作为最接近硬件的层次,需要在纯硬件的基础上实现什么功能。
在这一层面上看,操作系统需要实现的最主要功能就是实现对硬件及其的拓展。在没有任何软件支持的计算机(裸机)上安装的操作系统,要能够提供资源管理功能和方便用户的服务功能,将裸机改造成功能更强、使用更方便的机器。
如果把计算机比喻成锤子、钉子、木头,那么操作系统就应该是优秀的工匠,操作系统将这些简单的原料组织成房子、帆船、匹诺曹等等,普通用户就可以直接使用工匠提供的房子、帆船、匹诺曹,而无需关心这些东西在底层是怎么组织起来的。
下面对知识进行总结:
其中需要以后重点掌握的是关于资源管理的四个小方面,以及系统调用的相关知识。
操作系统主要由四个特征:并发、共享、虚拟和异步。其中并发和共享是操作系统两个最基本的特征,二者也互为存在条件。
并发是指两个或多个时间在同一时间间隔内发生,这些事件宏观上是同时发生的,但微观上是交替发生的。
注意把并发跟并行区分,后者指两个或多个事件在同一时刻同时发生
通常,一个单核处理机(CPU)同一时刻只能执行一个程序,操作系统在这里的职责就是负责协调多个程序交替执行。事实上,操作系统就是伴随着“多道程序技术”而出现的,可以说,操作系统和程序并发是一起诞生的。当然,现在的CPU一般都是多核CPU。
共享即资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。
共享有两种方式:互斥共享和同时共享。
其实,同时共享中的”同时“,往往只能表示宏观层面,微观层面上这些进程可能是交替地进行对资源的访问(分时共享)
下面拿两个案例来理解共享的两种方式:
例1:使用QQ和微信进行视频聊天,同一时间段内摄像头只能分配给其中一个进程,这就是互斥共享;
例2:使用QQ发送文件A,同时使用微信发送文件B。宏观上看,两边都在同时读取并发送文件,说明两个进程都在访问硬盘资源,从中读取数据。微观上看,两个进程是交替着访问硬盘的。这就是同时共享。
并发性指计算机系统中同时存在着多个运行着的程序。共享性是指系统中的资源可供内存中多个并发执行的进程共同使用。
通过下面这个例子来看并发与共享的关系:
使用QQ发送文件A,同时使用微信发送文件B。
1.两个进程正在并发执行(并发性)
2.需要共享地访问硬盘资源(共享性)
如果失去并发性,则系统中只有一个程序正在运行,则共享性失去存在的意义;如果失去共享性,则QQ和微信不能同时访问硬盘资源,就无法实现同时发送文件,也就无法并发。
虚拟是指把一个物理上的实体变为若干个逻辑上的对应物,前者(物理实体)是实际存在的,后者(逻辑对应物)是用户感受到的。
下面用一个例子来理解虚拟:
通过之前的学习我们知道,一个程序需要放入内存并给他分配CPU才能执行。假如说GTA5需要4GB的运行内存,QQ需要256MB的运行内存,网易云也需要256MB的运行内存,而我的电脑只有4GB的内存,但是却可以同时运行以上程序。问题来了:以上程序同时运行所需内存已经大于4GB了,为什么它们还可以同时运行在电脑上呢?原因就是操作系统采用了虚拟存储器技术。
虚拟存储器技术其实就是虚拟技术中的”空分复用技术“,对于这个概念,这里只需了解,会在后续学习过程进行学习。
再来一个例子:
在一台单核CPU中,用户可以打开QQ、Chrome、QQ音乐等程序。一个程序需要被分配CPU才能运行,而单核CPU却能在电脑中同时运行多个程序,背后其实就是运用了虚拟处理器技术。
虚拟处理器技术就是虚拟技术中典型的”时分复用技术“,在微观层面上处理机会在各个微小的时间段内交替着为各个进程服务。
当然,虚拟往往也伴随着并发。
异步是指,在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。
这里拿一个老渣与两个女孩约会的例子来解释异步:
加入两个女孩都给老渣下达了两道命令,同时要求老渣陪其吃饭和把心给她,而老渣的心和老渣的人都只有一个,假如一开始跟一号吃饭,之后一号和二号同时要求老渣把心给她,那么老渣将有两种选择,所以会有不同的约会过程。
老渣与与一号、二号的约会相当于对两个进程的处理,每个进程都有各自需要执行的指令。老渣的心相当于有限的系统资源。由于可分配的资源有限,进程的执行不是一贯到底的,而是走走停停的,以不可预知的速度向前推进。
显然,如果失去了并发性,那么系统只能串行的处理每个进程,每个进程的执行会一贯到底,所以,只有系统拥有并发性,才可能导致异步性。
下面对知识进行总结:
重要考点:
计算机刚被发明的时代的操作方式,那时并没有操作系统,程序员编写程序需要通过打孔机对纸带进行打孔,通过打孔与否区别二进制的1和0。机器读取纸带中的信息,并将其输入到计算机当中,计算机进行运算过后,CPU会将内存中的结果,操控机器对纸带打孔,进行结果输出。
主要缺点:用户独占主机、人机速度矛盾导致资源利用率极低。
为了解决手工操作阶段暴露出的问题,人们引入了脱机输入/输出技术(用磁带完成),并使用**监督程序(操作系统雏形)**负责控制作业的输入、输出。
程序员会事先将程序编写到纸带上,然后通过专门的外围控制机,把纸带机上的纸带的数据读到一个速度更快的磁带上,之后计算机直接从磁带上读取程序并处理,处理的结果将重新输送到磁带上,再通过外围控制机将结果输出到纸带上。
主要优点:缓解了一定程度的人机速度矛盾,资源利用率有所提升。
主要缺点:内存中仅能有一道程序运行,只有该程序运行结束之后才能调入下一-道程序。CPU有大量的时间是在空闲等待I/0完成。资源利用率依然很低。
为了解决单道批处理系统所暴露的问题,人们发明了多道批处理系统。
用户还是利用磁带将程序输入到计算机中,但是每次的传输将往内存传入多道程序,这些程序将在计算机中并发地执行。这个时候,操作系统正式诞生,并且引入了中断技术,由操作系统负责管理这些程序的运行。
主要优点:多道程序并发执行,共享计算机资源。资源利用率大幅提升,CPU和其他资源保持“忙碌”状态,系统吞吐量增大。
主要缺点:用户响应时间长,没有人机交互功能,用户提交自己的作业之后就只能等待计算机处理完成,中间不能控制自己的作业执行。
可以看到,并发和共享两大特性自操作系统诞生时就已存在
拿个例子来说明多道批处理系统相对于单道批处理系统,资源利用率为什么会大幅度提升。
假设计算机需要处理三个作业:
作业一:输入1秒,计算1秒,输出1秒
作业二:输入1秒,计算1秒,输出1秒
作业三:输入1秒,计算1秒,输出1秒
若采用单道批处理技术:
采用多道批处理技术:
上诉两种比较很好的说明了单道批处理和多道批处理的区别,同时也要记住,操作系统的出现是在多道批处理阶段
为了提供人机交互能力,人们发明了分时操作系统。计算机以时间片为单位轮流为各个用户/作业服务,各个用户可通过终端与计算机进行交互。
比如时间片为50ms,那么计算机为一个用户服务50ms之后就会处理为下一个用户服务。在这50ms当中,用户都可以通过终端跟计算机进行交互。
主要优点:用户请求可以在对应的时间片内被即时响应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在。
主要缺点:不能优先处理一些紧急任务。操作系统对各个用户/作业都是完全公平的,循环地为每个用户/作业服务一个时间片,不区分任务的紧急性。
由于分时操作系统无法即使处理紧急任务的局限性,导致它无法被用于一些特别的场景,比如武器控制系统。所以人们发明了实时操作系统。在实时操作系统的控制下,计算机系统接收到外部信号后及时进行处理,并且要在严格的时限内处理完事件。该系统的特点时及时性和可靠性。
实时操作系统主要分为硬实时系统和软实时系统。
主要优点:能够优先响应一些紧急任务,某些紧急任务不需要时间片排队。
伴随着计算机网络的发展而诞生的,能把网络中各个计算机有机地结合起来,实现数据传送等功能,实现网络中各种资源的共享(如文件共享)和各台计算机之间的通信。(如Windows NT就是一种典型的网络操作系统,网站服务器就可以使用)
主要特点时分布性和并行性。系统中的和泰计算机地位相同,任何工作都可以分布在这些计算机上,由他们并行、协同完成这个任务。
如Windows XP、MacOS,方便个人使用
绿框部分是考研重点内容,整体重点理解各阶段的优点和缺点,各阶段的主要优点其实都是解决了上一阶段的主要缺点。
在将指令的类别之前,我们先来认识什么叫指令:
简单点来说,指令就是处理器(CPU)能识别、执行的最基本命令。
一条高级语言的代码翻译过来可能会对应多条指令:
有的指令”人畜无害“,比如加减乘除这些普通的指令;有的指令拥有很高的权限,比如内存清零指令。如果操作系统允许任意的用户程序都可以无差别地使用系统指令,那么就意味着一个用户可以将其他用户地内存数据随意清零,这样做显然是不符合安全规范地。
为了解决上述问题,我们需要将指令划分为两种类别,并对权限加以区分:
上面我们说到指令分为两种,随之而来的有一个新问题,CPU如何判断当前是否可以执行特权指令?
为此,我们将处理器状态划分为两种:
在系统中使用程序状态寄存器(PSW)中的某标志位来表示当前处理器处于什么状态。
对于程序而言,有些程序可以同时使用非特权指令和特权指令,而有的程序只能只用非特权指令。根据程序所能使用指令级别的不同,我们把程序分为两种:
在我们安装完计算机的时候,可以发现操作系统给我们提供了多种多样的功能,比如“记事本”、”任务管理器“等等。然而,有些功能看起来并不是必不可少的,就像没有“任务管理器”,我们仍然可以使用计算机。可见,计算机内部的功能结构,也由核心与非核心之称。
再来看之前的操作系统层次结构,这次我们把它再细分:
操作系统的功能分为内核功能与非内核功能。其中内核是我们比较关注的,它是计算机上配置的底层软件,是操作系统最基本、最核心的部分。
实现操作系统内核功能的那些程序就是内核程序
内核主要分为两部分,一部分是对系统资源进行管理的功能,主要包括进程管理、存储器管理、设备管理等功能;另一部分主要包括时钟管理(实现计时功能)、中断处理、原语(一种特殊程序,是最接近硬件的部分,这种程序的运行具有原子性,涵括设备驱动、CPU切换等)。
原子性是指一但操作就必须执行完成,不可中断,否则回到执行之前的状态。
上面我们说到操作系统有内核与非内核之分。
需要注意的是:有些操作系统并没有把对系统资源进行管理的功能归为“内核功能”,也就是说,不同的操作系统对内核的划分并不严格一致。通常可以把内核包含了上述功能体系结构的称为大内核,内核没有把上述功能划分在内的体系结构称为微内核。
操作系统的体系结构问题与企业的管理问题很相似:
内核就是企业的管理层,负责一些重要的工作。只有管理层才能执行特权指令,普通员工只能执行非特权指令。用户态、核心态之间的切换相当于普通员工和管理层之间的工作交接;大内核就相当于企业初创时体量不大,管理层的人会负责大部分的事情。优点是效率高;缺点是组织结构混乱,难以维护。微内核就相当于随着企业体量越来越大,管理层只负责最核心的一-些工作。优点是组织结构清晰,方便维护;缺点是效率低。
需要注意的是,操作系统体系结构之间的差别可能做作为选择题进行考察。
早期的计算机是采用串行机制处理程序的,一个程序进入计算机运行结束之后,只有等待I/O程序将结果输出,才能读取运行下一个程序:
这种方式的缺点显而易见:各程序只能穿行执行、资源利用率极低。
为了解决上述问题,人们发明了操作系统(作为计算机的管理者),同时引入了中断机制,实现了多道程序并发执行(多道批处理阶段)。
中断的本质:发生中断就意味着需要操作系统介入,开展管理工作。
中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
下面说说中断机制运行的例子:
假如计算机中有三个进程,进程一运行过程中,CPU可能受到计时部件发出的中断信号(例如过了一个时间片),此时就意味着需要操作系统的介入,因此CPU的状态将切换到核心态,对中断进行处理;此时CPU的权限会移交给操作系统,操作系统的内核负责对中断信号进行处理。此时操作系统发现刚才的中断是表明进程一的时间片已用完,所以切换到进程2执行;之后操作系统会将CPU的使用权交还给用户进程,之后进程二就会在用户态下开始执行。
假如进程二发出系统调用(内中断信号),请求输出数据,此时CPU的状态将切换到核心态,同时移交权限给操作系统,操作系统内核再次负责对中断信号的处理,并要求打印机要是工作,此时进程二暂停运行等待I/O完成,换进程三运行,此时CPU状态返回用户态。等到I/O完成,设备向CPU发出中断信号,CPU接收到I/O设备发来的而中断信号,切换到核心态对中断进程处理。操作系统内核再次对中断信号进程处理,此时因为进程2的I/O已经完成,所以操作系统会让进程二恢复运行,以完成后续工作。
从上面的例子我们不难发现中断有三个特点:
发生了中断,就意味着需要操作系统介入,开展管理工作。由于操作系统的管理工作(比如进程切换、分配I/O设备等)需要使用特权指令,因此CPU要从用户态转为核心态。中断可以使CPU从用户态切换为核心态,使操作系统获得计算机的控制权。有了中断,才能实现多道程序并发执行。
需要注意的是,中断是CPU从用户态切换到核心态的唯一途径,核心态切换用户态只需要通过执行一个特权指令,将PSW的标志位设置为表示“用户态”的标志位
中断主要分为内中断和外中断,内中断也称为异常、例外、陷入,外中断可以简称为中断(狭义上的中断就是指外中断)。
这两种中断的区分主要根据信号的来源是CPU的内部还是外部,内中断与当前执行的指令有关,外中断与当前执行的指令无关。
内外中断还有下面的细分:
指令中断如:系统调用时使用的访管指令。硬件故障如:缺页。软件中断如:整数除0。
外设请求如:I/O操作完成发出的中断信号。人工干预如:用户强行终止有个进程。
当然,有些书上也把中断做如下的细分:
但其实上面两种分类都是一样的,陷入值得就是有意为之的异常,比如系统调用;故障就是指由错误条件引起的,可能被故障处理程序修复,如缺页;终止就是无可恢复的致命错误造成的结果,终止处理程序不再将控制返回给引发终止的应用程序,如整数除0。
下面拿一个案例来讲解外中断的处理过程:
假如CPU正在执行某一个程序,这个程序有n条指令。CPU会按照顺序依次执行这些指令。并且它会遵循下面的步骤:
1、在执行完每个指令之后,CPU都要检查当前是否有外部中断信号
2、如果没有检测到中断信号,则继续执行下一条指令;如果检测到外部中断信号,则需要保护被中断进程的CPU环境(如程序状态字PSW、程序计数器PC、各种通用寄存器)
3、根据中断信号类型转入相应的中断处理程序
4、恢复原进程的CPU环境并退出中断,返回原进程继续往下执行
其中,中断的概念和作用、中断的分类是考研的考点
之前在介绍操作系统的概念时说到过操作系统在三个层次上应该实现的功能和目标,其中提到过在向用户提供一些简单易用的服务时,主要实现包括命令接口和程序接口,而程序接口就是由一组系统调用组成的。
系统调用是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,应用程序可以发出系统调用请求来获得操作系统的服务。
系统调用所解决的问题就是禁止多个进程随机调用计算机资源,转而由进程本身运行时只能通过系统调用的方式向操作系统发出请求,最后再由操作系统对哥哥请求进行协调管理。
如果要来个官方一点的解释,那么应该这么说:应用程序通过系统调用请求操作系统的服务。系统中的各种共享资源都由操作系统统一掌管,因此在用户程序中,凡是与资源有关的操作( 如存储分配、I/0操作、文件管理等),都必须通过系统调用的方式向操作系统提出服务请求,由操作系统代为完成。这样可以保证系统的稳定性和安全性,防止用户进行非法操作。
下面是系统调用的具体分类:
主要注意到的是:系统调用一般涉及对系统资源的管理、对进程的控制,而这些功能一般都是需要执行一些特权指令才能完成的,因此系统调用的相关处理需要在核心态下进行。
上面说过系统调用可以理解为是一种可供应用程序调用的特殊函数,但是它并不等同于我们开发过程中使用到的库函数。
实际上,编写程序时可以通过汇编语言直接调用系统调用,也可以通过高级变成语言来实现相同的结果i,而平常我们所接触到的库函数,像C库这种其实也是在内部实现对系统调用的请求:
当然,不是所有的库函数都会使用到系统调用,比如“取绝对值”;判断库函数是否使用系统调用,可以通过是否涉及对计算机共享资源的操作进行简单判断
对于系统调用的过程,可以看下面这张图进行简单的理解:
这里的int指令的参数x指明了系统调用号(操作系统根据这个来进行系统调用),此处的int不是整形的意思,而是interrupt(中断)的缩写
当执行了陷入指令之后(用户态,进行系统调用请求,引发内中断),CPU的控制权就被转交给操作系统(核心态),操作系统通过相应的系统调用对程序传入的参数进行处理,系统调用完成后又会返回之前的用户程序,继续执行下一条指令。可以概括成下面的过程:
传递系统调用参数->执行陷入指令(用户态)->执行系统调用相应服务程序(核心态)->返回用户程序
需要注意的是:陷入指令是唯一一个只能在用户态执行,而不可在核心态执行的指令。