什么是时间片?

#计算机网络#操作系统#面试八股

什么是时间片?

时间片(time slice / quantum)是调度器一次分给某个可运行任务连续占用 CPU 的时长。用完就触发一次时钟中断, 调度器把 CPU 收回来交给下一个任务。它的作用是让"单核 CPU 看起来在同时跑很多任务", 本质是用**抢占(preemption)**换取响应速度和公平性。

1. 时间片怎么影响系统

单核、3 个可运行任务、时间片 4ms
时间 →
A(4ms) │ B(4ms) │ C(4ms) │ A(4ms) │ B(4ms) │ C(4ms)
       ↑每次切换要保存/恢复上下文,并让缓存、TLB 变冷

响应时间 ≈ 时间片 × 前面排队的任务数
吞吐     ≈ 1 / (时间片 + 切换开销)  × 有效工作量
时间片优点缺点
很小(<1ms)交互响应快,公平切换开销占比高,缓存命中率下降
很大(>100ms)吞吐高,缓存友好交互卡顿,一个死循环能饿死别人
适中(几 ms)两者折中需要按负载动态调整

切换本身不便宜:保存寄存器、切内核栈、换页表(TLB 失效)、污染分支预测器, 实测一次上下文切换约 2~5 微秒。时间片若只有 1ms,光切换就吃掉 0.5% 以上的 CPU,还不算缓存损失。

2. Linux 的做法:CFS 用"虚拟运行时间"

现代 Linux 默认调度器 CFS(Completely Fair Scheduler)没有固定时间片, 它维护每个任务的 vruntime(虚拟运行时间),永远挑 vruntime 最小的任务跑, 并用红黑树(red-black tree)按 vruntime 排序,取最左节点即 O(log n)。

                 rb_root
                /        \
          vruntime小      vruntime大
             /  \
        (最左) ← 下一个被调度的任务

实际分配时长由两个参数约束:

调度周期 sched_latency(默认 6ms)
若可运行任务数 > sched_latency / sched_min_granularity(默认 0.75ms)
    则周期拉长为 任务数 × min_granularity(保证每个任务至少跑 0.75ms)
单任务时间片 = 周期 × 该任务权重 / 所有任务权重之和

权重(weight)由 nice 值映射:nice 每降 1,权重约增加 25%,所以 nice -20 的任务拿到的时间片 大约是 nice 0 的 100 倍量级(权重 88761 对 1024)。

3. 查看与调整

# 调度周期与最小粒度(单位 ns)
cat /proc/sys/kernel/sched_latency_ns            # 6000000
cat /proc/sys/kernel/sched_min_granularity_ns    # 750000
cat /proc/sys/kernel/sched_wakeup_granularity_ns # 唤醒抢占阈值

# 看一个任务实际跑了多久、被抢占多少次
perf sched latency -p 1234
cat /proc/1234/schedstat    # 运行时长(ns) 等待时长(ns) 时间片次数

# 实时任务:SCHED_RR 的固定时间片为 100ms
chrt -r -p 10 1234
chrt -p 1234

容器里更常用 cgroup 的带宽控制,相当于给一组任务设"周期 + 配额":

# 每 100ms 周期内最多用 50ms CPU(约 0.5 核)
echo "50000 100000" > /sys/fs/cgroup/demo/cpu.max

4. 常见追问

Q:时间片用完,任务会怎样? 被标记 TIF_NEED_RESCHED,在返回用户态或中断返回时触发 schedule(),任务放回红黑树(其 vruntime 已推进), 状态变为可运行(R),等下一次被选中。它不会被"杀死",只是让出 CPU。

Q:为什么 CFS 不用固定时间片? 固定片在任务数变化时很难兼顾延迟和吞吐:任务多时响应变差,任务少时切换浪费。 CFS 用"按权重分配比例 + 最小粒度保底"的方式,让时间片随负载自动伸缩,同时保证公平。

Q:实时任务会不会把普通任务饿死? 会,所以内核默认开启 RT throttling(/proc/sys/kernel/sched_rt_runtime_us 默认 950000/1000000), 即每 1 秒最多让实时任务占用 95%,留 5% 给普通任务,避免系统失去响应。

Q:时间片和"调度延迟"是一回事吗? 不是。时间片是单个任务一次跑多久;调度延迟是从"任务变成可运行"到"真正拿到 CPU"的时间, 受队列长度、抢占策略、CPU 亲和性共同影响。压测里关心的 p99 延迟抖动,往往就是调度延迟。

小结

时间片是抢占式调度的最小分配单位,小了响应快但切换贵,大了吞吐高但卡顿。 Linux 用 CFS 的 vruntime + 权重 + 最小粒度 代替固定时间片,并用 cgroup 带宽做配额上限。 答这题时讲清"为什么需要时间片 → 大小如何权衡 → CFS 怎么实现 → 怎么观测"这条线就够了。

笔记加载中…