1. 前言
操作系统是管理计算机硬件和软件资源的计算机程序。比如管理配置内存、决定资源供需顺序、控制输入输出设备,提供用户交互等。
操作系统并不局限于存在在计算机,手机也是有操作系统的。常见的操作系统有:Android、iOS、Windos、Linux、MacOS。
我们不可能直接操作计算机硬件,而且像以前的计算机中编写的程序并不是可以在任何计算机上可以运行,所以就需要一个通用的环境,提出了操作系统。有了操作系统,普通人也可以方便使用。
2. 操作系统的演进
1.无操作系统的时代
- 人工操作:就是人工把编写的代码或数据转成二进制给计算机,然后使用穿孔纸带(带孔的设为1,无孔设为0),经过光电扫描输入电脑。要是有一个错误或者想改写代码/数据就得重新打印纸带。
其实那时候一般都是专业程序员搞的,并不是普通人就可以玩的。而且每次读取一条纸带就得占用一台计算机。CPU等人工操作。每次纸带读取完还得人工去拿下一条纸带给它读取,人不能离开计算机。资源利用率很低。
2.批处理系统的时代:
- 批处理是指用户将一批作业提交给操作系统后就不再干预,由操作系统控制它们自动运行,再输出结果,从而减少作业建立和结束过程中的时间浪费。也就是无需等待人工操作,计算机这时可以自动、成批的执行程序。
- 批量输入任务。数据可以批量输入到计算机中,但是并不是一次性把批量输入都处理了,早期的计算机的操作系统可以称为单道批处理系统,即内存中只允许存放一个作业。
- 资源利用率相对于之前有提高。但是一个作业单独进入内存并独占系统资源,直到运行结束后下一个作业才能进入内存,当作业进行I/O操作时,CPU只能处于等待状态,所以CPU利用率还是较低,尤其是对于I/O操作时间较长的作业。
多道程序设计。后来才提出的,此时的操作系统可以称为:多道批处理系统。即在内存中可同时存在若干道作业,说白了就是让批处理系统可以一次性处理多个作业,但其实是快速的穿插运行,使得看起来可以处理多个作业,因此CPU的利用率显著地提高了。
3.分时系统的时代:
- 人-机交互,也就是人工可以干预计算机,及时调试程序。
- 多用户共享计算机资源。
- 资源利用率大幅度提高.
3. 操作系统相关概念
- 并发性:指的是两个或多个事件可以在同一个时间间隔发送。
- 并行性:指的是两个或多个事件可以在同一个时刻发送。
当提到单处理器时实际上指的是并发性,提到多处理器指的是并行性。
-
共享性:操作系统的资源可以供给多个并发的程序共同使用。共享性可分为:互斥共享(当资源被程序A占用时,其他程序就只能等待程序A使用完释放后才可以使用),同时访问(某种资源在一段时间内并发地被多个程序访问,可以宏观地看该资源可以被同时访问,因为很快)
-
虚拟性:把一个物理实体转变为若干个逻辑实体,物理实体是真实存在的,比如硬件设备,逻辑实体是虚拟存在的,虚拟的技术主要有时分复用技术和空分复用技术。
- 时分复用技术:资源在时间上进行复用,不同程序并发使用。
- 虚拟处理技术:借助多道程序设计,为每个程序建立进程,然后多个进程分时复用处理器。
- 虚拟设备技术:物理设备虚拟为多个逻辑设备(能进行逻辑运算的设备),每个程序占用一个逻辑设备,多个程序通过逻辑设备并发访问。比如后面要学的spooling用的就是虚拟设备技术。
- 空分复用技术:来实现虚拟磁盘、虚拟内存等。
- 虚拟硬盘技术:物理磁盘虚拟为逻辑磁盘,比如把一个机械硬盘分区。
- 虚拟内存技术:在逻辑上扩大程序的存储容量,使用比实际内存更大的容量,提升编程效率。
- 时分复用技术:资源在时间上进行复用,不同程序并发使用。
-
异步性:在多道程序设计的环境下,允许多个进程并发执行,进程在使用资源时可能需要等待或放弃。比如上面的互斥共享。进程的执行并不是一下子对程序的代码执行到底,而是以走走停停的形式推进。比如进程A释放资源,进程B,C目前在抢夺资源,此时B或者C谁能抢到是不知道的,这也体现异步性。
-
操作系统的五大功能:进程管理、存储管理、作业管理、文件管理、设备管理。
4. 进程管理
4.1 进程
进程(Process):是系统进行资源分配和调度的基本单位。进程作为程序独立运行的载体,保证了程序正常执行。我们的桌面应用当点击启动时就会变成进程。
为什么需要进程?早期没操作系统,那么资源就只能分配给当前运行的程序;当有了操作系统,引入多道程序设计后,进程就出现,来合理隔离每个程序占用的资源。
进程在内存是一段连续的内存空间,这段空间称为进程控制块(PCB,一个数据结构),每一个进程一定有一个PCB,而进程控制块的构成如下:
解释:
- 标识符:唯一标识一个进程,用于区别其他进程。
- 状态:状态一共有三种(运行,等待,阻塞,当然也可以说5种,还有创建和终止)。有一张很重要的进程状态转换图,后续再说。
- 优先级:表示获得CPU控制权的优先级大小
- 程序计数器(PC):进程即将被执行的下一条指令的地址。
- 内存指针:可能是程序代码、或进程数据相关指针。
- 上下文数据:进程执行时处理器存储的数据。
- IO状态信息:被进程IO操作所占用的文件列表。像要删除某个文件夹,发现删不了,一看原来是文件夹里面的文件没有关闭,一直占用。
- 记账信息:进程使用CPU时间、时钟数总和等。
而上面可以总结分成四个种:进程标识符、处理机状态、进程调度信息、进程控制信息。
因为PCB是操作系统进行调度经常被读取的信息,所以PCB是常驻内存的,系统中有专门开辟一块PCB区域来存储所有进程的PCB。
4.2 线程
线程(Thread):是系统进行资源分配和调度的最小单位。进程是由系统分配,线程是由CPU分配,线程包含在进程中的,是进程中实际运行工作的单位,比如计算一个数据,是利用线程来进行计算。一个进程至少有一个线程,每当启动程序就先创建进程再创建一个线程。
一个进程可以并发多个线程,每个线程执行不同的任务。进程中的线程共享进程的资源,比如一个线程计算出的结果可以保存再进程中某个区域,然后另一个线程可以从进程中拿去到这个结果。
总结进程和线程的区别:
4.3 进程状态
也称为进程的生命周期。
1.就绪状态
- 当进程被分配到除CPU以外的所有必要资源后,只要再获得CPU的使用权,就可以立即运行。
- 在一个系统中多个处于就绪状态的进程通常排成一个队列,称为就绪队列。
2.运行(执行)状态:
- 进程获取CPU,其进程就称为运行状态。
- 在单处理器中,在某个时刻只能有一个进程是处于运行状态(并发)。
3.阻塞状态:
- 进程因某种原因,如其他设备未就绪而无法继续执行。从而放弃CPU的状态就称为阻塞状态。
- 像我们去打印时,在进程中已经向打印机发出打印请求,但发现打印机打印的可能还不是我们的,此时我们的进程就可以称为阻塞状态或等待中。
- 系统中可能有一个或多个阻塞进程,所以也有阻塞队列这个概念。
4.创建状态:创建进程时拥有PCB但其他资源尚未就绪的状态称为创建状态。
5.终止状态:进程结束由系统清理或者归还PCB的状态称为终止状态。
进程状态转换图:
4.4 同步
引入生产者-消费者问题:有一群生产者进程在生产产品,并将这些产品提供给消费者进程进行消费,生产者进程和消费者进程可以并发执行,在两者之间设置了一个具有n可缓冲区的缓冲池,生产者进程需要将所生产的产品放到一个缓冲区中,消费者进程可以从缓冲区取走产品消费。
当生产者生产一个产品,缓冲区就+1,当消费者拿取一个产品,缓冲区就-1。
来到计算机,一般一个操作缓冲需要三个步骤:
register = count; // 先从缓冲区拿取产品数
register = register + 1; // 然后生产,对其加1
count = register; // 把更新的值归还到缓冲区
但是在计算机中这样是有问题的,因为计算机中是并发执行的,比如:
可以代码:
/*
* 刚开始仓库数为0
* 现在要生产10次,消费10次,那么理想中最终仓库数应该为0
* 使用多线程来并发模仿一个生产,一个消费
*/
class Store {
private int num = 0;
public void producer() {
int times = 10;
while(times-- != 0) {
try {
this.num = this.num + 1;
System.out