前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊Linux内核进程调度上篇

聊聊Linux内核进程调度上篇

作者头像
用户4700054
发布2022-08-17 13:15:09
6500
发布2022-08-17 13:15:09
举报
文章被收录于专栏:存储内核技术交流

基本介绍

  • Linux的进程调度器是内核中最重要的核心组件,它决定了一个进程合适获取CPU的时间以及占用CPU的时间。最佳情况下每个进程需要CPU执行指令的时间,如果需要保证进程之间的如何合理的分配CPU的指令执行时,进程的调度器需要具备如下的特性.
  • Linux进程调度器采用类似于vfs的设计采用简单的两层结构模式,第一层是通用调度器,定义作为进程调度器的入口抽象层;第二层是调度器的具体实现,根据调度策略实现进程的调度的器的具体实现。第一层的使用了struct sched_class来描;第二层是具体的具体的调度器包括deadline调度器(struct sched_class dl_sched_class)实时调度器(struct sched_class rt_sched_class)完全公平调度器(struct sched_class fair_sched_class)
  • 内核中运行队列包含了所有的进程,每个CPU都有一个运行队列,各自的进程运行队列都会在各自的CPU队列争夺CPU的运行时间。实际的进程调度器都会嵌入到每个CPU的运行队列中。内核中进程运行队列是通过struct rq来定义
代码语言:javascript
复制
// 省略大部分字段,着重描述下运行队列中的一些字段
struct rq {
	// 每个CPU的运行队列的锁
	raw_spinlock_t		lock;
	// 运行队列的进程数
	unsigned int		nr_running;
	// 当前CPU上的负载
	struct load_weight	load;
	// 进程切换的次数
	u64			nr_switches;
	// 公平调度器
	struct cfs_rq		cfs;
	// 实时调度器
	struct rt_rq		rt;
	// deadline调度器
	struct dl_rq		dl;

	unsigned long		nr_uninterruptible;
	// 正在运行的进程任务
	struct task_struct	*curr;
	// 空闲的进程任务
	struct task_struct	*idle;
	// 停止的进程任务
	struct task_struct	*stop;
	unsigned long		next_balance;
};

进程调度实现

  • 进程调度是调用进程第一层的通用调度器,内核是从__schedule()函数开始,该函数是挑选下一个最佳的可运行的进程任务。__schedule()函数中的pick_next_task()遍历实际调度器中的函数,并选择出下一个最佳的任务。如果其他实际调度器没有更高的优先级可运行的进程任务,则pick_next_task()会选择完全公平调度器中寻找下一个进程任务。
代码语言:javascript
复制
static void __sched notrace __schedule(bool preempt)
{
	next = pick_next_task(rq, prev, &rf);
}
 // 选择一个优先级最高的进程执行
static inline struct task_struct *pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
{
	const struct sched_class *class;
	struct task_struct *p;


	if (likely((prev->sched_class == &idle_sched_class ||
		    prev->sched_class == &fair_sched_class) &&
		   rq->nr_running == rq->cfs.h_nr_running)) {

		p = fair_sched_class.pick_next_task(rq, prev, rf);
		if (unlikely(p == RETRY_TASK))
			goto again;

		if (unlikely(!p))
			p = idle_sched_class.pick_next_task(rq, prev, rf);

		return p;
	}

again:
	for_each_class(class) {
		p = class->pick_next_task(rq, prev, rf);
		if (p) {
			if (unlikely(p == RETRY_TASK))
				goto again;
			return p;
		}
	}

	BUG();
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 存储内核技术交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基本介绍
  • 进程调度实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档