不知道这些,我都不好意思说学过操作系统

刚好额这学期正在上操作系统这门课

同时我也在准备学习下学期的实习面试了,所以开个专栏,总结下我读操作系统的心得吧~

过程中大量翻阅书籍资料,融合自己的理解,只会让你更懂“Operating System"

Part1_OS简介

全局概述:

在信息化时代,软件被称为计算机系统的灵魂。而作为软件核心的操作系统,已经与现代计算机系统密不可分、融为一体。计算机系统自下而上可粗分为四个部分:硬件、操作系统、应用程序和用户操作系统管理各种计算机硬件,为应用程序提供基础,并充当计算机硬件和用户的中介

硬件,如中央处理器、内存、输入输出设备等,提供了基本的计算资源。应用程序,如字处理程序、电子制表软件、编译器、网络浏览器等,规定了按何种方式使用这些资源来解决用户的计算问题。操作系统控制和协调各用户的应用程序对硬件的使用。

综上所述,操作系统是指控制和管理整个计算机系统的硬件和软件资源,并合理的组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境集合。计算机操作系统是随着计算机研究和应用的发展逐步形成并发展起来的,它是计算机系统中最基本的系统软件

操作系统的结构:

接口:接口就是操作系统编写者为程序员提供的接口,就跟插座一样,你把插头插上去,就能连上电源,操作系统编写者为你提供了一系列接口,可以让你调用,完成你的需求

系统调用:程序分为内核程序和用户程序,操作系统内核程序(如系统启动程序)一般是不会让程序员去动这部分程序的代码的,它只会给你提供接口,由内核程序帮你实现某些功能,而程序员自己的代码如果想动用内核功能,需要通过系统调用去调用设计者给你提供的接口

用户态和内核态:

根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:

  1. 用户态(user mode) : 用户运行的进程或可以直接读取用户程序的数据。
  2. 系统态(kernel mode):内核态程序的进程

我们运行的程序基本都是运行在用户态,在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。

Part2_多进程(线程)

进程与线程的区别:

进程:计算机中特定功能的程序在数据集上的一次运行,如迅雷
线程:线程是进程的一个单元,如使用迅雷下载任务
多线程:一个进程中有多个线程在同时运行,如迅雷下载,迅雷软件的一次运行就是一个进程,那么在迅雷中可以同时下载多个电影,这就是多线程(每一个下载都是一个线程)
Jvm就是多线程的,在我们运行jvm的时候后台会运行垃圾回收的线程,来清理没有被引用的对象。

多进程原理:

在单核CPU的情况下,假想你的CPU只有一个核心,它一次只能处理一个线程

多个进程之间,比如你的迅雷与QQ,可以同步运行,那是怎么做到的呢?那是因为

多进程之间是交替运行的:不同进程争抢CPU资源,进程之间交替获得CPU资源进行自己的操作

多进程状态

在操作系统中,每个进程都会有如下状态

多个进程的切换,对应着多个进程各自状态的切换

  • 创建状态(new) :进程正在被创建,尚未到就绪状态。
  • 就绪状态(ready) :进程已处于准备运行状态,即进程获得了除了处理器之外的一切所需资源一旦得到处理器资源(处理器分配的时间片)即可运行
  • 运行状态(running) :进程正在处理器上上运行(单核 CPU 下任意时刻只有一个进程处于运行状态)。
  • 阻塞状态(waiting) :又称为等待状态,进程正在等待某一事件而暂停运行如等待某资源为可用或等待 IO 操作完成。即使处理器空闲,该进程也不能运行(这种情况可能会造成死锁)。
  • 结束状态(terminated) :进程正在从系统中消失。可能是进程正常结束或其他原因中断退出运行。

进程间的通信:

前面的阻塞态提过,比如两个进程在争求同一个资源的情况下,其中一个进程在等待另一个进程执行完成,才能继续对资源进行操作

那么,等待的进程如何知道另一个进程执行完成?这就是进程间的通信了:执行完相关操作的进程通知等待的进程,可以进行操作了

概念:

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)

信号量通信与进程同步

信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步

进程同步:让多个进程交替执行,实现多进程合作的合理有序

关于信号量:1965年由Dijkstra提出的一种特殊整型变量,信号用来决定进程睡眠(P)还是唤醒(V),量用来记录

在Linux的信号量通信中

  • 初始化信号量为0

  • 进程1执行,发现资源被占用 [此时信号量置为为-1]

  • 进程2执行,发现资源被占用 [此时信号量置为为-2]

