当前位置: 首页 > news >正文

Linux内核中的进程调度器详解

Linux内核中的进程调度器详解

引言

进程调度器是Linux内核中负责分配CPU时间的核心组件,它决定了系统中各个进程的执行顺序和优先级。一个好的调度器能够充分利用CPU资源,提高系统的响应速度和吞吐量。本文将深入探讨Linux内核中的进程调度器,包括其原理、实现和调优。

进程调度的基本概念

1. 调度器的作用

  • CPU分配:决定哪个进程获得CPU时间
  • 优先级管理:根据进程优先级分配CPU时间
  • 公平性:确保每个进程都能获得合理的CPU时间
  • 响应性:保证交互式进程的响应速度
  • 吞吐量:最大化系统的整体吞吐量

2. 进程的状态

  • 运行态(TASK_RUNNING):正在运行或准备运行
  • 可中断睡眠(TASK_INTERRUPTIBLE):等待事件,可被信号唤醒
  • 不可中断睡眠(TASK_UNINTERRUPTIBLE):等待事件,不可被信号唤醒
  • 僵尸态(TASK_ZOMBIE):进程已终止,等待父进程回收
  • 停止态(TASK_STOPPED):进程被停止

3. 调度策略

  • SCHED_OTHER:普通进程,CFS调度
  • SCHED_FIFO:实时进程,先进先出
  • SCHED_RR:实时进程,时间片轮转
  • SCHED_DEADLINE:实时进程,截止时间调度

CFS调度器

1. CFS的原理

CFS(Completely Fair Scheduler)是Linux 2.6.23引入的调度器,它基于公平调度的理念。

2. CFS的核心概念

  • 虚拟运行时间(vruntime):进程的实际运行时间按优先级比例缩放后的值
  • 红黑树:用于按vruntime排序进程
  • 调度实体(sched_entity):表示一个可调度的实体
  • 调度类(sched_class):实现不同的调度策略

3. CFS的结构

#include <linux/sched.h> struct cfs_rq { struct load_weight load; unsigned int nr_running; u64 exec_clock; u64 min_vruntime; struct rb_root tasks_timeline; struct rb_node *rb_leftmost; struct sched_entity *curr; // 其他字段... }; struct sched_entity { struct load_weight load; struct rb_node run_node; u64 vruntime; u64 prev_sum_exec_runtime; u64 sum_exec_runtime; // 其他字段... };

4. CFS的工作流程

  1. 进程创建:初始化调度实体,加入CFS运行队列
  2. 进程唤醒:将进程从睡眠队列移到运行队列
  3. 调度决策:选择vruntime最小的进程执行
  4. 时间片计算:基于进程优先级和系统负载计算时间片
  5. 上下文切换:保存当前进程状态,恢复下一个进程状态

实时调度器

1. 实时调度的原理

实时调度器为实时进程提供了更高的优先级和确定性。

2. 实时调度策略

  • SCHED_FIFO:先进先出,无时间片
  • SCHED_RR:时间片轮转
  • SCHED_DEADLINE:基于截止时间

3. 实时调度的实现

#include <linux/sched.h> struct rt_rq { struct list_head rt_rq_list; unsigned int rt_nr_running; unsigned int rt_throttled; u64 rt_time; u64 rt_runtime; struct rt_bandwidth *rt_bandwidth; // 其他字段... }; struct sched_rt_entity { struct list_head run_list; unsigned int time_slice; unsigned int nr_cpus_allowed; struct sched_rt_entity *back; // 其他字段... };

调度器的API

1. 调度器相关的系统调用

#include <sched.h> // 设置调度策略和优先级 int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param); // 获取调度策略 int sched_getscheduler(pid_t pid); // 设置调度参数 int sched_setparam(pid_t pid, const struct sched_param *param); // 获取调度参数 int sched_getparam(pid_t pid, struct sched_param *param); // 获取优先级范围 int sched_get_priority_max(int policy); int sched_get_priority_min(int policy); // 让出CPU int sched_yield(void);

2. 内核API

#include <linux/sched.h> // 调度类 struct sched_class { const struct sched_class *next; void (*enqueue_task)(struct rq *rq, struct task_struct *p, int flags); void (*dequeue_task)(struct rq *rq, struct task_struct *p, int flags); void (*yield_task)(struct rq *rq); bool (*pick_next_task)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf); void (*put_prev_task)(struct rq *rq, struct task_struct *p); // 其他方法... }; // 调度器操作 void sched_ttwu(struct task_struct *p, int wake_flags); void schedule(void); void schedule_preempt_disabled(void);

调度器的调优

1. 系统参数调优

# 调整调度器参数 sysctl -w kernel.sched_autogroup_enabled=1 # 自动分组 sysctl -w kernel.sched_child_runs_first=0 # 子进程优先 sysctl -w kernel.sched_migration_cost_ns=500000 # 迁移成本 sysctl -w kernel.sched_latency_ns=24000000 # 调度延迟 sysctl -w kernel.sched_min_granularity_ns=3000000 # 最小粒度

2. 进程优先级调优

