@[toc]
1.1.1 操作系统的概念、目标和功能
思维导图
操作系统的概念(定义)
我们平常买一台电脑,厂家生产的电脑都是一台裸机,然后装了操作系统之后,我们就可以下载应用程序,并且使用应用程序。我们还可以发现,用户也可以直接使用操作系统进行交互,比如cmd
黑窗口。
操作系统是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机地工作和资源地分配,以提供给用户和其他软件方便的接口和环境,它是计算机系统种最基本的系统软件。
- 操作系统是系统资源的管理者:我们可以查看我们的任务管理器,可以看到此时电脑中正在运行的程序,还有一些资源的分配,操作系统可以软件提供分配资源可以对系统的资源进行合理的分配。
- 向上层提供方便易用的服务:我们可以直接通过操作系统命令方式使电脑关机(打开命令行窗口,输入
shutdown -s -t 0
)。也可以通过一些软件打开电脑的摄像头,也是通过调用操作系统执行的。 - 最接近硬件的一层软件:其实操作系统虽然说是系统但还是一层软件。
操作系统的功能和目标--作为系统资源的管理者
用QQ和朋友视频聊天的过程:
- 在各个文件夹中找到QQ的安装位置 ==》 文件管理:负责文件的存取、共享和保护等
- 双击打开QQ程序 ==》 存储器管理:负责内存的分配与回收,执行一个程序必须要将程序放入内存中才能运行。
- QQ程序正常运行 ==》 处理机管理:负责CPU的分配与控制,运行程序必须需要CPU的处理。
- 打开摄像头与朋友聊天 ==》 设备管理:负责设备的分配和操纵,打开摄像头这类硬件设备就需要操作系统来管理。
我们已经介绍了操作系统的主要功能,后续章节都是围绕这几个功能详细展开的。
操作系统的功能和目标--向上层提供方便易用的服务
硬件只听得懂二进制指令,操作系统将用户发出的命令转换为二进制指令给硬件,然后硬件来完成工作。
这里用到了封装的思想,我不用知道具体怎么实现的,我只需要说出我想要什么,让操作系统来做就可以了。
GUI:图形化用户接口:用户可以使用形象的图形界面进行操作,而不需要记忆复杂的命令,参数。比如点开相机,操作系统就会对摄像头操作。
联机命令接口(交互式命令接口):用户说一句,系统跟着做一句。类似python这类解释型语言。
脱机命令接口(批处理命令接口):用户写一堆,系统跟着做一堆。而不是每次一句的执行了,是执行全部的命令,所以也叫批处理命令。
程序接口:可以在程序中进行系统调用来使用程序接口,普通用户不能直接使用程序接口,只能通过程序代码间接使用。
比如我们写c语言程序时经常用到的printf
函数,这个函数的使用就是一种系统调用,让操作系统来完成相关的指令。系统调用也可以说是调用了一些函数。这些函数组成了一个程序,而不是一些简简单单的指令。
总结
以上这些服务也就说明了为什么用户可以与操作系统直接交互了。
而应用程序可以通过程序接口来与操作系统交互,用户又可以使用应用程序间接实现了系统调用。
操作系统的功能和目标--作为最接近硬件的层次
没有操作系统的计算机称为裸机,在裸机上安装操作系统,可以提供资源管理功能和方便用户的服务功能,将裸机改造成为功能更强,使用更方便的机器。比如你只有发动机和轮子是无法运作的,你还要在他们之上覆盖一层传动系统,让发动机能够带动轮子转,这样原始的硬件机器就能有更多的功能了。
操作系统就是这样的一层扩展,可以将CPU,内存、磁盘等硬件合理的组织起来,让各种硬件能够相互协调配合,实现更复杂的功能。
1.1.2 操作系统的特征
1.并发
并发:指两个或多个时间在同一时刻间隔内发生,这些时间宏观上是同时发生的,但微观上是交替发生的。
并行:指两个或多个时间在同一时刻同时发生。
操作系统的并发性:指计算机系统中“同时”运行多个程序,这些程序宏观上看是同时运行着的,而微观上看是交替运行着的。操作系统和程序并发是一起诞生的。
注意
单核CPU:同一时刻只能执行一个程序,各个程序之恶能并发的执行
多核CPU:同一时刻可以同时执行多个程序,多个程序可以并行的执行。如果运行的操作超过了CPU的数量,那么还是会有并发执行的。
2.共享
共享:资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。
- 互斥共享方式:系统中的某些资源,虽然课题提供给多个进程使用,但一个时间段内只允许一个进程访问该资源。 比如说手机上的摄像头,不可能qq和微信同时打开摄像头和别人聊天。
- 同时共享方式:系统中的某些资源,允许一个时间段内由多个经常“同时”对它们进行访问,“同时”也可能是交替访问,比如qq和微信同时发送文件,两个程序看起来是在同时运行,但其实是交替执行的。
3.并发和共享的关系
如果失去并发性,那么系统中只有一个程序正在运行,那么就不需要同时共享资源,所以也就没有了共享性。
如果失去共享性,那么只允许一个程序访问资源,那么也就不会有多个程序同时访问资源,那么也就没有了并发性。
我的理解是,没并发,就执行完一个程序在执行完下一个程序,共享也就不可能实现了,共享就是可以让几个程序交替的访问资源,如果没法交替也就不能并发。
4.虚拟
虚拟:把一个物理上的实体变为若干个逻辑上的对应物,物理实体是实际存在的,而逻辑上对应物是后者感受到的。也就是说用户感觉到的和实际的并无一样。
一个程序需要放入内存并给它分配CPU才能运行,那你会发现你手机上运行了好几个软件,可能超过了运行内存,那么为啥还能同时运行呢,这里就用到了空分复用技术。只把需要用到的东西放入内存就行,其他不需要用到的就继续留在硬盘中。
一个单核CPU的计算机,却能同时运行好几个程序,用户感受到的是多个程序都在同时运行,但CPU在某个时刻中却只能运行一个程序,这又是为什么呢?这里就用到了时分复用技术,每个程序在CPU都只运行一段时间,每个程序交替运行,这样感觉好像多个程序都在同时运行。
虚拟和并发的联系:如果没有并发,那么就会一个时间段内都只运行一个程序,那么内存中也就只会有一个程序,也就没有了空分复用技术。内存中只有一个程序,那么也就不会有时分复用技术。
5.异步
异步:在多道程序环境下,允许多个程序并发执行,但由于资源有限,会等有资源了之后才会继续执行。进程的执行不是一贯到底的,而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。
这里我们用java
里的多线程模拟一下。这里我们可以看到程序不是按照顺序执行的。可能会走走停停。
public class ThreadDemo {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread()+"A吃饭");
try {
//这里由于资源有限,所以必须要等一段时间资源来了在运行。假设等了1秒
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread()+"A交心");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread() + "B吃饭");
System.out.println(Thread.currentThread() + "B交心");
}
}).start();
}
}
并发和异步的执行:如果没有了并发,那么系统只会有一个程序执行,资源也就不会被其他程序占用,那么也就没有了异步性。
总结
没有并发和共享,就谈不上虚拟和异步,因此并发和共享是操作系统两个最基本的特征。
1.2 操作系统的发展与分类
本节学习重点:关注和理解各类操作系统主要想解决的是什么问题,各自的优缺点。
操作系统的发展历程主要就是一个目标:让CPU在有限的时间内做更多的事,让它别闲着。其他都是为它服务的。
1.手工操作阶段
缺点:手工装/取纸带非常慢,纸带机读/写纸带也非常慢,但处理程序的速度非常快。导致效率非常低。而且一段时间内只能处理一个程序。
2.批处理阶段
解决了手工装/取纸带慢的问题,可以将纸带都通过外围机装入道磁带中。
而计算机读/写磁带的速度比纸带机快很多,所以也提升了读/写数据的速度。
引入脱机输入/输出技术,并由监督程序负责控制作业的输入、输出。自动的控制磁带读写的操作。一个程序读/写完,这个监督程序会自动让计算机读/写下一个程序。
这里也就是为什么是脱机技术了,让好几个程序连着执行,而不是每次都只执行一个。加快了速度。
优点:一个作业的输入输出过程快了很多。计算机效率提高了。
缺点:内存中仅能有一道程序执行,只有该程序结束之后才能调入下一个程序,CPU仍然有大量时间处于空闲状态,等待输入输出过程,资源利用率依然很低。
3.多道批处理系统
操作系统正式诞生,用于支持多道程序并发执行。多道批处理系统就不像单道批处理系统那样需要一个作业执行完之后才能执行下一个程序,而是可以在其他作业在读/写的同时处理其他程序。
我的理解:这里很重要的一个点就是每个设备都是接替执行的,读完就可以在读下一个,CPU执行完就可以执行下一个,输出完就输出下一个,每个设备都是分开的,耦合度降低了。处理完之后就不需要在继续等了,直接去处理剩下的。之前的单道每次就只能有一个程序执行,这里可以有多个程序被执行,也就有了并发。
优点:多道程序并发执行,共享计算机资源,资源利用率大幅提升,CPU和其他资源更能保持“忙碌”状态,系统吞吐量增大。
缺点:用户响应时间长,没有人机交互功能(用户提交自己的作业之后就只能等待计算机处理完成,中途不能控制自己的作业执行,无法调试程序/无法在程序允许过程中输入一些参数)。
举个例子:我们写算法题的时候,有时候是读文件的形式,有时是用黑窗口读入程序的形式。用黑窗口可以输入边输入边看程序执行过程,可以根据程序的变化读入不同的数据。而读文件只能一次读完,也没办法调试。
4.分时操作系统
计算机以时间片为单位轮流为各个用户/作业服务,各个用户可以通过终端与计算机进行交互。
优点:用户请求可以被即时响应,解决了人机交互问题,允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在。
我的理解:这也就是上面说的,每个作业不是一次性执行完,而是每次都只执行一小段时间,在步执行的过程中我可以看到程序的变化,还可以输入一些参数修改程序的变化。就像在命令行端口一样,输入一次输出一次。比如我们还可以作业执行过程中让程序停止。这也体现了交互过程。
缺点:不能处理一些紧急任务,操作系统对每个用户/作业都是公平的,循环的为各个用户服务一个时间片。不区分任务的紧急性。
5.实时操作系统
优点:能过优先响应一些紧急任务,某些紧急任务不需要时间片排队。
在实时操作系统的控制下,计算机系统接收到的外部信号后及时进行处理,并且要在严格的时限内处理完事件。
实时操作系统的主要特定是及时性和可靠性。
实时操作系统:
- 硬实时系统:必须在绝对严格的规定时间内完成处理。
- 软实时系统,能接收偶尔违反时间规定。
6.其他操作系统
7.总结
操作系统的发展迭代都是为了解决某个问题而诞生的。
手算太慢==》开发了手工操作系统 ==》速度还是慢,开发了单道批处理系统,解决IO慢的问题 ==》 CPU还是很多时间闲着,效率还是低,所以开发出了批处理系统,让几个程序并发执行 ==》 人机不能交互,那我要在程序运行过程中修改怎么办,开发了分时操作系统 ==》 但是如果有了特别重要的任务来了,我必须要让CPU处理它又怎么办?开发了实时操作系统。
所以一些为了效率。时间就是金钱。
1.3.1 操作系统的运行机制
1.程序是如何运行的?
我们用C语言写一个输出"hello world"程序,必须要编译过后才能运行。而编译的过程其实是将C语言代码准换位机器指令,也就是二进制。一条C语言语句,可能就对应几条机器指令。
程序运行的过程其实也就是CPU执行一条一条机器指令的过程。
指令:CPU能识别、执行的最基本命令。
终端输入的其实是:“交互式命令接口”,本节中的指令是二进制的机器指令。
2.内核程序和应用程序
:lemon:应用程序:手机里下的应用软件
:leaves:内核程序:操作系统里的内核程序,这些内核程序组成了操作系统内核,简称为”内核“。内核是操作系统最重要最核心的部分,也是最接近硬件的部分。系统对系统内资源的管理其实是内核实现的。(Docker)
操作系统的功能未必都在内核中,如图形化界面GUI。
3.特权指令和非特权指令
:octopus:特权指令:只能由内核才能使用特权指令,而普通应用程序无法使用特权指令
特权指令对系统影响重大,可能会出现不可挽回的操作,所以必须由内核来发出,不能让其他应用程序发出。
在CPU设计和生产过程中就划分了特权指令和非特权指令,因此CPU执行一条指令就能够区分出类型。
我的理解,比如关机这件事,不能一个应用软件就可以随便关机吧。也不可能随便就给电脑设置密码。当然有些病毒可以做到。(我上初中时差点就被搞了,但是我意识到有问题就迅速关机然后没事了,事后还要敲诈我)。
4.内核态和用户态
:question:这里又有一个问题:CPU时如何区别是应用程序发出的特权指令还是内核程序发出的特权指令。
CPU有两种状态:内核态和用户态
处于内核态时,说明此时正在运行的时内核程序,此时可以执行特权指令也可以执行非特权指令。
处于用户态时,说明此时正在运行的时应用程序,此时只能执行非特权指令。
CPU里有一个程序状态寄存器,用0/1表示状态
5.内核态和用户态的切换
一个故事举例:
- 刚开机时,CPU为内核态,因为要初始化一些电脑需要用到的资源等,操作系统内核程序就会在CPU上先执行。
- 开机完成后,用户可以启动某个应用程序。
- 操作系统内核程序在合适的时候会主动让出CPU,让应用程序执行
- 此时应用程序处于用户态
- 此时,一个黑客在应用程序中植入了一条特权指令,企图破坏系统。
- CPU发现接下来执行的这条指令时特权指令,而自己又处于用户态
- 这个非法时间会引起一个中断信号
- CPU检测道中断信号后,会立即转换为内核态,并停止运行当前的应用程序,转而运行处理中断信号的内核程序。(在生活中,你开车突然熄火了,你一定会停车并且下来检查有没有问题,或者去维修店维修,此时那个维修店就是内核态检查汽车的内部问题,当都处理完后才会把车交给你,你才能放心的继续开车)
- 内核态处理完后,又会转为用户态,继续执行接下来的应用程序。
:cherry_blossom:内核态-->用户态:执行了一条特权指令,修改程序状态寄存器为用户态标志,这意味着操作系统主动让出CPU使用权。
:white_flower:用户态-->内核态:由中断引发,硬件自动完成变态过程,除法终端信号意味着操作系统将强行夺回CPU的使用权。
总结
1.3.2中断和异常
中断的作用
:ok_hand: 中断会使CPU由用户态变为内核态,使操作系统重新夺回CPU的使用权。中断也是让操作系统内核夺回CPU使用权的唯一路径。
:question:如果没有中断机制的化,那么一旦应用程序上CPU运行,CPU就会一直运行这个应用程序,那么并发怎么办?这样不久没办法实现并发了嘛。所以要想实现并发,必须要实现中断。
中断的类型
内中断:与当前执行的指令有关,中断信号来源于CPU内部。
外中断:与当前执行的指令无关,中断信号来源于CPU外部。
:ledger:内中断的例子:
- 用户态状态下,发现了特权指令,那么就会引发中断,从而转为内核态,处理中断信号的内核程序。
- 执行除法指令时发现除数为0。
这里我们用Java来实现这个例子
public class Demo { public static void main(String[] args) { int i=1/0; } }
这里就报了一个异常,表示除零错误。
- 有时候应用程序想请求操作系统内核的服务,此时会执行一条特殊的指令--陷入指令,该指令就回引发一个内部中断信号。这是应用程序主动要求转为内核态的,不是被动的,它也不是特权指令,它实在用户态下执行的。
所以如果执行指令非法或者参数非法或者主动想要切换内核态的话,那么就会引发 内中断。
:book:外中断的例子:
- 时钟中断--由时钟部件发来的中断信号。时钟部件每隔一个时间片就回发送一次中断信号,内核程序会处理时钟中断,并且把CPU的使用权交给其他应用程序,从而切换为用户态,让其他程序上CPU执行。这也就实现了并发。
- I/O中断--由输入/输出设备发来的中断信号。当输入输出设备完成时,向CPU发送中断信号,通知已经完成了。CPU又会转为内核态处理中断。
CPU在每一个指令结束的时候就会例行检查有无外中断信号。
总结
故障:由错误条件引起的,可能被内核程序修复,内核程序修复故障后会把CPU使用权还给应用程序,让他继续执行下去。
终止:内核程序无法修复了,必须终止应用程序。
中断机制的基本原理
不同的中断不可能由同一个中断处理程序来出来,所以会由不同。
CPU会根据不同的中断信号,需要用不同的中断处理程序来处理。当CPU检测道中断信号后,会根据中断信号的类型去查询”中断向量表“,以此来找到相应的中断处理程序在内存中的存放位置。
总结
1.3.3 系统调用
1.什么是系统调用,有何作用?
操作系统作为用户和计算机之间的接口,需要向上层提供一些简单易用的服务,主要包括命令接口和程序接口。其中,程序接口由一组系统调用组成。应用程序可以通过系统调用来请求获得操作系统内核的服务。
2.系统调用和库函数的区别
C语言库函数有些就会执行系统调用,C语言将系统调用封装成库函数,以隐藏系统调用的一些细节,是程序员编程更加方便。
应用程序可以直接进行系统调用,也可以使用库函数。
并不是所有的库函数都会进行系统调用,比如”取最大值“就不会有系统调用,而”创建一个新文件“函数就回进行系统调用。
:question: 为什么系统调用是必须的?
这里如果两台打印机并发执行的话,那么打印出来的一定会很乱。所以不能这两个程序都同时使用打印机。
如何解决:操作系统内核对共享资源进行统一管理,并向上提供”系统调用“,用户进程想要使用打印机这种资源,只能通过系统调用向操作系统内核发出请求,内核对各个请求进行协调处理。 如果打印机已经被使用了,那么其他程序要想使用打印机就只能等待。
3.什么功能要用到系统调用
凡是和共享资源有关的操作(如存储分配、I/O操作,文件管理等),都必须通过系统调用的方式向操作系统内核提出服务请求,由操作系统内核代为完成,这样可以保证系统的稳定性和安全性,防止用户进行非法操作。也就是说只要是很重要的东西都需要由操作系统内核来完成,所以就需要通过系统调用。
4.系统调用的过程
一个程序想要使用系统调用的话会先将一些要执行系统调用的类型和参数存放入寄存器中,然后执行“陷入指令”,随后转入内核态,这里会有一个系统调用入口程序,根据寄存器中的参数判断用户需要那种系统调用服务。随后在转入那种系统调用的处理程序。
简单来说就是:
- 存参数
- 变态
- 取参数
- 调入程序
- 变回去
细节
总结
1.4 操作系统的体系结构
1.操作系统的内核
操作系统包含内核和非内核功能
:ice_cream:非内核功能:如GUI
:ear_of_rice:内核包括:进程管理,存储器管理,设备管理,处理器管理,时钟管理,中断管理,原语。
时钟管理:利用时钟中断实现计时功能,也实现了并发性
原语:原语是一种特殊的程序,具有原子性。也就是说,这段程序的运行必须一气呵成,不可被中断。和事务类似。
2.操作系统的体系结构
内核:包括大内核和微内核,大内核是整个内核,而微内核只保留时钟管理、中断处理、原语这些与硬件紧闭相连的功能,把进程管理、存储器管理等纳入了非内核功能,这些功能更多的是对数据结构的操作,而不会直接涉及到硬件部分。
区别:非内核是在用户态下执行的,内核功能是在内核态下执行,所以微内核就把那些管理放到了非内核态下执行。
举个例子:一个应用程序想要请求操作系统的服务,这个服务的处理同时涉及到进程管理,存储器管理,设备管理。
如果在大内核下,所有请求都会转为内核态处理,而在微内核下,每个在用户态下的管理都要转换到内核态下进行处理,这样就大大增加了状态转化的数量,浪费了更多的资源和成本。
3.总结
大内核:把操作系统的主要功能都作为系统内核,运行在核心态。
- 优点:高性能
- 缺点:内核代码庞大,结构混乱,难以维护。
微内核:只把最基本的功能保留在内核
- 优点:内核功能少,结构清晰,方便维护
- 缺点:需要频繁地在核心态和用户态之间切换,性能低。
1.5 第一章知识回顾
1.OS的概念和功能
- 向上提供接口:比如CMD命令行接口,联机命令结构,脱机命令接口,还有GUI图形窗口,还有程序接口,让应用程序实现系统调用。
- 对下层功能的拓展:实现了对硬件设备的功能拓展,使各个硬件相互协调配合,实现更复杂的功能。
- 对系统资源的管理:处理器管理(对CPU的分配和控制),存储器管理(对内存的管理和回收),设备管理(对设备的分配和操作),文件管理(对文件的存取、保护、共享等)。
2.OS的发展与特征
发展:
- 手工操作阶段:手工装取纸带慢,计算机读取纸带慢,但计算机计算很快,所以效率很低。
- 批处理阶段:计算机读取磁带快了很多,但一次还是只能运行一个程序,CPU还是有很多时间在空闲,效率依然很低。
- 多道批处理系统:多道程序一起被计算机读入,实现了程序之间并发执行,大大提升了效率,但无法实现交互功能,用户无法查看程序执行过程。
- 分时操作系统:每个程序会轮流得到一个时间片处理时间,用户就可以在不处理当前程序时输入指令,更改程序的执行,也可以查看程序的执行过程,可以调试。但是又存在无法紧急处理程序的问题,比如又更重要的程序需要执行,但时间片还没轮到自己。
- 实时操作系统:能够及时对紧急任务进行处理,实现了操作系统的及时性和可靠性。
特征:
- 并发:在一个时间段内有多个程序执行,但不是同时执行,而是交替执行。
- 并行:同一个时间段内有两个或多个程序在同时执行。多核CPU可以实现。
- 共享:一个文件能够同时并多个程序访问,可以是并发访问,也可以是并行。如果没有了并发,那么系统内只能有一个程序在执行,那么就不可能有共享这一说。如果没有共享,那么就不会有多个程序同时访问资源,那么也就没有了并发。、
- 异步:
4.中断和异常
:one:有何作用:
中断可以迅速处理危险信号,比如用户态下要执行特权指令就会引发中断,转为内核态,让中断处理程序处理这个中断。
中断也可以让应用程序进行一些系统调用,比如C语言中的创建文件函数,就会用到系统调用。
应用程序为了使用内核态下的功能,主动地执行陷入指令,转变状态,获取自己想要地服务。
中断也可以实现并发, 比如时钟中断,让每个应用程序只执行一个时间片。
异常可能是程序出现了问题,需要被修复后才能执行,但故障表示无法修复,必须终止程序运行。
根据不同的中断信号,内核态下会查询中断向量表,找到对应地中断处理程序。