__操作系统(Operating System,OS):__是指控制和管理整个计算机系统的__硬件和软件__资源,并合理的组织调度计算机的工作和资源的分配;以__提供给用户和其它软件方便的接口和环境;它是计算机系统中最基本的__系统软件。
1.2.1、系统资源的管理者:
操作系统要提供一些功能,如下:
1.2.2、向上提供方便易用的服务:
? 封装思想:操作系统把一些丑陋的硬件功能封装成简单易用的服务,使用户能更方便的使用计算机,用户无 需关心底层硬件的原理,只需要对操作系统发号施令即可。
那具体操作系统向上提供那些易用的服务呢?如下:
GUI:图形化用户接口(Graphical User Interface)用户可以使用形象的图形界面进行操作,而不需要记忆复杂的命令、参数。
命令行的方式:
__程序接口:__可以在程序中进行__系统调用__来使用程序接口。普通用户不能直接使用程序接口,只能通过程序代码__间接__使用。
如:C语言使用printf函数时使用了操作系统提供的一些接口。
在有些教材中,系统调用=广义指令
。
1.2.3、作为最接近硬件的层次
没有任何软件支持的计算机称为裸机。在裸机上安装的操作系统,可以提供资源管理功能和方便用户的服务功能,将裸机改造成功能更强,使用更方便的机器。
通常把覆盖了软件的机器称为__扩充机器__,又称__虚拟机。__
操作系统对硬件的扩展:将CPU、内存、磁盘、显示器、键盘等硬件合理的组织起来,当各种硬件能够相互协调配合,实现更多更复杂的功能。
并发:指两个或多个事件在同一时间间隔内发生。这些事件__宏观上时同时发生的,但在__微观上是交替发生的。
易混淆————__并行:__指两个或多个事件在同一时刻同时发生。
__操作系统的并发性:__指计算机系统中“同时”运行着多个程序,这些程序宏观上看是同时运行的,而微观上看是交替运行的。
操作系统就是伴随着"多道程序技术"而出现的。因此,操作系统和程序并发是一起诞生得的。
【注意】(重要考点):
单核CPU__同一时刻只能执行__一个程序,各个程序只能__并发__的执行。
多核CPU__同一时刻可以同时执行__多个程序,多个程序可以__并行__地执行。
4核CPU,意味着可以__并行地执行4个程序。__
即使是对于4核CPU来说,只要有4个以上的程序需要“同时”运行,那么并发性依然是必不可少的,因此__并发性是操作系统一个最基本的特性。__
__共享__即资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。
共享分为两种:
所谓的“同时”往往是宏观上的,而在微观上,这些进程可能是交替地对该资源进行访问(即分时共享)。
生活实例:
互斥共享:使用微信和QQ视频,同一时间段摄像头只能分配给其中一个进程。
同时共享:使用QQ发送文件A,同时使用微信发送文件B。宏观上来看,两边都在同时读取并发送文件,说明两个进程都在访问硬盘资源,从中读取数据。微观上来看,两个进程是交替着访问硬盘的。
__并发性__指计算机系统中同时存在着多个运行的程序。
__共享性__是指系统中的资源可供内存中多个并发执行的进程共同使用。
通过下列例子来看并发和共享的关系:
使用QQ发送文件A,同时使用微信发送文件B。
1、两个进程正在并发执行(并发性)
2、需要共享的访问硬盘资源(共享性)
如果失去并发性,则系统中只有一个程序正在运行,则共享性失去存在的意义。
同样的,如果失去共享性,则QQ和微信不能同时访问硬盘资源,就无法实现同时发送文件,则并发性失去存在的意义。
结论:并发性和共享性是互为存在的。
__虚拟__是指把一个物理上的实体变为若干个逻辑上的对应物。物理实体(前者)是实际存在的,而逻辑上对应物(后者)使用户感受到的。
虚拟技术分为两种:
虚拟内存:
__背景知识:__一个程序需要放入内存并给它分配CPU才能执行。
运行A程序需要4GB的内存,B程序需要1GB内存,C程序需要1GB内存…,我的电脑只有4GB内存是,为什么还能同时运行A、B、C三个程序呢?
答:这是__虚拟存储器技术__(空分复用技术)。实际上只有4GB的内存,在用户看来似乎远远大于4GB。
__虚拟CPU:__某单核CPU的计算机中,用户打开QQ、微信、WPS等等软件。
问题:既然一个程序需要被分配CPU才能正常运行,那为什么单核CPU的电脑中能同时运行这么多个程序呢?
答:这是利用__虚拟处理器__(时分复用技术)。实际上只有一个单核CPU,但在用户看来似乎有6个CPU在同时为自己服务。
__时分复用技术:__微观上处理机在各个微小的时间段内交替着为各个进程服务。
那时分复用技术和并发有什么样的关系呢?
__异步__是指,在多道程序环境下,允许多个程序并发执行,但由于资源有限,进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。
由于并发性的程序会争抢着使用系统资源,而系统中的资源有限,因此进程的执行不是一贯到底的,而是走走停停的,已不可预知的速度前进。
但如果失去了并发性,那系统只能串行的运行各个程序,那么每个程序的执行会一贯到底。
所以总结:只有系统用用并发性,才有可能导致异步性。
【重要考点】:
此阶段操作系统并没有诞生。程序员写的程序需要写在纸带上面,纸带上面有孔
代表二进制的1,没孔
代表二进制的0。
工作过程:
我们用数轴来反映这个手工操作阶段写程序的效率:
可以看到将纸带安装或取出纸带机时,时间超慢,但是此时计算机运行的速度很快。所以这就导致了一大步时间是在左无用功。并且此时及算你的造价很贵,所以资源利用率低。
引入__脱机输入/输出技术__(用外危机+磁带完成),并由__监督程序__负责控制作业的输入、输出。、
如下图:通过外围机将多个纸带的数据提前存储到磁带上面。
计算机通过__监督程序__(这个监督程序就是操作系统的雏形)将磁带里面的数据进行输入/输出。这个速度很快。
我们用数轴来反映这个单道批处理阶段写程序的效率:
单道批处理的主要__优点__:缓解了一定程序的人机速度矛盾,资源利用率有所提高。
单道批处理的主要__缺点__:内存中仅能有一道程序运行,只有该程序运行结束之后才能调入下一道程序。__CPU有大量的时间是在空闲等待I/O完成。__资源利用率依然很低。
上面单道批处理系统,内存中一次仅能运行一道程序。而多道批处理,就每次往内存中读入多道程序。
此阶段操作系统正式诞生,用于支持多道程序并发运行。
__主要优点:__多道程序并发执行,共享计算机资源,资源利用率大幅提升,CPU和其它资源更能保持“忙碌”状态,系统吞吐量增大。
__主要缺点:__用户响应时间长,没有人机交互功能(用户提交的作业之后就只能等待计算机处理完成,中间不能控制子集的作业执行。eg:无法调试程序/无法在程序运行过程中输入一些参数)。
__分时操作系统:计算机以__时间片__为单位__轮流为各个用户/作业服务,各个用户可通过终端(键盘,鼠标等等)与计算机进行交互。
__主要优点:__用户请求可以被即时相应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在。
__主要缺点:__不能优先处理一些紧急任务。操作系统多各个用户/作业,都是完全公平的,循环的为每个用户/作业服务一个时间片,不区分任务的紧急性。
实时操作系统的优点:能够优先响应一些紧急任务,某些紧急任务不需时间片排队。
在实时操作系统的控制下,计算机系统接收道外部信号后即时进行处理,并且要求在严格的时限内处理完事件。
实时操作系统的主要特点:及时性和可靠性。
而实时操作系统又分为两类:
__网络操作系统:__是伴随着计算机网络的发展而诞生的,能把网络中各个计算机有机的结合起来,实现数据传送等功能,实现网络中各种资源的共享(如文件共享)和各台计算机之间的通信。(如:windows NT就是一种典型的网络操作系统,网站服务器就可以使用)。
__分布式操作系统:主要特点是__分布性和并行性。系统中各台计算机地位相同,任何工作都可以分布在这些计算机上,由它们并行、协同完成这个任务。
__个人计算机操作系统:__如windows XP,MacOS,方便个人使用。
学习目标:
__指令:__就是处理器(CPU)能识别、执行的最基本命令。
【注】不要把“指令”和Linux或者是windows或者是MacOS中的“交互式命令”相混淆。
本节中的“指令”指二进制机器指令。
__应用程序:__就是普通程序员写的程序就是“应用程序”,或者说就是我们平常使用的程序,如:QQ,微信等等。
__内核程序:__微软,苹果有一帮人负责实现操作系统,它们写的是“内核程序”。有很多内核程序组成了“操作系统内核”,简称为“内核”(Kernel)。
内核__是操作系统最重要最核心的部分,也是__最接近硬件的部分。
操作系统对资源的管理工作就是在内核部分实现的。
甚至可以说,一个操作系统只要有内核就够了,如Docker—>仅需Linux内核。
但是操作系统的功能未必都在内核中,如图形化用户界面GUI。
上面学习了应用程序和内核程序。下面我们来看看特权指令和非特权指令。
内核作为操作系统的“管理者”,有时会让CPU执行一些“特权指令”,如:内存清零指令。这些指令影响重大,只允许“管理者”————即操作系统内核来使用。
而应用程序只能使用“非特权指令”,如:加法指令,减法指令等。
当然了CPU设计和生产的时候就划分了特权指令和非特权指令,因此CPU执行一条指令前就能判断出其类型。
虽说CPU可以判断出指令类型。但是CPU怎么区分此时正在运行的是内核程序还是应用程序呢?
如下方法来区分:
CPU有两种状态:
当CPU处于__内核态__时,说明此时正在运行的是内核程序,此时可以执行特权指令。
当CPU处于__用户态__时,说明此时正在运行的是应用程序,此时只能执行非特权指令。
那又何如直到当前CPU在内核态还是用户态呢?
扩展:CPU中有一个寄存器叫__程序状态字寄存器(PSW)__,其中有一个二进制位,1表示“内核态”,0表示“用户态”。
一个故事:
所以说内核态和用户态的切换,如下:
除了非法使用特权指令之外,还有很多事件会触发中断信号。一个共性是,但凡需要操作系统介入的地方,都会触发中断信号。
学习目标:
__中断的作用:__会使CPU由用户态变为内核态,使操作系统重新夺回对CPU的控制权。
__”中断“__是让操作系统内核夺回CPU使用权的唯一途径。
中断和并发的关系:如果没有”中断“机制,那么一旦应用程序上CPU运行,CPU就会一直运行这个应用程序。
那这样一来,那就不需要并发了。所以没有中断就不存在并发,换句话说没有中断就没有操作系统。
中断的类型有两种:
内中断的例子:(若当前执行的指令是非法的,则会引发一个中断信号)
试图在用户态下执行特权指令。
执行除法指令时发现除数为0。
有时候应用程序想请求操作系统内核的服务,此时会执行__一条特殊的指令——陷入指令__,该指令会引发一个内部中断信号。
【说明】执行__”陷入指令“__,意味着应用程序__主动__地将CPU控制权还给操作系统内核。”系统调用“就是通过陷入指令完成的。
? 【注意】__陷入指令__是一条特殊指令,并不是一条特权指令,因为陷入指令是在用户态执行的。
外中断的例子:
每一条指令执行结束时,CPU都会例行检查是否有外中断信号。
区分__内中断__和__外中断__和方法就是,看此中断信号是来自CPU的内部还是外部。
大多数的教材,试卷中,“中断”特指狭义的的中断,即外中断。而内中断一般称为“异常”。
这里内中断包括:
不同的中断信号,需要不同的中断处理程序来处理。当CPU检测到中断信号后,会根据中断信号的类型取查询“中断向量表”,以此来找到相应的中断处理程序在内存种的存放位置。
中断处理程序一定是内核程序,需要运行在内核态。
学习目标:
其实在第一小节中就已经学习到了。
操作系统作为用户和计算机硬件之间的接口,需要向上提供一些简单易用的服务。主要包括命令接口和程序接口。其中,程序接口由一组__系统调用__组成。
“系统调用”是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的特殊函数,
应用程序可以通过系统调用来请求获得操作系统内核的服务。
普通应用程序 | 可直接进行系统调用,也可以使用库函数。有的库函数涉及系统调用,由的不涉及。 |
---|---|
编程语言 | 向上提供库函数。有时会将系统调用封装成库函数,以隐藏系统调用的一些细节,使程序员编程更加方便。 |
操作系统 | 向上提供系统调用,使得上层程序能请求内核的服务 |
裸机 |
不涉及系统调用的库函数:如__“取绝对值”__的函数。
涉及系统调用的库函数:如__“创建一个新文件”__的函数。
生活场景:去学校打印店打印论文,我使用wps的“打印”选项,在我的论文打印一半时,而有个同学使用word的“打印”按钮,开始打印它的论文。
思考:如果两个进程可以随意地、并发地共享打印机资源,会发生什么情况?
答:两个进程并发运行,打印机设备交替地收到wps和word两个进程发来的打印请求,结果两篇论文的内容混杂在一起了。
__解决办法:__由操作系统内核对共享资源进行统一的管理,并向上提供“系统调用”,用户进程想要使用打印机这种共享资源,只能通过系统调用向操作系统内核发出请求。内核会对各个请求进行协调处理。
系统调用有如下功能:
扩展:也可以了解Linux系统调用。
什么功能要用到系统调用?
应用程序通过系统调用请求操作系统的服务。而系统中的各种共享资源都由操作系统内核统一掌管,因此凡是与__共享资源有关的操作(如存储分配,I/O操作,文件管理等)__,都必须通过系统调用的方式向操作系统内核提出服务请求,由操作系统内核代为完成。这样可以保证系统的稳定性和安全性。防止用户进行非法操作。
一个应用程序运行在用户态,应用程序的各个指令会被CPU依次执行。
当这个应用程序要发出系统调用的时候,这个时候应用程序需要向CPU发出传参指令
,并给CPU中寄存器传入必要的参数。如下:
其中该参数指明了系统调用类型,如“fork”。
那传参指令
会有多条…
主要看系统调用传递几个参数,操作系统会根据此参数来判断,该应用程序是哪种类型的服务。
那当这些参数都放入到寄存器中之后,应用程序就会执行一种特殊的指令陷入指令
,该指令的执行会引发一个内中断(CPU控制权交给操作系统内核),因此转入相应的中断处理程序——即__系统调用的入口程序__。
此时CPU为内核态,并且开始执行__系统调用入口程序的指令__,如下:
然后根据寄存器中的参数判断用户需要那种系统调用服务。比如是fork
服务。
那接下来就需要把fork
相关指令放到CPU种进行运行,如下:
那当系统调用执行完毕后,CPU又会转为用户态,然后继续执行应用程序的其它指令。
传递系统调用参数—>执行陷入指令(用户态)—>执行相应的内请求程序处理系统调用(内核态)—>返回应用程序并继续执行应用程序其它的指令。
【注意】
别名:陷入指令=trap指令=访管指令
。
学习目标:
总而言之,__内核__是操作系统最基本,最核心的部分。
实现操作系统内核功能的那些程序就是__内核程序__。
如上图,我们可以看到始时钟管理
,中断处理
,原语
是最接近于硬件的。
而进程管理
和存储器管理
和设备管理
等功能工作更多的是对数据结构的操作,不会直接涉及硬件。
所以有些操作系统并不会把对系统资源进行管理的功能放在内核当中。而只在内核当中保留与硬件最为紧密的部分(时钟管理、中断管理、原语)。
上面说到在操作系统内核种有一些部分,如:时钟管理、中断管理、原语部分是紧密接触硬件的。
而对系统资源进行管理的功能在其上面。
所以这就引出了两种操作系统内核的设计方法:
需要注意的是:如果是微内核的设计。只有时钟功能
、中断处理
、原语
等于硬件紧密接触的部分才属于运行在内核态。而系统资源管理(存储器管理,功能管理,进程管理)上运行在用户态的。
如下图:
那__大内核__和__微内核__有什么区别呢?
答:微内核的性能不如大内核。如下原因:
假如现在,应用程序想要请求操作系统的服务,这个服务的处理同时涉及到进程管理,存储管理,设备管理。
可以看到,如果是大内核的情况,从用户态到内核态只需要进行两次变态,而微内核的情况,从用户态到内核态需要进行六次变态。
而,变态的过程是有成本的,要消耗不少时间,频繁的变态会降低系统性能。
典型的大内核/宏内核/单内核操作系统:Linux、UNIX。
典型的微内核操作系统:Windows NT。
此小节知识回顾:
该结构,最底层是硬件,最高层是用户接口,每层可调用更低一层,并且只能调用相邻的低一层。
这种分层的结构有些优缺点:
模块化是将操作系统按功能划分为若干个具有一定独立性的模块。每个模块具有某方面的管理功能,并规定好各模块间的接口,使各模块之间能通过接口进行通信。还可以进一步将各模块细分为若干个具有一定功能的子模块,同样也规定好各子模块之间的接口。把这种设计方法称为模块-接口法
。如下图:
内核 = 主模块+可加载内核模块。
__主模块:__就是最核心并且必不可少的那些模块,如:进程调度
,内存管理
等模块。
__可加载内核模块:__可以动态加载新模块到内核,而无需重新编译整个内核。
模块化结构的优缺点:
__内核:__负责进程调度、进程通信等功能。
__外核:__负责为用户进程分配未经抽象的硬件资源(如硬盘空间,内存),且由外核负责保证资源使用安全。
这里来解释以下什么叫做__未经抽象的硬件资源__。
我们直到在__普通的操作系统__之中,如果用户进程想要申请使用一片内存空间,那么操作系统内核给它分配的内存空间是经过抽象的,经过虚拟化的。站在用户进程自己的角度上来看它似乎拥有了一整片连续的内存空间,但事实上分配给该进程的只是虚拟的地址空间。操作系统内核会把这些虚拟的页面映射到实际的物理页框中,这些物理页框在内存中通常是离散的。所以__普通的操作系统__给进程分配的内存空间其实是经过抽象的,经过虚拟化的。除了内存空间之外给进程分配的文件存储空间,外存空间也是抽象的。对于进程来说它觉得自己的文件好像是连续的一个地址空间,但事实上这个文件各个块在磁盘当中很有可能是被离散存储的。所以普通的操作系统给用户进程分配的磁盘空间也是经过抽象的。
但回到__外核__,外核可以给用户进程直接分配未经抽象的硬件资源,这样的资源管理策略有的时候会很有作用。
比如,一个用户进程它很有可能知道,自己的这一片存储空间是经常需要随机访问的。那如果给此用户进程分配的磁盘空间在外存当中是离散的,那么用户进程在随机访问文件块的时候,意味着磁头需要来回横跳,这样就会导致用户进程对自己的文件随机访问的性能变低。
而采用__外核__的策略,外核可以直接给用户进程分配未经抽象的硬件资源,那如果该用户进程知道自己的文件需要频繁的被随机访问,那么用户进程就可以向外核申请给自己一整片连续的磁盘空间。用户进程的这些数据直接存放在连续的磁盘块中,那该用户进程在随机访问的磁盘块时磁头移动距离很小,所以效率就会很快。
所以外核能够给用户进程直接分配一个未经抽象的系统资源是很有用的。
外核除了分配、回收这些未经抽象的硬件资源。它还负责保证这些硬件资源的使用安全。
外核结构的优缺点:
以上操作系统结构特征的汇总:
学习目标:
操作系统引导(boot)——开机的时候怎么让操作系统运行起来。
安装完操作系统之,磁盘内部如下:
先来看C盘:
下面我们来看看C盘中的操作系统是怎么一步一步启动的。
启动操作系统的数据肯定是要放在__主存__里面的。
计算机的主存由两部分组成:
那这就意味着,当CPU开机通电后,CPU会去主存当中固定的位置去找到ROM引导程序,然后执行这个程序里面的指令。
执行这个ROM引导程序的作用是什么呢?
作用是它会指示CPU去把磁盘中主引导程序(MBR)读入主存的RAM里面去。因为主引导程序(MBR)中包含:磁盘引导程序__和__分区表。所以现在把__磁盘引导程序和分区表__读入RAM中去了。
接下来CPU就执行主存里面的磁盘引导程序,而磁盘引导程序会根据分区表判断C盘所处的位置,那接下来就可以读入C盘的第一部分数据——引导记录PBR,这个PBR本质上也是个程序,PBR被读入主存后,CPU开始执行此程序。
PBR负责找到“启动管理器”,这个“启动管理器”在C盘的根目录下某个位置,找到这个“启动管理程序”后,将其读入主存中,然后CPU执行这个“启动管理程序”,接下来这个“启动管理程序”就会完成操作系统初始化的一系列操作。
以上为个人理解操作系统引导过程,下面来看比较权威的概述。
操作系统引导过程主要分为四大步骤,如下图:
我们来看一下,windows下根目录中的“启动管理器”。
传统计算机,由于只能运行一个操作系统,这会导致硬件资源利用不充分。
__虚拟机:__使用虚拟化技术,将一台物理机器虚拟化为多台虚拟机器(Virtual Machine,VM),每个虚拟机器都可以独立运行一个操作系统。
同义术语:虚拟机管理程序/虚拟机监控程序/Virtual Machine Monitor/Hypervisior。
虚拟管理程序可以分为两类:
第一类VMM,直接运行在硬件上:
如何把一个机器上的硬件资源分配给虚拟机器呢?
首先来说CPU,一个单核的CPU,把此CPU的时间片进行划分,每个虚拟机器分配若干个时间片,这样在上层虚拟出来的操作系统来看就是一个独立CPU。但事实上只是把物理CPU的某一些时间片分配给此虚拟机了。
那磁盘、内存就直接划分空间分配给虚拟机即可。
这里只有VMM(虚拟机管理程序)运行在CPU的内核态。而上层虚拟出来的操作系统和应用程序运行在用户态空间。但是虚拟的操作系统并不是到自己是运行在用户态的,它认为自己是运行在内核态的,所以上层的操作系统依然会使用特权指令。但是我们又说只有VMM运行在内核态,所以不能让上层的操作系统使用特权指令。
那这种情况怎么办呢?
可以这样处理:当上层的操作系统想要使用特权指令时,这个行为,动作会被VMM截获,然后VMM将上层操作系统发过来的特权指令进行等价转化,要给上层操作系统一种假象,就让上层的操作系统认为它自己就可以运行特权指令。
第二类VMM:运行在宿主机操作系统上:
例如:VWware workstation、VirtualBox。
那在第一类VMM的情况时,可以将第一类VMM运行在ring 0,而将虚拟的操作系统运行在ring 1,上层的应用程序运行在ring 2。
那当上层操作系统需要使用ring 1,ring 2指令时,就不需要经过VMM了,直接上层操作系统进行ring1和ring2指令即可。
而上层的操作系统需要使用ring 0指令时,才调用VMM去执行ring 0指令。
这就相当于把原来的特权指令又细分了:
这样VMM不用检查每一条特权指令的执行,只需要检查某一些敏感指令即可。