总结,非单值信号量用来表示等待进程的个数

为了获得共享资源,进程需要执行下列操作:

为了正确地实现信号量,信号量值的加减操作应当是原子操作。为此,信号量通常是在内核中实现的。

进程调度算法:

进程调度指在CPU空闲的时候,决定允许哪一个进程进来。

  • 先到先服务(FCFS)调度算法 : 从就绪队列中选择一个最先进入该队列的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
  • 短作业优先(SJF)的调度算法 : 从就绪队列中选出一个估计运行时间最短的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
  • 时间片轮转调度算法 : 时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法,又称 RR(Round robin)调度。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。
  • 多级反馈队列调度算法 :前面介绍的几种进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程 。多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。,因而它是目前被公认的一种较好的进程调度算法UNIX 操作系统采取的便是这种调度算法。
  • 优先级调度 : 为每个流程分配优先级,首先执行具有最高优先级的进程,依此类推。具有相同优先级的进程以 FCFS 方式执行。可以根据内存要求,时间要求或任何其他资源要求来确定优先级。

Part3_内存管理

内存管理

操作系统的内存管理主要负责内存的分配与回收

(在C语言中:malloc 函数:申请内存,free 函数:释放内存)

另外地址转换也就是将逻辑地址转换成相应的物理地址等功能也是操作系统内存管理做的事情

几种内存管理机制

简单分为连续分配管理方式非连续分配管理方式这两种。

连续分配管理方式是指为一个用户程序分配一个连续的内存空间,常见的如 块式管理 。同样地,非连续分配管理方式允许一个程序使用的内存分布在离散或者说不相邻的内存中,常见的如页式管理段式管理

  1. 块/区式管理 : 远古时代的计算机操系统的内存管理方式。将内存分为几个固定大小的块,每个块中只包含一个进程。如果程序运行需要内存的话,操作系统就分配给它一块,如果程序运行只需要很小的空间的话,分配的这块内存很大一部分几乎被浪费了。这些在每个块中未被利用的空间,我们称之为碎片
  2. 页式管理 :把主存分为大小相等且固定的一页一页的形式,页较小,相对相比于块式管理的划分力度更大,提高了内存利用率,减少了碎片。页式管理通过页表对应逻辑地址和物理地址。
  3. 段式管理 : 页式管理虽然提高了内存利用率,但是页式管理其中的页实际并无任何实际意义。 段式管理把主存分为一段段的,每一段的空间又要比一页的空间小很多 。但是,最重要的是段是有实际意义的,每个段定义了一组逻辑信息,例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。 段式管理通过**段表**对应逻辑地址和物理地址。
  4. 段页式管理机制:段页式管理机制结合了段式管理和页式管理的优点。简单来说段页式管理机制就是把主存先分成若干段,每个段又分成若干页,也就是说 段页式管理机制 中段与段之间以及段的内部的都是离散的

快表和多级页表

页表的管理机制中有两个很重要的概念:快表和多级页表

上面说过,页式管理通过页表维护逻辑地址和物理地址

页表通常存储在内存中,所以在内存中要维护页表,页表如果过大,必然影响内存空间,内存空间是宝贵的,如果控制页表对内存的占用?

第一种方式:

页表只存放用到的页,但这带来的问题就是,页表中的页号不连续,每次在通过页表的时候,会带来查找(二分查找)操作,这在时间上是不被允许的

第二种方式:多级页表

这是一种很常用且被广泛应用的方式了,页表映射到页表,层层递进,最终映射到物理地址空间上,把避免把全部页表一直放在内存中占用过多空间,特别是那些根本就不需要的页表就不需要保留在内存中

​ 多级页表为何解决的内存?

  • 二级页表可以不存在,只在需要时创建
  • 二级页表可以不在主存,而在硬盘,这是利用了程序的局部性原理

多级页表是一种典型的时间换空间策略!

第三种方式:快表TLB

为了解决虚拟地址到物理地址的转换速度,操作系统在 页表方案 基础之上引入了 快表 来加速虚拟地址到物理地址的转换。我们可以把块表理解为一种特殊的高速缓冲存储器(Cache)

页表的一部分或者全部内容。作为页表的 Cache,提高了访问速率。由于采用页表做地址转换,读写内存数据时 CPU 要访问两次主存。有了快表,有时只要访问一次高速缓冲存储器,一次主存,这样可加速查找并提高指令执行速度

