结构非常混乱
听说期末考试要把同步互斥那边的例子的 Code 都背下来
lec1 OS overview
操作系统是管理硬件资源
抽象
操作系统内核的特征
单用户系统
简单结构
目标三元组
lec3 ISA TrapCtx & TaskCtx
了解计算机硬件与操作系统的关系
硬件 与 OS 的 边界
了解操作系统与应用程序的关系
系统调用和地址空间
了解操作系统如何隔离与限制应用程序 控制上 数据上 时间上
特权级机制 地址空间 中断处理 破坏隔离
TrapContext 都有哪些内容
什么时候会进行用户栈与内核栈的切换
作业与多道程序
进程的特点
进程 = 程序 + 执行状态
进程状态
lec5 mem
OS 中的内存管理方式
地址生成时机
内存分配方式
栈动态隐式内存分配
malloc free 连续
连续内存分配中的动态分区分配策略
连续内存分配中的伙伴系统
段式存储管理
lec6 vm & replacement
覆盖技术
时间局部性
空间局部性
分支局部性
局部页面置换算法
置换页面的选择范围仅限于当前进程占用的物理页面内
最优页面置换算法 (OPT, optimal) 缺页时
先进先出页面置换算法 (FIFO) 维护一个记录所有位于内存中的逻辑页面链表
最近最久未使用算法 (LRU, Least Recently Used) 缺页时
时钟页面置换算法 (Clock) 各页面组织成环形链表
- 访问位为0
则置换该页, 后访问位置1, 并指针移动到下一个页面, ; - 访问位为1
则访问位置0, 并指针移动到下一个页面, 直到找到可置换的页面, 。
改进的时钟页面置换算法 减少修改页的缺页处理开销
标志位为两位
最不常用置换算法 (LFU, Least Frequently Used ) 缺页时
Belady 现象
期中考完 Update
LFU 那道判断题竟然算没有 Belady 现象 : 明明不恢复计数的会有 , 参见 Reference 的那篇 Blog , 去查卷也没查出个所以然 。 但是成功面到了 rls , 也算值了 :) ,
全局页面置换算法
工作集页面置换算法 全局页面置换算法
常驻集
工作集替换算法
缺页率页面置换算法 缺页率
抖动问题 由于分配给进程的物理页面太少无法包含工作集导致大量缺页而频繁置换
lec7 & 8 scheduler
一个具有一定独立功能的程序在某数据集合上的一次执行和资源使用的动态过程
任务和进程的区别
shell 启动过程
单处理机调度
进程在CPU计算和I/O操作间交替
吞吐量与延迟有 trade off
调度算法
先来先服务调度算法FCFS 依据进程进入就绪状态的先后顺序排列
短作业优先调度算法SJF 选择就绪队列中执行时间最短作业/进程占用CPU进入运行状态
最短剩余时间算法SRT 有新的进程就绪
最高响应比优先算法HRRN 选择就绪队列中响应比R值最高的进程
时间片轮转算法RR 时间片结束时
多级队列调度算法MQ 就绪队列被划分成多个独立的子队列
多级反馈队列调度算法MLFQ 工作进入系统时
实时调度算法
Real-time OS: 正确性依赖于其时间和功能两方面的操作系统
实时操作系统的性能指标
静态优先级调度
动态优先级调度
最低松弛度优先算法
优先级反置
两种解决方案
多处理机调度
SMP是指对称多处理器结构
NUMA 架构为非一致性存储器访问架构
MMP 也被称为海量并行处理架构
单队列多处理器调度 SQMS
多队列多处理器调度 MQMS 每个 CPU 调度相互独立
虽然很有意思但是 Linux 内的调度算法与历史演进过程的三节不考 :)
lec9 fs
文件系统是存储设备上组织文件的方法和数据结构
文件是具有符号名
文件系统的存储视图
文件数据块的分配方式
为了处理大文件
每次读数据需要 Read Inode, Read Data, Write Inode
如果需要创建一个新的 Inode / Data block
多数磁盘划分为一个或多个分区
崩溃一致性问题
文件系统检查程序 fsck 是一种修复方案
数据日志的更新流程
-
日志写入 Journal write
将事务的内容: 包括TxB( 元数据和数据、 写入日志) 等待这些写入完成, 。 -
日志提交 Journal Commit
将事务提交块: 包括TxE( 写入日志) 等待写完成, 事务被认为已提交, committed( ) 。 -
加检查点 Checkpoint
将更新内容: 元数据和数据( 写入其最终的磁盘位置) 。
数据日志的崩溃恢复
- 崩溃发生在Journal Commit完成前
文件系统可以丢掉之前写入的log: 由于磁盘具体位置的bitmap。 inodes, data blocks都没变, 所以可以确保文件系统一致性, 。 - 崩溃发生在Journal Commit后
Checkpoint之前, 文件系统在启动时候: 可以扫描所有已经commited的log, 然后针对每一个log记录操作进行replay, 即recovery的过程中执行Checkpoint, 将log的信息回写到磁盘对应的位置, 这种操作也成为redo logging。 。 - 崩溃发生在Checkpoint完成后
那无所谓: 都已经成功回写到磁盘了, 文件系统的bitmap, inodes、 data blocks也能确保一致性、 。
日志文件系统的性能优化
不同日志模式
Journal Mode: 操作的metadata和file data都会写入到日志中然后提交
lec10 & 11 IPC 线程与协程
进程间通信的定义
进程是资源
- 用户态管理且用户态运行的线程
内核不可见的用户线程( ) - 内核态管理且用户态运行的线程
- 内核态管理且内核态运行的线程
- 双态管理的线程
轻量级进程( LWP, )
相同进程中的线程切换
协程的核心思想
依照三个因素来对协程进行分类
- 控制
控制权( 传递机制) 对称协程: 等价( / 非对称协程) 调用与挂起( ) - 栈式构造
有栈协程 / 无栈协程: - 编程语言中第一类
First-class( 对象) First-class对象 / second-class对象:
需要切换的内容
lec12 同步互斥
临界区(Critical Section) – 访问规则
- 空闲则入
没有线程在临界区时: 任何线程可进入, - 忙则等待
有线程在临界区时: 其他线程均不能进入临界区, - 有限等待
等待进入临界区的线程不能无限期等待: - 让权等待
可选( ) 不能进入临界区的线程: 应释放CPU, 如转换到阻塞状态( )
同步互斥的方法
- 方法1
禁用硬件中断: 进入临界区( 禁止所有中断: 并保存标志, 离开临界区; 使能所有中断: 并恢复标志, ) - 方法2
基于软件的解决方法:
- 方法3
更高级的抽象方法: 锁( 使用 TestAndSet / CaS, 自旋锁或忙等锁 v.s. 等待锁, )
信号量
管程
https://en.wikipedia.org/wiki/Readers–writers_problem#cite_note-3
读者优先
semaphore resource=1;
semaphore rmutex=1;
readcount=0;
/*
resource.P() is equivalent to wait(resource)
resource.V() is equivalent to signal(resource)
rmutex.P() is equivalent to wait(rmutex)
rmutex.V() is equivalent to signal(rmutex)
*/
writer() {
resource.P(); //Lock the shared file for a writer
<CRITICAL Section>
// Writing is done
<EXIT Section>
resource.V(); //Release the shared file for use by other readers. Writers are allowed if there are no readers requesting it.
}
reader() {
rmutex.P(); //Ensure that no other reader can execute the <Entry> section while you are in it
<CRITICAL Section>
readcount++; //Indicate that you are a reader trying to enter the Critical Section
if (readcount == 1) //Checks if you are the first reader trying to enter CS
resource.P(); //If you are the first reader, lock the resource from writers. Resource stays reserved for subsequent readers
<EXIT CRITICAL Section>
rmutex.V(); //Release
// Do the Reading
rmutex.P(); //Ensure that no other reader can execute the <Exit> section while you are in it
<CRITICAL Section>
readcount--; //Indicate that you no longer need the shared resource. One fewer reader
if (readcount == 0) //Checks if you are the last (only) reader who is reading the shared file
resource.V(); //If you are last reader, then you can unlock the resource. This makes it available to writers.
<EXIT CRITICAL Section>
rmutex.V(); //Release
}
写者优先
int readcount, writecount; //(initial value = 0)
semaphore rmutex, wmutex, readTry, resource; //(initial value = 1)
//READER
reader() {
<ENTRY Section>
readTry.P(); //Indicate a reader is trying to enter
rmutex.P(); //lock entry section to avoid race condition with other readers
readcount++; //report yourself as a reader
if (readcount == 1) //checks if you are first reader
resource.P(); //if you are first reader, lock the resource
rmutex.V(); //release entry section for other readers
readTry.V(); //indicate you are done trying to access the resource
<CRITICAL Section>
//reading is performed
<EXIT Section>
rmutex.P(); //reserve exit section - avoids race condition with readers
readcount--; //indicate you're leaving
if (readcount == 0) //checks if you are last reader leaving
resource.V(); //if last, you must release the locked resource
rmutex.V(); //release exit section for other readers
}
//WRITER
writer() {
<ENTRY Section>
wmutex.P(); //reserve entry section for writers - avoids race conditions
writecount++; //report yourself as a writer entering
if (writecount == 1) //checks if you're first writer
readTry.P(); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS
wmutex.V(); //release entry section
resource.P(); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource
<CRITICAL Section>
//writing is performed
resource.V(); //release file
<EXIT Section>
wmutex.P(); //reserve exit section
writecount--; //indicate you're leaving
if (writecount == 0) //checks if you're the last writer
readTry.V(); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading
wmutex.V(); //release exit section
}
保证公平防止饥饿
int readcount; // init to 0; number of readers currently accessing resource
// all semaphores initialised to 1
semaphore resource; // controls access (read/write) to the resource. Binary semaphore.
semaphore rmutex; // for syncing changes to shared variable readcount
semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO)
//READER
reader() {
<ENTRY Section>
serviceQueue.P(); // wait in line to be serviced
rmutex.P(); // request exclusive access to readcount
readcount++; // update count of active readers
if (readcount == 1) // if I am the first reader
resource.P(); // request resource access for readers (writers blocked)
serviceQueue.V(); // let next in line be serviced
rmutex.V(); // release access to readcount
<CRITICAL Section>
//reading is performed
<EXIT Section>
rmutex.P(); // request exclusive access to readcount
readcount--; // update count of active readers
if (readcount == 0) // if there are no readers left
resource.V(); // release resource access for all
rmutex.V(); // release access to readcount
}
//WRITER
writer() {
<ENTRY Section>
serviceQueue.P(); // wait in line to be serviced
resource.P(); // request exclusive access to resource
serviceQueue.V(); // let next in line be serviced
<CRITICAL Section>
// writing is performed
<EXIT Section>
resource.V(); // release resource access for next reader/writer
}
死锁问题 – 必要条件
- 互斥
任何时刻只能有一个进/线程使用一个资源实例: - 持有并等待
进/线程保持至少一个资源: 并正在等待获取其他进程持有的资源, - 非抢占
资源只能在进程使用后自愿释放: - 循环等待
存在等待进程集合: 进程间形成相互等待资源的环,
死锁问题的避免
除了死锁避免算法之外