第4周 星期二 第2大节
- 视频:
screen_操作系统与分布式计算_第4周_星期二_第2大节.mp4 - 字幕:
transcripts/第4周_星期二_第2大节.srt
时间轴
[03:10]检查作业:Linux调度策略(学生回答CFS、实时FIFO/RR/Deadline)[14:23]线程概念引入:TCB、线程组成[17:31]线程优势:开销小、切换快、通信效率高、并发度高[23:08]用户级线程 vs 内核级线程 vs 混合实现[28:19]并发执行的同步与互斥问题[56:01]同步(直接制约)vs 互斥(间接制约)[01:06:28]生产者-消费者问题(链表buffer数据丢失)[01:14:37]临界资源CR与临界段CS概念[01:20:22]软件互斥:Dekker算法→Peterson算法[01:45:03]硬件方法:关中断、TestAndSet、Swap[01:54:35]信号量机制(Dijkstra):P/V操作[02:10:00]课堂练习:S1~S7任务图PV同步设计
Linux调度策略复习
- Linux调度分三类:普通调度(CFS完全公平调度,基于红黑树+vruntime,始终选vruntime最小进程执行)、实时调度(FIFO先进先出、RR时间片轮转、Deadline明确时间约束)、扩展调度(标志位配合使用)
- CFS虚拟化CPU:假设N个进程,每个分得1/N资源,vruntime增长速率受优先级影响
- 实时调度策略均为静态优先级
- Deadline可与其它调度策略配合使用,整体非常灵活
线程概念
- 线程提出目的:让CPU并行粒度更细,进程间并行粒度太大→同一进程内部不同任务也可并行
- 线程与进程是包含关系:每个线程从属于一个进程,一个进程可有多个线程
- TCB(线程控制块):记录线程所属进程ID、运行现场数据保护恢复、寄存器组、程序计数器、工作区(参数传递等)
- 同进程内线程共享进程的PCB、程序数据、地址空间、资源分配
线程优势
- 开销小:切换时保护恢复的信息量比进程小得多
- 切换快:上下文信息少,同进程内线程切换尤其快(不同进程的线程切换退化为进程切换)
- 通信效率高:同进程线程共享地址空间,通过共享内存直接通信
- 并发度高:一个进程内部可多个线程并发
线程 vs 进程比较
| 进程 | 线程 | |
|---|---|---|
| 地址空间 | 独立地址空间 | 共享所属进程地址空间 |
| 资源分配 | 以进程为单位 | 线程体量很小 |
| 切换开销 | 上下文切换信息量大,开销大 | 同进程内切换只需切换线程部分资源 |
| 安全性 | 进程间相互独立 | 同进程线程可修改彼此数据,需保证一致性 |
用户级线程 vs 内核级线程 vs 混合
- 用户级线程:操作系统仍以进程管理,线程在用户空间实现,调度由应用程序自己完成,OS不参与
- 内核级线程(Windows/Linux等主流):OS层面按线程粒度调度CPU,提供线程相关API直接调用
- 混合实现(如Solaris):用户级与内核级两种层面都支持,融合两者优点
并发程序设计的三种方法
- 自动识别:写顺序程序,工具自动分析代码中可并行部分,OS利用进程/线程并发执行
- 并行程序设计语言:语言语法直接表达并行,编译系统映射到进程/线程
- 传统语言+操作系统API(重点):利用OS提供的并发机制(fork等),在串行语言中实现并发
parbegin/parend 伪代码
parbegin和parend之间的任务可以并发执行- 例如 S1和S2可并发,之后执行S3:
parbegin S1, S2 parend; S3 - 优点:结构化特征好,清楚表明哪些模块可并发
- 缺点:无法描述并发任务之间的优先/同步关系(复杂任务图需用信号量)
fork/exit/wait 系统调用
- fork:创建子进程,复制父进程的data、code、战区等内存映像到子进程。父进程和子进程从同一点(fork返回处)继续执行。返回值为子进程PID(父进程看到)或0(子进程看到)
if (pid > 0)父进程执行代码;if (pid == 0)子进程执行代码
- exit:结束进程
- wait/waitpid:进程间消息传递,父进程等待子进程结束,
waitpid可指定等待特定进程
并发执行的同步与互斥
- 并发任务带来两个问题:同步(Synchronization)和 互斥(Mutual Exclusion)
同步 vs 互斥
- 同步(直接制约):为共同完成同一任务,伙伴进程间需要在某些位置协调工作先后顺序,传递信息产生的制约关系。例如S3必须在S1和S2完成后才能执行
- 互斥(间接制约):进程竞争使用独占资源(如打印机、共享变量、缓冲区)产生的制约关系。进程间本身不需要协作,因竞争同一资源而被迫等待
临界资源CR与临界段CS
- 临界资源 CR(Critical Resource):一次仅允许一个进程使用的资源,如打印机、共享变量、缓冲池
- 临界段 CS(Critical Section):各进程必须互斥执行的程序段,即访问临界资源的代码段
- 临界区访问四准则:
- 互斥使用:同一时刻只能有一个进程在临界区
- 让权等待:等待进入临界区的进程必须释放CPU,将自己阻塞
- 有空让进:临界区外运行的进程不能阻止其他进程进入临界区(临界区空时任何进程有权申请)
- 有限等待:不应使要进入临界区的进程无限期等待
生产者-消费者问题
- 抽象:往buffer写数据的进程=生产者,从buffer读数据的进程=消费者
- 共享数据:链表表头指针first(producer插入新节点时修改first,consumer取数据时也修改first)
- 若不互斥:producer和consumer并发访问first指针,数据可能丢失(新节点未正确插入就被覆盖)
- 典型的一类互斥问题
软件互斥方法
软件实现需额外加入entry code和exit code控制临界区互斥访问,不能假设硬件指令、处理机数目、进程相对速度。
简单turn令牌算法(失败)
- 定义全局变量turn(0或1),turn=0表示P0可进入,turn=1表示P1可进入
- 问题:P0不想进入时P1也无法进入(违反有空让进);进程在CS内失败时其他进程无限等待
Dekker算法演进
- 改进一(flag数组):flag[0]/flag[1]表示各自对CS的使用情况。先检测对方flag再进入
- 问题:同时检测到CS为空,两个进程都进入(违反互斥)
- 改进二(先举手先声明):先置flag为true表明意愿,再检测对方flag
- 问题:双方同时举手,谁也进不去(违反有空让进)
- 最终Dekker算法:融合turn令牌 + flag数组(举手示意)
- 先举手(flag=true),如果有意愿且令牌给对方,则放手(flag=false)等待令牌变回来
- 正确解决互斥,满足所有准则
Peterson算法
- 代码比Dekker更简洁,思想类似,结合turn和flag实现
硬件方法
-
关中断(disable/enable interrupt)
- 原理:CPU调度发生在中断时,关中断后不会发生进程切换
- 缺点:限制CPU并发能力;上层应用若关中断可能忘开;多CPU系统失效(其他核仍可运行)
-
TestAndSet 指令
- 硬件原子指令:读取lock值到rv,将lock置为true,返回rv
while TestAndSet(lock)忙等,直到lock为false才进入CS,退出时置lock=false
-
Swap 指令
- 硬件原子指令:交换两个变量的值
- 局部变量key=true,
while (key) swap(lock, key)忙等,lock被释放时key变为false则进入CS,退出时lock=false
信号量机制(Dijkstra)
- 信号量:特殊数据结构,专门用于实现进程同步和互斥,代表需要互斥访问的共享资源
- 信号量的值只能通过 P/V原语操作 改变
P操作(申请资源)
P(S) {
S--;
if (S < 0) 将当前进程放入阻塞队列;
}V操作(释放资源)
V(S) {
S++;
if (S <= 0) 从阻塞队列唤醒一个进程到就绪队列;
}信号量类型
| 类型 | 用途 | 初值 |
|---|---|---|
| 公用信号量 | 进程间互斥(代表临界资源) | 1 |
| 私有信号量 | 进程内同步(进程内部任务间) | 0 或 N |
互斥模式(P和V在同一进程)
P(mutex); // 进入CS前申请
CS;
V(mutex); // 退出CS后释放同步模式(P和V在不同进程)
// P1进程 // P2进程
S1; P(sync);
V(sync); S2;- 同步信号量初值=0
- P1执行完S1后V(sync)通知P2,P2在S2前P(sync)等待
S1~S7任务图PV同步设计(课堂练习)
任务依赖关系:
- S1→S2→S4→S5→S7(串行主线)
- S1完成后可并行执行S3
- S3完成后可执行S6
- S5和S6都完成后才能执行S7
方案一(三个进程):
- P1进程:S1, S2, S4, S5, S7(顺序执行)
- P2进程:S3(与P1中的S2并发)
- P3进程:S6(与P1中的S5并发)
同步点及信号量设计:
sync1:S1→S3(P1中S1后V(sync1),P2中S3前P(sync1))sync2:S3→S6(P2中S3后V(sync2),P3中S6前P(sync2))sync3:S6→S7(P3中S6后V(sync3),P1中S7前P(sync3))- 所有同步信号量初值=0
也可将S3和S6合并到一个进程(两进程方案),体现多种划分可能
信号量底层实现要点
- P操作若资源不可用,将进程挂入阻塞队列并让出CPU(不是忙等)
- V操作从等待队列唤醒进程到就绪队列
- PV操作本身的互斥通过屏蔽中断或硬件加锁实现
- 信号量数据结构包含:整型value + 等待队列指针
考勤/签到/小测
- 点名:曹凯琪、黄康、李毅佳、梅智轩、周丁男、杜春雨、杨寿辉、曾建成
- 缺勤率高被指出
- 下节课上机安排(地点在乐学平台公布)
作业
- 课外作业:调研Linux调度策略(已检查)
考试/复习重点
- 同步 vs 互斥区别(直接制约 vs 间接制约)
- 临界区访问四准则
- Dekker算法、Peterson算法
- P/V操作原语(互斥模式与同步模式的区别)
- 信号量解决生产者-消费者、任务图同步问题
其他需要回看的片段
[01:06:28]生产者-消费者数据丢失问题(链表first指针互斥)[01:54:35]信号量P/V操作讲解[02:10:00]S1~S7任务图PV练习(三种同步信号量设计)
省流
- 线程概念(TCB/共享进程资源/优势) + 并发同步互斥问题(同步=直接制约协同,互斥=间接制约竞争) + 三种互斥机制(软件Dekker→Peterson/硬件关中断TAS Swap/信号量PV),重点:P/V操作原语、信号量解决同步互斥、S1~S7任务图PV设计