使用快表之后的地址转换流程原理是这样的:

  1. 根据虚拟地址中的页号查快表;
  2. 如果该页在快表中,直接从快表中读取相应的物理地址;
  3. 如果该页不在快表中,就访问内存中的页表,再从页表中得到物理地址,同时将页表中的该映射表项添加到快表中
  4. 当快表填满后,又要登记新页时,就按照一定的淘汰策略淘汰掉快表中的一个页。

虚拟内容(Virtual Memory)

这个在我们平时使用电脑特别是 Windows 系统的时候太常见了。很多时候我们使用点开了很多占内存的软件,这些软件占用的内存可能已经远远超出了我们电脑本身具有的物理内存。为什么可以这样呢?

正是因为 虚拟内存 的存在,通过 虚拟内存 可以让程序可以拥有超过系统物理内存大小的可用内存空间。另外,虚拟内存为每个进程提供了一个一致的、私有的地址空间,它让每个进程产生了一种自己在独享主存的错觉(每个进程拥有一片连续完整的内存空间)。这样会更加有效地管理内存并减少出错。

虚拟内存 使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如 RAM)的使用也更有效率。目前,大多数操作系统都使用了虚拟内存,如 Windows 家族的“虚拟内存”;Linux 的“交换空间”等。From:https://zh.wikipedia.org/wiki/虚拟内存

虚拟内存的实现也是基于程序的局部性原理

页面置换

虚拟内存管理很重要的一个概念就是页面置换算法

地址映射过程中,若在页面中发现所要访问的页面不在内存中,则发生缺页中断

当发生缺页中断时,如果当前内存中并没有空闲的页面,操作系统就必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。用来选择淘汰哪一页的规则叫做页面置换算法,我们可以把页面置换算法看成是淘汰页面的规则(淘汰策略)

  • OPT (最佳页面置换算法) :最佳(Optimal, OPT)置换算法所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。一般作为衡量其他置换算法的方法
  • FIFO(First In First Out) 页面置换算法(先进先出页面置换算法) : 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰。
  • LRU (Least Currently Used)页面置换算法(最近最久未使用页面置换算法) :LRU算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 T,当须淘汰一个页面时,选择现有页面中其 T 值最大的,即最近最久未使用的页面予以淘汰。
  • LFU (Least Frequently Used)页面置换算法(最少使用页面置换算法) : 该置换算法选择在之前时期使用最少的页面作为淘汰页。

Part4_文件管理

磁盘结构

  • 磁盘面(Platter):一个磁盘有多个盘面;

  • 磁道(Track):盘面上的圆形带状区域,一个盘面可以有多个磁道;

  • 扇区(Track Sector):磁道上的一个弧段,一个磁道可以有多个扇区,它是最小的物理储存单位,目前主要有 512 bytes 与 4 K 两种大小;

  • 磁头(Head):与盘面非常接近,能够将盘面上的磁场转换为电信号(读),或者将电信号转换为盘面的磁场(写)

  • 制动手臂(Actuator arm):用于在磁道之间移动磁头

  • 主轴(Spindle):使整个盘面转动

磁盘调度算法

读写一个磁盘块的时间的影响因素有:

  • 旋转时间(主轴转动盘面,使得磁头移动到适当的扇区上)
  • 寻道时间(制动手臂移动,使得磁头移动到适当的磁道上)
  • 实际的数据传输时间

其中,寻道时间最长,因此磁盘调度的主要目标是使磁盘的平均寻道时间最短

以下罗列相关的磁盘调度算法

  • FCFS, First Come First Served:按照磁盘请求的顺序进行调度,因为未对寻道做任何优化,使平均寻道时间可能较长

  • SSTF, Shortest Seek Time First(最短寻道时间优先):优先调度与当前磁头所在磁道距离最近的磁道,虽然平均寻道时间比较低,但是**不够公平。如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象。**具体来说,两端的磁道请求更容易出现饥饿现象

  • 电梯算法:电梯总是保持一个方向运行,直到该方向没有请求为止,然后改变运行方向

    电梯算法(扫描算法)和电梯的运行过程类似,总是按一个方向来进行磁盘调度,直到该方向上没有未完成的磁盘请求,然后改变方向

    因为考虑了移动方向,因此所有的磁盘请求都会被满足,解决了 SSTF 的饥饿问题

Part5_IO管理

[待更新…]

原创文章 197 获赞 142 访问量 6万+

猜你喜欢

转载自blog.csdn.net/JunSIrhl/article/details/105777622