1 计算机体系
存储器的层次结构与高速缓存
当存储器的层次结构满足以下条件时:
a 容量递增
b 存取时间递增
c 访问频率递减
注:条件c有效的基础是访问的局部性原理
可以发现,总的平均存取时间更接近于第一级存储器的存取时间而不是第二级存储器的存取时间。
这种发现同样适用于缓存系统的设计中,其中,保证缓存的高频访问是主要原则
关于访问的局部性
局部性通常有两种形式:
时间局部性(temporal locality)
时间局部性指的是:被引用过一次的存储器位置在未来会被多次引用(通常在循环中)。
空间局部性(spatial locality)
如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。
假如, 有95%的存储器存取发生在缓存中,访问缓存0.1ms,访问硬盘1ms,则访问一个字节的平均存取时间可表示为:
0.950.1+0.05(1+0.1)=0.095+0.055=0.15ms
缓存系统的两个目标:
1 重复利用未过期的缓存数据,降低磁盘io次数;
2 由于数据访问的局部性现象,一次读取一块连续的数据以满足一次存储器访问时,很可能仅仅这的多次访问的数据都是该块中的其他字节,这样也可降低磁盘io次数;
缓存系统的设计
1 缓存的大小
2 块(交换数据)大小
3 映射函数
4 置换算法,如LRU
5 写策略(缓存内的数据被修改,需要回写保存)
6 缓存的级数
数据访问的局部性原理是保证缓存命率的重要基础,如果没有缓存的高命中率,则这个缓存系统是不成功的。
IO操作
可编程IO
CPU直接与IO模块进行交互,并等待IO模块处理完成,在此期间,处理器必须不断询问IO模块的状态,严重降低了CPU的利用率;
中断驱动IO
由处理器给IO模块发送IO命令,然后处理器继续做其他工作。当IO模块准备好与处理器交换数据时,发送中断处理信号给CPU。CPU接收到中断信号后开始与IO模块进行数据传送,然后恢复处理器之前的执行过程。
多中断的处理方式:
- 顺序(排队)
- 优先级(插队)
直接内存存取DMA
上述两种方式的数据传送都依赖于CPU,因此它们有两个固有的缺陷:
1 IO传送速度受限于处理器提供服务的速度;
2 处理器忙于管理IO传送的工作,必须执行很多的指令以完成IO传送;
当需要移动大量数据时,需要使用一种更为有效的技术,DMA.DMA可以代替CPU完成IO的读写工作。当CPU需要读或写一块数据时,它可以给DMA产生一条命令,之后处理器继续其他工作,DMA负责直接与存储器交互,完成IO动作。当传送完成后,DMA模块发送一个中断信号给CPU。因此,只有在开始传送和传送结束后处理器才会参与。
DMA模块需要控制总线以便与存储器进行数据传送,这可能与CPU形成总线争用导致CPU执行速度变慢(但这不是中断,不会发生CPU上下文切换),但尽管如此,对于多字IO传送来说,DMA比上面两种IO方式更有效。
2 操作系统概述
操作系统需要的必要条件:
- CPU从内存的不同部分取指的能力;
- 内存保护:防止用户程序改变包含操作系统程序的内存区域;
- 定时器:防止用户程序独占CPU,保证操作系统重新获得控制权;
- 特权指令:特权指令只能由操作系统执行;
- 中断:提高操作系统让用户程序放弃控制权或从用户程序获得控制权时的灵活性;
多任务操作系统的必要条件:内存管理、调度管理
多用户操作系统的必要条件:信息保护和安全
内存管理的五个任务:
- 进程隔离
- 自动分配的管理
- 支持模块化程序设计
- 保护和访问控制
- 长期存储
信息保护和安全的四个任务:
- 可用性,保护系统不被打断;
- 保密性,保证用户不能督导未授权访问的数据;
- 数据完整性,保护数据不被未授权的修改;
- 认证,身份认证与识别;
调度和资源管理的任务:
- 调度公平性
- 有差别的响应
- 有效性
3 进程
进程的状态模型
进程组成
进程由用户程序、用户数据、系统栈、进程控制块组成;
进程切换
进程切换也叫进程上下文切换,工作量较大
进程切换的时机:中断(时钟中断、I/O中断、内存失效)、陷阱及系统调用
进程的切换步骤:
保存处理器上线文环境,包括程序计数器和其他寄存器;
更新当前运行态进程的进程控制块,包括将进程的状态改变到另一状态(就绪态、阻塞态或退出态)。还必须更新其他相关域,包括离开运行态的原因和记账信息。
将进程的进程控制块移到相应的队列(就绪、在事件i处阻塞、就绪/挂起)
选择另一个进程执行。
更新所选择进程的进程控制块,包括将进程状态变为运行态。
更新内存管理的数据结构,这取决于如何管理地址转换。
恢复处理器在被选择的进程最近一次切换出运行态时的上线文环境。
用户进程与系统进程的三种关系模型
- 分离的内核
- 在用户进程中执行操作系统程序(UNIX)
- 操作系统进程作为分离的进程执行
模式切换
模式的切换在中断处理阶段完成。
进程的切换在中断、陷阱或系统调用时发生。
在用户进程与系统进程一体的进程模型下,相比于进程切换,模式切换开销更低。
4 线程
线程分类
用户级线程:由一个在进程的用户空间中运行的线程库创建并管理,用户级线程对操作系统是未知的。用户级线程是非常高效的,因为从一个线程切换到另一个同进程的线程不需要进行状态转换(模式切换)。但是,一个进程中一次只能有一个用户级线程可以执行,如果一个线程发生阻塞,整个进程的多个线程都会被阻塞。
内核级线程:进程内包含的内核级线程由内核维护,由于内核认识它们,因而同一个进程中的多个线程可以在多个处理器上并行执行。一个线程的阻塞不会阻塞整个进程的线程,但当一个线程切换到另一个线程时就需要进行模式转换。
Linux的线程
Linux其实本事没有线程的概念,只是为了迎合开发者的需要而使用了一个所谓轻量级进程(POSIX线程),你从这两者区别也可以发现,轻量级进程最大的用途在于可以共享一些资源,如地址空间,打开文件。所以,事实上Linux实现多线程应用程序的方式就是用轻量级进程来代替线程。
虽然Linux中线程没有单独的数据结构,进程和线程差别也不大,但是进程在切换的时候要切换地址空间,而线程在切换的时候判断一下是不是在一个进程组,如果属于一个进程组,只是切换一下上下文而已,所以开销要小的多
并发:互斥和同步
并发关键词
原子性操作:操作不可中断、不可分割性,该操作要么执行完成,要么不执行;
临界资源:是一种共享资源,会被多个进程或线程使用;
临界区:是一段代码,这段代码会对临界资源进行读写,临界区是互斥的,也就是如果一个进程处于临界区时,其他进程是不能执行临界区代码的;
竞争条件:多个进程或者线程同时读或者写共享数据时,最终的结果依赖于多个进程的执行顺序的情况,称为竞争条件;
互斥
硬件支持:中断禁用、专用机器指令:CAS
信号量
信号量
二元信号量
自旋锁
管程
消息传递
读写者问题
并发:死锁和饥饿
死锁的检测方法
假设有i个进程P(1..i),有m个资源R(1..m),我们使用R(im)表示进程i请求的资源,使用Q(im)表示已分配给进程i的资源,使用V(m)表示剩余的资源。则可以:
1 在Q(im)矩阵中,找出一个未分配任何资源的进程Pi,并标记该进程;
2 初始化一个临时向量W,令W等于V向量;
3 在R(im)矩阵中,查找下标i,使进程i当前未标记且R的第i行小于等于W,如果找不到这样的行,终止算法;
4 如果找到这样的行,标记进程i,并把Q矩阵中的第i行加到W中,令Wk=Q(ik)+Wk。返回步骤3
当且仅当这个算法最后结果有未标记的进程时,表明存在死锁。
死锁的恢复方法
取消所有死锁的进程,撤销存在死锁的进程的资源。
银行家算法
与死锁的检测方法类似。又叫资源分配拒绝策略,通过该算法检测到请求的资源会导致死锁时,则拒绝资源分配请求。
哲学家就餐问题
解决方案:
不影响并发的情况下:
1 增加总资源:增加5套叉子
2 降低资源需求:教会哲学家只使用一支叉子吃饭
降低并发的情况下:
1 一次只允许(N-1)个人吃饭,剩下的一个人等待直到有人吃完;
2 引入服务员,由服务员决定是否可以获得叉子;
3 把筷子两两分对,哲学家一次获取一双;
内存屏障
解决编译器及处理器的指令重排问题,禁止指令重排
针对编译器及处理器的指令:
mb() 读写指令 内存屏障,,保证代码mb()之前的任何读写操作无法穿透屏障
rmb() 读取指令 内存屏障,保证代码rmb()之前的任何读操作无法穿透屏障
wmb() 写指令内存屏障,保证代码wmb()之前的任何写操作无法穿透屏障
针对编译器的指令:
barrier() 更轻量级,是mb()的简化版,仅控制编译器的行为。若确认处理器不会进行重排,则可以使用这个操作。
5 内存管理
5.1 内存管理的目标
重定位
保护
共享
5.2 内存管理相关技术
5.2.1内存分区
- 固定分区,有内部碎片,但简单
- 动态分区,有外部碎片,需要压缩,无内部碎片
- 伙伴系统,动态二分,动态合并,属于一种折中方案
放置算法
固定分区:由于其分区大小相同,仅需要找到可用的分区即可;
动态分区:有三种算法,1最佳适配,寻找差距最小的分区; 2 首次适配,第一个找到的可用的分区 ;3 下次适配,从上次放置位置开始扫描内存,找到可用分区;
其中首次适配效率最好,最佳适配会产生大量及其微小的碎片,需要频繁压缩内存。下次适配则会将分配几种与内存的末端空间,导致这里出现大量碎片。
5.2.2 重定位
解决进程在被换出之后再次换入内存后物理地址发生变化后,不会影响处理器的访问。重定位技术还能通过界限寄存器对内存访问进行保护。
逻辑地址:处理器使用的地址,不会随着进程的换入换出而改变;
物理地址:进程在内存中的实际地址,会随着进程的换入换出而改变;
分页
5.2.3 分页
内存被划分为大小固定的相等的块,且块相对比较小,每个进程也被分成同样大小的块,进程中的块成为页(page),内存中的块成为页框(frame);页可以被装载入页框中。
分页技术没有外部碎片,且仅在进程最后一个块中产生微小的内部碎片。
为了知道程序在哪些frame中,操作系统会为每个进程维护一个页表(page table)。页表给出了每个进程的每一页所对应的frame的位置。
在程序中每一个逻辑地址包括两部分:页号和偏移量
5.2.4 分段
分段技术通过把程序及其相关的额数据划分为几个不同的段(segment),可以对他们进行不同的权限控制(只读、只执行),段的大小是动态的,分段类似于动态分区。和分页一样,采用分段技术时的逻辑地址也是两部分:段号和偏移量
5.3.5 缓冲区溢出攻击
缓冲区溢出又称内存越界。
缓冲区溢出攻击,是通过恶意覆盖程序中缓冲区界限之外的内存部分,植入恶意代码。
6 虚拟内存
实存
实际的内存,称为实存
虚存
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换
系统抖动
系统为了读入新的页而换出了即将会用的旧的页,系统频繁的换页导致系统利用率急剧降低的情况,称为系统抖动
驻留集
程序驻留在内存中的部分,称为驻留集