📖 推荐阅读:《Yocto项目实战教程:高效定制嵌入式Linux系统》
🎥 更多学习视频请关注 B 站:嵌入式Jerry
Linux 任务调度在进程管理中的关系和运行机制
Linux 内核中的“任务调度”是进程管理系统的核心部分,相互关联而且分工明确。本文通过概念分析、模型分布、行为模式、调度策略、管理工具、代码示例和流程总结,全面讲解 Linux 任务调度在进程管理中的作用和机制。
一、任务 vs 进程:基本概念分清
概念 | 含义 |
---|---|
进程 (Process) | 抽象的运行单元,拥有独立的虚拟地址空间和资源 |
线程 (Thread) | 进程内部的执行流 |
任务 (Task) | Linux 内核中对进程和线程的通用统一概念,对应一个 task_struct 结构,是调度的基本单元 |
同一进程内的多个线程,将在内核中分别代表为多个 task
二、调度系统结构与模式
Linux 调度系统分为以下几个层级:
1. 调度器(Scheduler)
- 核心模块,管理所有任务的调度逻辑。
- 入口函数如
schedule()
、pick_next_task()
、context_switch()
。
2. 调度行为(Scheduling Behavior)
定义内核是否允许任务在运行中被中断(即“抢占”)。
模式 | 名称 | 说明 |
---|---|---|
抢占式 | Preemptive | 当前任务可以随时被更高优先级任务抢占 CPU,适合响应敏感系统(Linux 默认支持) |
非抢占式 | Non-preemptive | 当前任务必须主动放弃 CPU(如阻塞或退出),适合嵌入式、批处理任务等 |
注意:抢占式是一种调度行为,不是调度策略,它适用于不同调度策略下的调度逻辑实现。
3. 调度策略(Scheduling Policy)
调度器采用不同策略决定如何选择任务。
策略 | 类型 | 抢占行为 | 说明 |
---|---|---|---|
SCHED_NORMAL (CFS) | 非实时 | 抢占式 | 默认策略,基于虚拟运行时间(vruntime)公平调度 |
SCHED_FIFO | 实时 | 非抢占式 | 先来先服务,不自动让出 CPU,适合控制系统 |
SCHED_RR | 实时 | 抢占式 | 时间片轮转,适合需要时间约束的实时任务 |
SCHED_DEADLINE | 实时 | 抢占式 | 基于截止时间和周期调度,用于软/硬实时系统 |
三、任务调度流程:从状态到切换
任务状态:
状态 | 说明 |
---|---|
TASK_RUNNING | 可调度,或正在运行 |
TASK_INTERRUPTIBLE | 等待被中断唤醒 |
TASK_UNINTERRUPTIBLE | 不可被中断,用于硬件阻塞操作 |
TASK_DEAD | 任务结束,正在回收资源 |
调度进程切换流程:
正在运行的任务 A||规则触发 (CPU 用完 / 阻塞 / 有高优先级任务)|schedule()|pick_next_task()|context_switch(A, B)|
切换到 B 执行
四、调度管理工具
工具 | 功能 |
---|---|
ps / top / htop | 查看运行任务信息 |
chrt | 设置或查询任务的调度策略(如 FIFO、RR) |
taskset | 设置 CPU 给任务的亲和性(CPU affinity) |
schedtool | 更细化设置调度策略和优先级 |
/proc/[pid]/sched | 查看进程调度信息结构体 |
五、代码实战:两个线程设置不同调度策略
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <unistd.h>void *low_task(void *) {while (1) {printf("low priority running\n");sleep(1);}
}void *high_task(void *) {while (1) {printf("HIGH priority running\n");sleep(1);}
}int main() {pthread_t t1, t2;struct sched_param param;pthread_create(&t1, NULL, low_task, NULL);pthread_create(&t2, NULL, high_task, NULL);param.sched_priority = 10; // lowpthread_setschedparam(t1, SCHED_RR, ¶m);param.sched_priority = 80; // highpthread_setschedparam(t2, SCHED_RR, ¶m);pthread_join(t1, NULL);pthread_join(t2, NULL);return 0;
}
通过
pthread_setschedparam
分别设置不同线程的调度策略与优先级,可观察抢占调度行为,高优线程会频繁抢占 CPU。
六、调度模型补充说明:是否还有其他调度模式?
除了抢占式与非抢占式,还有以下相关概念值得补充:
1. 自愿抢占(Voluntary Preemption)
- Linux 内核配置中
CONFIG_PREEMPT_VOLUNTARY
- 表示仅在特定调度点(如 IO 阻塞、显式调用
schedule()
)才允许切换。 - 优点是可控性好,适合桌面/服务器系统,缺点是实时性较差。
2. 强制抢占(Fully Preemptible)
CONFIG_PREEMPT
- 表示内核大多数路径都允许被抢占,适合响应及时性高的系统。
3. 实时抢占补丁(PREEMPT_RT)
- 加强版本的内核实时性特性,几乎所有内核上下文都可被中断。
- 适合工业级/控制系统等严格实时场景。
七、总结:调度机制是进程管理的动态执行核心
- ✅ 任务是调度的基本对象,所有进程/线程均由 task_struct 管理
- ✅ 调度行为定义是否可打断当前任务(抢占与否)
- ✅ 调度策略定义如何选择下一个任务(如 FIFO、RR、CFS)
- ✅ 调度器通过 schedule/pick/context_switch 完成任务切换
- ✅ 配套工具(如 chrt、schedtool)是日常开发/调试调度的关键武器
📖 推荐阅读:《Yocto项目实战教程:高效定制嵌入式Linux系统》
🎥 更多学习视频请关注 B 站:嵌入式Jerry