cswork / OA打开练习工作台

OA 计算题 · 逐步模拟

手算题,先让模拟器走一遍。

OA 的 CS 选择题常要手算:平均等待时间、缺页次数、安全序列、cwnd、握手时的 seq 和 ack。这六个模拟器一步一步算给你看,每个都能换成题目里的数据,用来核对你的手算。

CPU 调度:画甘特图,算平均等待时间

OA 常给三五个进程的到达时间和运行时间,问某种调度算法下的平均等待或周转时间。在输入框里换算法(fcfs、sjf、srtf、rr 加时间片、prio、prio-p)或换进程,逐段看为什么轮到这个进程。

交互演示 · 逐步观察

CPU 调度 · 甘特图

时间片轮转 RR q=2:平均等待时间是多少?

换个输入
当前处理已发现 / 已计算答案
就绪队列(进程:剩余时间)
空
A
到达 0 · 运行 5
B
到达 1 · 运行 3
C
到达 2 · 运行 1
D
到达 3 · 运行 2

时间片轮转 RR q=2:4 个进程。每一格是 CPU 上连续运行的一段,格子下方是起止时刻。

始终成立周转 = 完成 − 到达,等待 = 周转 − 运行时间,响应 = 第一次上 CPU − 到达。约定:同时到达按输入顺序;优先级数字越小越优先;RR 中同一时刻新到达的进程排在刚用完时间片的进程前面。

页面置换:数缺页次数

默认的访问序列用 FIFO 时,3 个页框缺页 9 次,4 个页框反而缺页 10 次,这就是 Belady 异常。换成 lru、opt 或 clock 对比;最后一步列出四种算法的缺页数和 1 到 7 个页框的缺页曲线。

交互演示 · 逐步观察

页面置换 · 数缺页

3 个页框,用 FIFO 置换,访问 1 2 3 4 1 2 5 1 2 3 4 5 一共缺页几次?

换个输入
1#1
2#2
3#3
4#4
1#5
2#6
5#7
1#8
2#9
3#10
4#11
5#12
F1
F1
F1
F1
F1
F1
F1
F1
F1
F1
F1
F1
F2
F2
F2
F2
F2
F2
F2
F2
F2
F2
F2
F2
F3
F3
F3
F3
F3
F3
F3
F3
F3
F3
F3
F3
当前处理已发现 / 已计算答案
缺页
0
命中
0

3 个页框,开始都是空的。第一行是访问序列,下面每行是一个页框,每一列是访问完这一页之后的内存。

始终成立FIFO 换出最早装入的页;LRU 换出最久没访问的页;OPT 换出下次访问最晚的页;Clock 给每页一个访问位(装入或命中时置 1),缺页时指针转圈,把 1 清成 0,换出第一个为 0 的页。LRU 和 OPT 是栈算法,页框越多缺页不会越多;FIFO 和 Clock 不是,会出现 Belady 异常。

银行家算法:找安全序列

先算 Need = Max − Allocation,再用 Work 一轮轮找能运行完的进程。带上请求(如 P1 1 0 2)时,先检查它是否超过 Need 和 Available,再试分配并做安全检查。

交互演示 · 逐步观察

银行家算法 · 安全序列

P1 请求 (1, 0, 2),能批准吗?

换个输入
P0Need
7A
4B
3C
P1Need
1A
2B
2C
P2Need
6A
0B
0C
P3Need
0A
1B
1C
P4Need
4A
3B
1C
当前处理已发现 / 已计算答案
安全序列(已找到的部分)
空
Available
(3, 3, 2)
Work
—
请求
P1 (1, 0, 2)

每行是一个进程的 Need = Max − Allocation,也就是它还要多少 A、B、C 资源才能运行完。Available = (3, 3, 2)。

始终成立每轮从 P0 开始扫描,选第一个 Need ≤ Work 的进程,它运行完把 Allocation 还回来:Work += Allocation。所有进程都能完成才是安全状态。请求先要满足 Request ≤ Need 和 Request ≤ Available,再试分配并做安全检查。安全序列可以不止一个,这里按"从 P0 扫描"的约定给出一个。

