操作系统——OS概述
操作系统概念
操作系统(Operation System,OS)是管理计算机硬件与软件资源的计算机程序。由此来看,OS是一种特殊的软件,它给用户和其他软件提供接口和环境,是计算机系统中最基本的系统软件。常见的OS有Linux、MacOS、Windows。
计算机系统由上到底层的结构:
- 用户
- 应用程序
- OS
- 硬件(裸机;一般称没有软件只有硬件的机器为裸机)
总体来讲,OS解决了如下问题:
- 与硬件交互
- 对资源共享进行调度管理
- 解决并发操作处理的协调问题
- 数据机构复杂,外部接口多样化,便于用户反复使用
OS功能有:
- 管理与配置内存
- 决定系统资源供需优先次序
- 控制输入/输出设备(I/O设备)
- 提供用户与硬件系统之间的接口
- 实现对计算机资源的抽象
在计算机上配置OS的目标
分为有效性、方便性、可扩充性、开放性几个方面。
为了管理系统资源,如提高系统资源利用率、提高系统吞吐量(有效性),同时为了方便用户使用(方便性)以及作为扩充机器(可扩充性、开放性)。
OS提供的接口
OS给用户与计算机硬件系统提供的接口通常有三种,即程序接口、命令接口、图形用户接口(Graphical User Interface, GUI)。命令接口分为了联机命令接口与脱机硬件接口,其中脱机硬件接口又叫批处理接口。
联机命令接口,通常是用户发出一个命令,OS就跟着执行一个功能。而批处理接口,包含多个命令(如Windows下的.bat后缀的脚本文件)。
echo "helloworld"
echo "hello, OS"
GUI就是我们开机后经常看到的图形界面,通常你能够利用鼠标点击某系图标或按钮来执行某些功能。如点击浏览器图标,打开一个浏览器窗口。这个过程开放了简单的访问方式,隐藏了实现细节。
程序接口,即可以在程序中进行系统调用来使用的接口。一般由程序员来调用,比如我们用C语言写一个HelloWorld程序:
#include <stdio.h>
int main(){
printf("hello, world\n");
return 0;
}
我们在最开始会引入stdio.h
这个头文件,这个文件实际上声明了一系列的接口,其过程由一些系统调用来完成。例如我们使用的printf
这个函数,它就负责通过系统调用将我们的字符打印到显示设备上。
另外,在某些书籍上,命令接口与程序接口又统称为用户接口。我们可以看出对于GUI和命令接口,使用方式比较直接,它是直接给用户使用的;而程序接口则相反,它需要用户通过程序间调用来完成。
OS的特征
OS具有并发性、共享性、虚拟性、异步性等特征。并发与共享是OS两个最基本的特征,二者互为存在条件,若无并发性共享性也就无意义;若无共享性,就无法同时实现并发。
并发性
我们首先来看并发与并行两个概念:并发是指两个或多个事件在宏观上同时发生,但在微观上可能是交替发生的。而并行是指两个或多个事件在同一时刻发生。
用生活中的例子来讲(当然有些不严谨),所谓并行就好比你便做饭便烧水,这两个是可以同时进行的。而并发就是你在写作业时,先完成一道数学习题,在完成一道物理习题,在宏观上看你同时在写物理作业和数学作业,但在微观上你的数学题和物理题是交替完成的。
因此对于单核CPU,一次只能执行一个程序,各个程序只能并发执行;而对于多核CPU,可以同一时刻执行多个程序,可以并行执行。
共享性
资源共享可以分为两种共享方式,即互斥共享和同时共享。互斥共享一个时间段内只能允许一个进程访问该资源;而同时共享可以由多个程序“同时”对它们访问(这里的同时为微观上交替宏观上的同时)。
用一个例子来讲,所谓互斥共享,就是你在进行微信视频通话的时候,别的软件是无法使用摄像头的。同时共享就是你用微信发送一个文件,同时使用QQ发送一个文件,宏观上看两个软件都在同时发送文件,说明两个进程都在访问硬件资源读取数据,从微观上看两者是交替访问硬盘的。
虚拟性
虚拟是把物理上一个实体变为若干个逻辑上的对应物。虚拟技术分有空分复用技术和时分复用技术。例如后面地虚拟存储器就是一种空分复用技术,而虚拟处理器实际上是一种时分复用技术。
若没有并发性,OS只需要运行一道程序,那么就是去了虚拟性的意义。
异步性
异步是在多道程序环境下,允许多个进程并发执行,但由于资源有限,进程的执行不是一贯道到底的,而是走走停停以不可预知的速度向前推进。
由此可见只有系统具有并发性才能导致异步性。
OS分类
最早期程序员都是通过对纸带打孔,输入纸带机,但这个速度非常缓慢,而计算过程又十分快速,计算完成后还是需要纸带输出,这个过程又会变得相当缓慢。在上述过程中,用户独占全机,而且人机速率之间的矛盾导致资源利用率极低。
单道批处理系统
单道批处理系统引入了脱机输入/输出技术,使用外围机与磁带完成,并且由监督程序控制作业输入。外围机把程序提前存放到磁带里,磁带读写速度比纸带快得多。
此时计算机中运行着一个监督程序,负责从磁带输入数据,并计算完成后输出数据到磁带中。
这个监督程序实际上就是OS的雏形,但是这种方式只允许内存中又一道程序,并且该程序结束后才能执行下面的程序。CPU有大量时间在空闲等待I/O完成,资源利用率仍然很低。
多道批处理系统
每次从磁带内读入多道程序,标志着OS正式诞生,用于支持多道程序并发运行。
多道资源并发执行,共享计算机资源,资源利用率大幅度提升,CPU与其他资源更是能保持忙碌状态,系统吞吐量增大。但是用户响应时间长,没有人机交互过程。(用户提交作业后就只能等待,中间不能控制自己作业执行)
分时操作系统
计算机以时间片为单位轮流为各个作业或用户服务,各用户可用通过终端与计算机进行交互。
但是这种方式不能处理一些紧急任务,OS对各个作业或用户都是完全公平的,循环为每人服务一个时间片。
实时操作系统
实时操作系统能优先相应一些紧急任务,某些紧急任务不需要时间片排队。在这种情况下,计算机在收到外部信号后及时进行处理,并且要在严格时间限度内完成事件。这类OS的主要特点是及时性和可靠性。
实时OS分为两种:硬实时系统和软实时系统。硬实时系统要求时间限度必须严格,如自动驾驶系统等;而软实时系统能接受偶尔违反时间规定,如火车订票系统。
微机操作系统
微机实际上就是个人计算机(为了防止与程序计数器混淆,在后面的介绍中一般不用缩写PC)。
微机操作系统从单用户单任务计算机(如MS-DOS)逐渐演变到了多用户多任务(如Unix、Windows等)。
其他操作系统
网络操作系统:伴随计算机网络诞生,能把网络中各个计算机有机结合起来,实现数据传送等功能,实现网络各种资源的共享和各个计算机的通信 。
分布式操作系统:主要特点是分布性和并行性,系统中的各台计算机地位相等,任何工作都可以分布在这些计算机上,并由它们并行、协同完成任务。
OS运行机制
这里首先区分下指令与命令的概念。通常OS中所指的指令,是CPU能识别、执行的最基本的命令。而对于终端中的命令,很多人也习惯上称为指令,但实际上是调用程序的接口。
以C语言为例子,C语言代码被编译成一条条机器指令(二进制),这个就是我们上方提到的指令。
而通过某些符号启动这个编译后的程序,并传入某些参数,这个符号实际上是程序预留给用户的接口,即我们上面说的终端里的命令。
程序分为两种:内核程序和应用程序。以我们文章上方写的HelloWorld为例,这种就是应用程序。而有一些程序员专门负责开发操作系统,写的是内核程序,很多内核组成了OS的内核,简称内核(kernel)。内核时OS最核心最接近硬件的部分,甚至可以说一个OS只要有一个内核就够了。但操作系统所有的功能未必都在内核中,例如GNU/Linux的GUI,而Windows的GUI是放在内核中的。但无论如何,我们通常指操作系统一般是指其内核。
既然程序分为两种,那么就必然有些CPU指令只能运行在内核程序中,而不能运行在应用程序里,这类指令叫做特权指令,它们通常影响重大,例如内存清零指令,所以只允许OS这个管理者使用。而特权指令以外的被叫做非特权指令。
CPU在设计的时候就划分了特权指令和非特权指令,因此CPU执行一条指令前就能判断类型,这是CPU硬件固有的功能,而不是软件划分。
那么问题来了,CPU如何判断此时运行的程序是哪一种?CPU有两种状态,一种是内核态(又称核心态、管态)另一种为用户态(又称目态),处于内核态说明运行的是内核程序,而用户态自然就是应用程序。CPU内部有一个程序状态字寄存器(PSW),其中有个二进制位,1表示内核态,0表示用户态。
CPU的内核态到用户态,执行力一条特权指令,修改了PSW标志位为用户态,这意味着OS主动让出CPU使用权;而用户态到内核态的切换由中断引发,硬件自动切换,这意味着OS强行剥夺CPU使用权(例如程序执行了系统调用,包含了一条trap指令引发中断)。
中断与异常
中断是让OS夺回CPU使用权的唯一途径。如果没有中断,CPU就会一直运行某个程序,也就无并发可言。
中断分为两种:内中断和外中断。
内中断又被叫做异常、例外,通常是trap指令、故障以及终止。trap指令由程序故意引发目的是执行某些系统调用陷入到内核态,故障是由于错误引起的,这些错误可能被内核修复,修复后会把CPU使用权还给应用程序,而终止更加严重,由致命错误引起,内核无法修复,该应用程序会被直接终止。
外中断也称中断,是一种狭义中断,例如时钟信号和I/O请求中断。时钟中断是由CPU的始终部件导致的,该部件每隔一段固定时间会给CPU发来一个中断信号;而IO中断通常是某些IO设备完成任务的时候用来告知OS操作系统进行处理。
不同的中断信号需要用到不同中断程序处理。CPU检测到中断信号后,会根据中断信号的类型去查询中断向量表,以此来找到相应的中断处理程序在内存中的存放位置。
系统调用
应用程序通过请求系统调用来完成请求OS的服务。系统调用通常与共享资源的管理相关,如设备管理、文件管理、进程管理、进程通信、内存管理等。这样某些操作就可由OS代替应用程序完成,保证了系统稳定性和安全性。
比如试想一个应用程序若不用经过系统调用可以直接对内存进行操作,对于其他正在运行的程序随时可能会由于这个程序修改内存数据而崩溃。
系统调用的过程:
- 传参
- trap指令
- 由OS kernel处理系统调用请求
- 返回应用程序
OS体系结构
宏内核
宏内核将进程管理、存储管理等功能都写在了内核之中。对于这些资源的处理都需要切换到内核态。
如Linux、Unix是经典的宏内核OS。
微内核
微内核将与硬件联系最紧密的功能存放在了内核里,如原语(原子操作)、中断处理、始终管理。而像进程管理、存储管理、设备管理都被放在了内核之外,这些不需要通过切换到内核态来执行。
当用户程序请求服务,这个服务涉及进程管理、设备管理、存储管理,而这些被请求的模块还要通过内核来访问硬件资源,这些操作会导致CPU在内核态与用户态之间来回切换,总共有6次状态切换,有一定的性能开销,而对于宏内核来讲,只需要两次。
分层结构
分层结构的最底层是硬件,最高层是用户接口。每一层对上提供接口,对下进行调用。逐层之间接口调用清晰固定,但是效率低,不可跨层,且系统调用时间长。
模块化结构
模块化会把内核划分为多个模块,各个模块之间相互写作。内核分为主模块和其余客家在内核模块。主模块只负责核心功能,如进程调度、内存管理,而可加载内核模块可以动态加载到内核无需重新编译。
这种方式虽然增强了OS的适应性,而且任何模块都可以调用其他模块无需采用消息通信的方式提高了效率,但实际上编写的时候接口定义未必合理,而且可能导致模块间相互依赖难以维护。
外核
外核操作系统减少传统概念,即操作系统必须提供构建应用程序的抽象内容。该方法实现了应用级资源管理,即由应用程序而不是操作系统管理硬件资源。这时,进程间通信、虚拟内存管理等抽象概念都是单个应用实现的。因此,可以将这些应用作为库操作系统(LibOS)使用。被称为外核的最小核心安全可靠的为多个LibOS提供了有用的硬件资源。
内核负责进程调度、进程通信,外核负责抽象资源分配。
OS引导
计算机主存分为两部分,ROM和RAM。RAM断电后里面的数据会被清空,而ROM不会。
ROM通常集成在主板上,里面存放着基本输入输出系统(Basic Input/Output System, BIOS),这个程序里包含ROM引导程序即自举程序。
CPU一通电就会到主存特定地址找到这个自举程序,执行这个指令,然后会把磁盘的主引导记录读入到RAM中,主引导记录中包含分区表和磁盘引导程序,磁盘引导程序会根据分区表来判断活动分区(安装了操作系统的分区,如c盘),读入这个分区头部的引导记录PBR到RAM中,PBR负责找到根目录的启动管理程序,这个启动管理程序会负责初始化系统,完成开机动作。