操作系统

请注意,本文编写于 901 天前,最后修改于 876 天前,其中某些信息可能已经过时。

硬件结构

存储器的层次结构

image-20220331222447058.png
image-20220331222447058.png

CPU Cache(L1 Cache、L2 Cache、L3 Cache)

内存

SSD/HDD硬盘

中断与软中断

中断:中断请求的响应程序,也就是中断处理程序,要尽可能快的执行完,这样可以减少对正常进程运行调度地影响

软中断:为了解决中断处理程序执行过⻓和中断丢失的问题,将中断过程分成了两个阶段,分别是上半部和下半部分,上半部用来快速处理中断,下半部用来延迟处理上半部未完成的工作。

负数、小数、补码

负数要用补码表示

补码就是把正数的二进制全部取反再加 1

小数部分的转换不同于整数部分,它采用的是乘 2 取整法,整数部分 + 小数部分

0.1转换成二进制

image-20220331223548004.png
image-20220331223548004.png

由于计算机的资源是有限的,所以是没办法用二进制精确的表示 0.1,只能用「近似值」来表示,就是在有限的精度情况下,最大化接近 0.1 的二进制数,于是就会造成精度缺失的情况

用32位来表示的浮点数,则称为单精度浮点数

用64位来表示的浮点数,称为双精度浮点数

内存管理

虚拟内存

操作系统会提供一种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来

我们程序所使用的内存地址叫做虚拟内存地址

实际存在硬件里面的空间地址叫物理内存地址

内存分段

不同的段是有不同的属性的,所以就用分段(Segmentation)的形式把这些段分离出来。

image-20220401143450196.png
image-20220401143450196.png

分段会产生碎片,所以进行内存交换。

因为硬盘的访问速度要比内存慢太多了,每一次内存交换,我们都需要把一大段连续的内存数据写到硬盘上,为了解决内存分段的内存碎片和内存交换效率低的问题,就出现了内存分⻚

内存分页

分⻚是把整个虚拟和物理内存空间切成一段段固定尺寸的大小。这样一个连续并且尺寸固定的内存空间,我们叫页(Page)。在 Linux 下,每一页的大小为4KB。

采用了分⻚,那么释放的内存都是以页为单位释放的,也就不会产生无法给进程使用的小内存

image-20220401143933698.png
image-20220401143933698.png

把虚拟内存地址,切分成⻚号和偏移量;
根据⻚号,从⻚表里面,查询对应的物理⻚号;
直接拿物理⻚号,加上前面的偏移量,就得到了物理内存地址。

100个进程的话,就需要400MB的内存来存储⻚表,这是非常大的内存了
要解决上面的问题,就需要采用一种叫作多级⻚表。

image-20220401144048053.png
image-20220401144048053.png

image-20220401144125434.png
image-20220401144125434.png

段页式内存管理

先将程序划分为多个有逻辑意义的段,也就是前面提到的分段机制;
接着再把每个段划分为多个⻚,也就是对分段划分出来的连续空间,再划分固定大小的⻚;

地址结构就由段号、段内⻚号和⻚内位移三部分组成

image-20220401144225718.png
image-20220401144225718.png

第一次访问段表,得到⻚表起始地址;
第二次访问⻚表,得到物理⻚号;
第三次将物理⻚号与⻚内位移组合,得到物理地址。

进程与线程

进程

image-20220401144444098.png
image-20220401144444098.png

image-20220401144514949.png
image-20220401144514949.png

创建进程

为新进程分配一个唯一的进程标识号,并申请一个空白的 PCB,PCB 是有限的,若申请失败则创建失败;
为进程分配资源,此处如果资源不足,进程就会进入等待状态,以等待资源;
初始化 PCB;
如果进程的调度队列能够接纳新进程,那就将进程插入到就绪队列,等待被调度运行;

终止进程

查找需要终止的进程的 PCB;
如果处于执行状态,则立即终止该进程的执行,然后将 CPU 资源分配给其他进程;
如果其还有子进程,则应将其所有子进程终止;
将该进程所拥有的全部资源都归还给父进程或操作系统;
将其从 PCB 所在队列中删除;

阻塞进程

找到将要被阻塞进程标识号对应的 PCB;
如果该进程为运行状态,则保护其现场,将其状态转为阻塞状态,停止运行;
将该 PCB 插入到阻塞队列中去。

唤醒进程

在该事件的阻塞队列中找到相应进程的 PCB;
将其从阻塞队列中移出,并置其状态为就绪状态;
把该 PCB 插入到就绪队列中,等待调度程序调度;

进程的上下文切换