TCP 三次握手与四次挥手

每一步的 seq、ack 和两端状态都画在时序图上。场景可以换成 syn-loss(第一个 SYN 丢失后重传)或 simul-close(双方同时关闭,经过 CLOSING)。

交互演示 · 逐步观察

TCP 连接 · 握手与挥手

三次握手和四次挥手时,seq、ack 和两端状态怎样变化?

换个输入
CCLOSEDSLISTEN
当前处理已发现 / 已计算答案
客户端
CLOSED
服务器
LISTEN
本步报文
—

服务器先被动打开,进入 LISTEN;客户端在 CLOSED。初始序号:客户端 x = 100,服务器 y = 300。

始终成立C 是客户端,S 是服务器,从上往下是时间。SYN 和 FIN 各占一个序号,所以确认它们的 ack 是对方 seq + 1;ack 总是“下一个想收到的序号”。主动关闭的一方最后进入 TIME_WAIT,等 2MSL 才关闭。

拥塞控制:cwnd 曲线

给出初始 ssthresh、轮数,以及哪一轮超时(timeout)或收到 3 个重复 ACK(dup),逐轮算出 cwnd。Reno 收到 3 个重复 ACK 时,这里按国内教材的简化把 cwnd 设为新的 ssthresh;RFC 5681 的快恢复先设为 ssthresh + 3。

交互演示 · 逐步观察

拥塞控制 · Reno 的 cwnd 曲线

初始 ssthresh = 8,每轮的 cwnd 是多少?

换个输入
ssthresh1
1#1
当前处理已发现 / 已计算答案
cwnd
1
ssthresh
8
阶段
慢启动
轮次
1 / 20

第 1 轮:cwnd = 1 < ssthresh = 8,慢启动,每轮翻倍,下一轮 2。

始终成立cwnd 从 1 开始;小于 ssthresh 时慢启动,每轮翻倍但不超过 ssthresh;达到 ssthresh 后拥塞避免,每轮加 1。超时:ssthresh = max(⌊cwnd/2⌋, 2),cwnd = 1。3 个重复 ACK:Tahoe 同超时;Reno 按教材简化取 cwnd = 新 ssthresh(RFC 5681 是 ssthresh + 3 进入快恢复)。绿线是 ssthresh,红点是出事件的那一轮。

滑动窗口:GBN 与 SR

同样丢一个分组,回退 N 步(GBN)要从丢失的分组起全部重传,选择重传(SR)只重传那一个。把第一段改成 sr,对比两者的发送次数。在 TCP 里,这个窗口取接收方通告的接收窗口(流量控制)和拥塞窗口(拥塞控制)中较小的一个。

交互演示 · 逐步观察

滑动窗口 · GBN 与 SR

回退 N 步 GBN,窗口 4:发完 10 个分组一共要发送几次?

换个输入
0可发送
1可发送
2可发送
3可发送
4不能发
5不能发
6不能发
7不能发
8不能发
9不能发
当前处理已发现 / 已计算答案
这一步的分组(× 丢失)或 ACK
空
base
0
next
0
接收方期望
0
发送 / 其中重传
0 / 0

回退 N 步 GBN:10 个分组,窗口大小 4,分组 3 第一次发送时会丢失。蓝色是发送窗口 [base, base + 4),窗口里的分组不用等确认就能发。

始终成立发送方只能发 [base, base + 窗口) 里的分组。GBN 接收方只收按序到达的分组,用累计 ACK 确认最后一个按序分组,超时后发送方从 base 起全部重传;SR 接收方缓存失序分组并逐个确认,只重传超时的分组。这里一轮是一个往返,没确认的分组在下一轮结束时超时;序号不回绕(真实的 SR 要求窗口不超过序号空间的一半)。TCP 的发送窗口还受接收方在 ACK 里通告的接收窗口 rwnd 限制,取 min(cwnd, rwnd):rwnd 防止发送方塞满接收方的缓冲区(流量控制),cwnd 防止网络拥塞(拥塞控制)。