# 调整进程优先级 nice -n 19 ./program # 降低优先级 # 调整实时优先级 chrt -f 99 ./program # SCHED_FIFO,优先级99 chrt -r 50 ./program # SCHED_RR,优先级50 # 查看进程优先级 ps -eo pid,comm,ni,pri,rtprio

3. CPU亲和性

# 设置CPU亲和性 taskset -c 0-3 ./program # 绑定到CPU 0-3 # 查看CPU亲和性 taskset -p <pid> # 内核API int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask); int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);

实际案例分析

1. 高优先级进程

#include <stdio.h> #include <sched.h> int main() { struct sched_param param; // 设置实时优先级 param.sched_priority = 99; if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) { perror("sched_setscheduler"); return 1; } // 实时任务 while (1) { // 处理实时任务 } return 0; }

2. 批处理任务

#include <stdio.h> #include <sched.h> int main() { struct sched_param param; // 设置普通优先级(低) param.sched_priority = 0; if (sched_setscheduler(0, SCHED_BATCH, &param) == -1) { perror("sched_setscheduler"); return 1; } // 批处理任务 for (int i = 0; i < 1000000; i++) { // 计算密集型任务 } return 0; }

3. 交互式任务

#include <stdio.h> #include <sched.h> int main() { struct sched_param param; // 设置普通优先级(高) param.sched_priority = 0; if (sched_setscheduler(0, SCHED_NORMAL, &param) == -1) { perror("sched_setscheduler"); return 1; } // 调整nice值 nice(-10); // 提高优先级 // 交互式任务 while (1) { // 处理用户输入 } return 0; }

结论

进程调度器是Linux内核中最核心的组件之一,它直接影响系统的性能和响应速度。CFS调度器通过公平分配CPU时间,为普通进程提供了良好的性能,而实时调度器则为时间敏感的任务提供了确定性的执行环境。理解调度器的原理和调优方法,对于系统性能优化和应用程序设计都有重要意义。

http://www.jsqmd.com/news/635366/

相关文章:

  • 2026年新疆新能源汽车漆面防护与轻改升级完全指南|车闪电官方联系方式+行业深度横评 - 精选优质企业推荐榜
  • 55.5%高增速锚定!双足仿人形机器人赛道开启未来六年黄金增长期
  • Transmission终极指南:从基础部署到高级调优的完全手册
  • 电动汽车对IEEE 33节点电网影响的汽车负荷预测与节点潮流网损、压损计算——四种场景应用
  • STM32F407通过FSMC接口驱动LAN9252 EtherCAT从站实战
  • 无线射频基础:从波长、频率到振幅与相位的实战解析
  • STM32H743双CAN总线负载太高?试试用CubeIDE+CanFestival同时跑两个CANopen主站
  • Fish Speech 1.5效果展示:听听AI生成的自然流畅语音
  • 2026年新疆新能源汽车漆面防护与轻改升级完全指南:车闪电官方联系方式+主流品牌横评+避坑指南 - 精选优质企业推荐榜
  • BiliTools:3步解锁哔哩哔哩高效学习新体验,让知识获取速度提升300%
  • 2026 年国内托盘式桥架厂家排名前十权威发布:安徽鑫铂特电气有限公司位居榜首 - 安互工业信息
  • 2026年高纯气体过滤有哪些品牌?行业精选推荐 - 品牌排行榜
  • 如何实现抗体亲和力的高效优化?
  • 如何不用 iTunes 将 iPhone 备份到移动硬盘?
  • 现代 .NET(.NET Core 5+)架构,原生跨平台
  • 基于.NET 6 + GTK的Winform跨平台实战:从Windows到Linux/Mac的无缝迁移
  • 这 12 个神级免费工具,我用了才知道白白多花了好几年冤枉钱!
  • 液体在线浓度仪选购攻略:揭秘行业领先品牌与实力厂家 - 品牌推荐大师
  • 数仓分层实战:从ODS到ADS的架构设计与业务落地
  • 10分钟快速上手:用AutoGen构建你的第一个AI智能体团队
  • 上海二手奢侈品门店深度指南:资深买家的实地甄选 - 见闻解构
  • 2026新疆新能源汽车漆面防护与轻改升级完全指南:车闪电官方联系方式+主流品牌深度横评 - 精选优质企业推荐榜
  • 别再死记硬背了!从真实波形看懂跨时钟域打两拍为啥比打一拍靠谱
  • 超频进化和生存危机
  • 2026 年国内铝合金桥架厂家排名前十权威发布:安徽鑫铂特电气有限公司位居榜首 - 安互工业信息
  • 不锈钢水波纹板成型技术与装饰应用:鼎钻钢业立体工艺专家 - 博客万
  • 2026年国内工业滑触线厂家排名前十权威发布:鑫铂特电气有限公司位居榜首 - 安互工业信息
  • 如何用iCloud照片下载器实现全自动照片备份:终极命令行工具指南
  • 把 ABAP RFC Gateway 日志真正配明白,SMGW、gw/logging 与 secinfo、reginfo 的实战思路
  • 4月13日