各个进程之间是共享 CPU 资源的,在不同的时候进程之间需要切换,让不同的进程可以在CPU 执行,那么这个一个进程切换到另一个进程运行,称为进程的上下文切换。

线程

线程是进程当中的一条执行流程

一个进程中可以同时存在多个线程;
各个线程之间可以并发执行;
各个线程之间可以共享地址空间和文件等资源;

当进程中的一个线程崩溃时,会导致其所属进程的所有线程崩溃

线程与进程的比较

进程是资源(包括内存、打开的文件等)分配的单位,线程是 CPU 调度的单位;
进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈;
线程同样具有就绪、阻塞、执行三种基本状态,同样具有状态之间的转换关系;
线程能减少并发执行的时间和空间开销;

线程的上下文切换

线程是调度的基本单位,而进程则是资源拥有的基本单位

当进程只有一个线程时,可以认为进程就等于线程;
当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源,这些资源在上下文切换时是不需要修改的;

调度

非抢占式调度算法挑选一个进程,然后让该进程运行直到被阻塞,或者直到该进程退出,才会调用另外一个进程,也就是说不会理时钟中断这个事情。

抢占式调度算法挑选一个进程,然后让该进程只运行某段时间,如果在该时段结束时,该进程仍然在运行时,则会把它挂起,接着调度程序从就绪队列挑选另外一个进程。这种抢占式调度处理,需要在时间间隔的末端发生时钟中断,以便把 CPU 控制返回给调度程序进行调度,也就是常说的时间片机制。

调度算法

先来先服务:每次从就绪队列选择最先进入队列的进程,然后一直运行,直到进程退出或被阻塞,才会继续从队列中选择第一个进程接着运行

image-20220401163310974.png
image-20220401163310974.png

最短作业优先:优先选择运行时间最短的进程来运行

image-20220401163319307.png
image-20220401163319307.png

高响应比优先:每次进行进程调度时,先计算「响应比优先级」,然后把「响应比优先级」最高的进程投入运行。

image-20220401163019901.png
image-20220401163019901.png

image-20220401163334381.png
image-20220401163334381.png

时间片轮转:每个进程被分配一个时间段,称为时间片(Quantum),即允许该进程在该时间段中运行

image-20220401163345434.png
image-20220401163345434.png

多级反馈队列:
「多级」表示有多个队列,每个队列优先级从高到低,同时优先级越高时间片越短。
「反馈」表示如果有新的进程加入优先级高的队列时,立刻停止当前正在运行的进程,转而去运行优先级高的队列;

image-20220401163408075.png
image-20220401163408075.png

进程通信

管道、消息队列、共享内存、信号量、信号、socket

多线程同步

互斥与同步

同步就好比:「操作 A 应在操作 B 之前执行」,「操作 C 必须在操作 A 和操作 B 都完成之后才能执行」
互斥就好比:「操作 A 和操作 B 不能在同一时刻执行」

锁、信号量

死锁

互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

悲观锁与乐观锁

悲观锁:互斥锁、自旋锁、读写锁

乐观锁

调度算法

进程调度算法

先来先服务调度算法

最短作业优先调度算法

高响应比优先调度算法

时间片轮转调度算法

最高优先级调度算法

多级反馈队列调度算法

内存页面置换算法

最佳页面置换算法(OPT)

置换在「未来」最⻓时间不访问的页面

先进先出置换算法(FIFO)

选择在内存驻留时间很⻓的页面进行中置换

最近最久未使用的置换算法(LRU)

选择最⻓时间没有被访问的⻚面进行置换

时钟页面置换算法(Lock)

当发生缺⻚中断时,算法首先检查表针指向的⻚面:
如果它的访问位位是 0 就淘汰该⻚面,并把新的⻚面插入这个位置,然后把表针前移一个位置;
如果访问位是 1 就清除访问位,并把表针前移一个位置,重复这个过程直到找到了一个访问位为 0 的⻚面为止;

最不常用置换算法(LFU)

当发生缺⻚中断时,选择「访问次数」最少的那个⻚面,并将其淘汰

磁盘调度算法

先来先服务算法

image-20220401165515250.png
image-20220401165515250.png

最短寻道时间优先算法

image-20220401165531953.png
image-20220401165531953.png

扫描算法算法

image-20220401165545352.png
image-20220401165545352.png

循环扫描算法

image-20220401165555526.png
image-20220401165555526.png

LOOK 与 C-LOOK 算法

image-20220401165611895.png
image-20220401165611895.png

image-20220401165625051.png
image-20220401165625051.png

添加新评论

评论列表