【Linux 内核调度器源码解析:从调度入口到挑选下一个进程】这个函数用于选择下一个要在公平调度类中运行的任务 。函数中包含了条件判断和循环,以确保选择最适合的任务 。
/* * 选择下一个调度实体,考虑以下因素,按照顺序: * 1) 在进程/任务组之间保持公平性 * 2) 选择“下一个”进程,因为某个进程确实希望运行 * 3) 选择“上一个”进程 , 以提高缓存局部性 * 4) 如果其他任务可用,则不运行“跳过”的进程 */static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr){struct sched_entity *left = __pick_first_entity(cfs_rq);// 获取最左边的实体struct sched_entity *se;/** 如果 curr 被设置,我们必须查看它是否位于树中最左边的实体的左侧,* 前提是树中确实有实体存在 。*/if (!left || (curr && entity_before(curr, left)))left = curr;se = left; /* 理想情况下,我们运行最左边的实体 *//** 避免运行跳过的实体 , 如果可以不运行其他实体而不会太不公平 。*/if (cfs_rq->skip && cfs_rq->skip == se) {struct sched_entity *second;if (se == curr) {second = __pick_first_entity(cfs_rq);// 获取最左边的实体} else {second = __pick_next_entity(se);// 获取下一个实体if (!second || (curr && entity_before(curr, second)))second = curr;}if (second && wakeup_preempt_entity(second, left) < 1)se = second;}if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, left) < 1) {/** 有人确实希望运行这个实体 。如果不不公平,就运行它 。*/se = cfs_rq->next;} else if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, left) < 1) {/** 更倾向于运行最后一个实体 , 尝试将 CPU 返回到一个被抢占的任务 。*/se = cfs_rq->last;}return se;} if (se == curr) {second = __pick_first_entity(cfs_rq);// 获取最左边的实体} else {second = __pick_next_entity(se);// 获取下一个实体if (!second || (curr && entity_before(curr, second)))second = curr;}if (second && wakeup_preempt_entity(second, left) < 1)se = second;return se; } 函数pick_next_entity的作用是选择下一个要运行的调度实体,它根据一系列因素来决定选择哪个实体,以确保公平性、满足任务需求,并尽量提高缓存局部性 。
总结通过深入分析Linux内核调度器的代码实现,我们了解了调度器的入口函数和选择下一个执行进程的过程 。这个过程是内核多任务处理的核心 , 确保了系统资源的合理分配 。深入理解调度器的工作原理将有助于我们更好地优化系统性能,提高响应速度 。
推荐阅读
- Linux中Netstat命令最常用的五个用法
- Linux技巧:使用cURL将输出保存到文件
- Linux协程艺术:探秘ucontext函数族的神奇世界
- 深入Linux内核:探秘进程实现的神秘世界
- 构建基于Linux的物联网应用程序:传感器和数据处理
- Mac使用CLion连接Linux进行远程开发
- 如何使用 Linux Xargs 命令,看这篇就够了
- XXL-JOB真的要凉了?出现了一个王炸级别的分布式任务调度与计算框架?
- Linux 黑话解释:Linux 中的 Super 键是什么?
- 揭秘 Linux 调度策略与 CFS 调度算法:解锁内核的奥秘
