插件窝 干货文章 linux的进程调度发生在什么情况下

linux的进程调度发生在什么情况下

调度 进程 触发 内核 98    来源:    2025-05-02

Linux 进程调度(Process Scheduling)会在多种情况下触发,主要由内核的调度器(如CFS、O(1)调度器等)根据策略和事件决定。以下是触发调度的典型场景:


1. 主动调度(Voluntary)

  • 系统调用显式让出CPU
    进程通过系统调用(如 sched_yield()nanosleep())主动放弃CPU。
  • 阻塞操作
    当进程因I/O、锁、信号量等资源不可用而阻塞时,内核会将其移出运行队列,触发调度。

2. 被动调度(Involuntary)

  • 时间片耗尽(Time Slice Expired)
    Linux 的 CFS 调度器通过虚拟时间(vruntime)公平分配CPU。当进程耗尽其时间片(由 sched_latency_nssched_min_granularity_ns 控制),会被重新排队,调度新进程。
  • 更高优先级进程就绪
    实时进程(RT Priority)或更高优先级的普通进程(Nice值更低)进入可运行状态时,可能抢占当前进程。

3. 中断和异常

  • 硬件中断
    例如网卡收到数据包、磁盘I/O完成时,中断处理程序执行后可能唤醒等待该事件的进程,触发调度。
  • 时钟中断(Tick)
    内核周期性时钟中断(如 CONFIG_HZ=1000 时每秒1000次)检查是否需要调度(通过 scheduler_tick() 更新进程状态和时间片)。

4. 进程状态变化

  • 进程创建/终止
    fork()exit() 等操作会修改任务队列,触发调度。
  • 进程唤醒(Wake Up)
    等待中的进程被唤醒(如 wake_up()),若其优先级高于当前进程,可能触发抢占。

5. 显式抢占(Explicit Preemption)

  • 内核抢占(Kernel Preemption)
    配置 CONFIG_PREEMPT 时,内核代码(除关键区域)可被高优先级进程抢占。
  • 用户态抢占(User Preemption)
    从内核态(系统调用、中断)返回用户态前,检查是否需要调度。

6. 其他特殊情况

  • CPU负载均衡
    多核系统中,调度器可能将进程迁移到空闲CPU,触发调度。
  • cgroup 限制
    进程超出其所属Cgroup的CPU配额时会被限制。

调度触发的底层机制

  • 调用 schedule() 函数
    上述所有场景最终通过调用内核的 schedule() 函数完成实际切换。
  • 抢占标记(TIF_NEED_RESCHED)
    内核通过设置当前线程的 need_resched 标志,在安全点时触发调度。

观察调度行为

  • 工具
    使用 perf schedftrace/proc/<pid>/schedstat 跟踪调度事件。
  • 日志
    内核启动参数添加 sched_debug 可查看详细调度信息。

通过理解这些触发条件,可以更好地优化进程优先级(Nice/RT)、减少阻塞、或调整调度策略(如 chrt 修改实时策略)。