大内核和微内核
1.大内核
大内核是将操作系统功能作为一个紧密结合的整体放到内核
由于各模块信息共享,因此有很高的性能。
2. 微内核
由于操作系统不断复杂,因此将操作系统一部分功能移出内核,从而降低内核的复杂性。移出的部分根据分层的原则划分成若干服务,相互独立。
在微内核结构下,操作系统被划分成小的、定义良好的模块,只有微内核一个模块运行在内核态,其余模块运行在用户态。
因为需要频繁地在用户态和内核态之间切换,所以有一定的损失。
进程与线程
进程
进程是资源分配的基本单元。
进程控制块(Process Control Block,PCB)描述进程的基本信息和运行状态,所谓的创建进程和销毁进程都是对PCB的操作。
下图显示了 4 个程序创建了 4 个进程,这 4 个进程可以并发地执行。
2.线程
线程是独立调度的基本单元
一个进程种有多个线程,它们可以共享资源。
QQ和浏览器是两个进程,浏览器进程里有很多线程,例如HTTP请求线程、事件响应线程、渲染线程等等,线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件。
3.区别
1)拥有资源
进程是资源分配的基本单元,但线程不拥有资源,线程可以访问隶属进程的资源。
2)调度
线程是独立调度的基本单元,同一进程种,线程的切换不会引起进程的切换,从一个进程中的线程切换到另一个进程的线程,会引起进程切换。
3)系统开销
由于创建和销毁进程时,系统都要为之分配或回收资源,例如内存空间,I/O设备,多付出的开销远远大于创建和销毁线程时的开销。类似地,在进程切换时,涉及当前进程CPU环境的保存及新调度进程CPU环境的设置,而线程只需要保存和设置少量寄存器。
4)通信方面
线程间的通信可以直接读取同一进程中的数据进行通信,但是进程通信需要借助IPC。
进程状态切换
应该注意:
- 只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
- 阻塞状态是缺少所需要的资源从而由运行状态转换而来,但该资源不包括CPU资源,缺少CPU时间会从运行转换成就绪。
进程调度算法
不同操作系统调度算法目标不同
1.批处理系统
批处理系统没有太多的用户操作,其调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)
1.1先来先服务first come first serverd(FCFS)
非抢占式的调度算法,按照请求的顺序进行调度。
有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。
1.2短作业优先shortest job first(SJF)
非抢占式的调度算法,按估计运行时间最短的顺序进行调度。
长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。
1.3最短剩余时间优先shortest remaining time next(SRTN)
最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。
2. 交互式系统
交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。
2.1 时间片轮转
将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。
时间片轮转算法的效率和时间片的大小有很大关系:
- 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。
- 而如果时间片过长,那么实时性就不能得到保证。
2.2 优先级调度
为每个进程分配一个优先级,按优先级进行调度。
为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。
2.3多级反馈队列
一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。
多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,..。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次。
每个队列优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列上的进程。
可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合。
实时系统
实时系统要求一个请求在一个确定时间内得到响应。
进程通信
进程同步和进程通信很容易混淆,它们的区别在于:
进程同步:多个进程按一定顺序执行
进程通信:进程间传输信息
进程通信是一种手段,进程同步是一种目的。也可以说,为了可以达到进程同步,需要在进程之间传递一些必要的信息。
1. 管道
通过调用pipe()函数创建,fd[0]用于读,fd[1]用于写,
它具有以下限制:
- 只支持半双工通信
- 只能在父进程或兄弟进程之间通信
2.FIFIO
也称为命名管道,去除了管道只能在父子进程中使用的限制,
FIFO常用于客户-服务应用程序中,FIFO用作汇聚点,在客户进程和服务进程之间传递数据。
3.消息队列
相比于 FIFO,消息队列具有以下优点:
- 消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;
- 避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;
- 读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收。
4. 信号量
它是一个计数器,用于为多个进程提供对共享数据对象的访问。
5. 共享存储
允许多个进程共享一个给定的存储区。因为数据不需要在进程之间复制,所以这是最快的一种 IPC。
需要使用信号量用来同步对共享存储的访问。
多个进程可以将同一个文件映射到它们的地址空间从而实现共享内存。另外 XSI 共享内存不是使用文件,而是使用内存的匿名段。
6. 套接字
与其它通信机制不同的是,它可用于不同机器间的进程通信。
虚拟内存
虚拟内存的目是为了让物理内扩充成更大的逻辑内存,从而让程序获得更多可用的内存。
为了更好的管理内存,操作系统将内存抽象成地址空间。每个程序拥有自己的地址空间,这个地址空间被分割成多个块,每一块称为一页。这些页被映射到物理内存,但不需要映射到连续的物理内存,也不需要所有页都必须在物理内存中。当程序引用到不在物理内存中的页时,由硬件执行必要的映射,将缺失的部分装入物理内存并重新执行失败的指令。
从上面的描述中可以看出,虚拟内存允许程序不用将地址空间中的每一页都映射到物理内存,也就是说一个程序不需要全部调入内存就可以运行,这使得有限的内存运行大程序成为可能。例如有一台计算机可以产生 16 位地址,那么一个程序的地址空间范围是 0~64K。该计算机只有 32KB 的物理内存,虚拟内存技术允许该计算机运行一个 64K 大小的程序。
分页系统地址映射
内存管理单元(MMU)管理着地址空间和物理内存的转换,其中的页表(Page table)存储着页(程序地址空间)和页框(物理内存空间)的映射表。
一个虚拟地址分成两个部分,一部分存储页面号,一部分存储偏移量。
下图的页表存放着 16 个页,这 16 个页需要用 4 个比特位来进行索引定位。例如对于虚拟地址(0010 000000000100),前 4 位是存储页面号 2,读取表项内容为(110 1),页表项最后一位表示是否存在于内存中,1 表示存在。后 12 位存储偏移量。这个页对应的页框的地址为 (110 000000000100)。
页面置换算法