恶霸调度器-实时调度器

1.内核如何组织调度实体:

struct task_struct {
    ...
    struct sched_rt_entity		rt;
    ...
}

struct sched_rt_entity {
	struct list_head		run_list;
	unsigned long			timeout;
	unsigned long			watchdog_stamp;
	unsigned int			time_slice;
	unsigned short			on_rq;
	unsigned short			on_list;

	struct sched_rt_entity		*back;
#ifdef CONFIG_RT_GROUP_SCHED
	...	
#endif
}

2.进程的实时调度实体是怎么加入到cpu的rt_rq的?

static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, unsigned int flags)
{
	//通过当前rq_se找到当前cpu中的per_cpu变量runqueues中的rt_rq
	struct rt_rq *rt_rq = rt_rq_of_se(rt_se);
	//得到rt_prio_array
	struct rt_prio_array *array = &rt_rq->active;
	struct rt_rq *group_rq = group_rt_rq(rt_se);
	//根据优先级找到对应的queue
	struct list_head *queue = array->queue + rt_se_prio(rt_se);

	//入队queue
	if (move_entity(flags)) {
		WARN_ON_ONCE(rt_se->on_list);
		if (flags & ENQUEUE_HEAD)
			list_add(&rt_se->run_list, queue);
		else
			list_add_tail(&rt_se->run_list, queue);

		__set_bit(rt_se_prio(rt_se), array->bitmap);
		rt_se->on_list = 1;
	}
	//标记当前进程在队中
	rt_se->on_rq = 1;
	//增加rt_rq的统计值
	inc_rt_tasks(rt_se, rt_rq);
}

3.关于时间片:

fork进程时,不论是不是实时进程,rt相关的成员都会进行初始化:

static void __sched_fork(unsigned long clone_flags, struct task_struct *p)
{
	INIT_LIST_HEAD(&p->rt.run_list);
	p->rt.timeout		= 0;
	p->rt.time_slice	= sched_rr_timeslice;
	p->rt.on_rq		= 0;
	p->rt.on_list		= 0;
|
}
//实时调度器默认时间片100毫秒():
#define RR_TIMESLICE		(100 * HZ / 1000)

实时为何如此之大的原因后面会提到

4.为什么说实时调度器是非常霸道?

它的调度器类优先级是仅次于deadline调度类的:

#define sched_class_highest (&stop_sched_class)
stop_sched_class.next = &stop_sched_class->next = \ 
	&dl_sched_class->next = \
	&rt_sched_class->next = \
	&fair_sched_class->next = \
	&idle_sched_class->next = \
	NULL
 //pick_next_task核心逻辑
 for_each_class(class) {
	p = class->pick_next_task(rq, prev, rf);
}

就像银行排号一样,一旦来了一个白金卡用户,他会立即排到所有普通卡用户前头。所以在执行调度时,一旦有实时进程的存在,就优先调度实时进程。

再看看实时进程有没有可能被抢占,周期性调度器会调用当前进程调度类的task_tick来决定当前进程是否要抢占,看看实时调度类的实现task_tick_rt:

static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued)
{
	if (p->policy != SCHED_RR)//SCHED_FIFO
		return;

	if (--p->rt.time_slice)//SCHED_RR
		return; 
    //即使是RR进程的时间片用完,它也只是重新填上时间片再加到同实时优先级run_list的队尾而已
    p->rt.time_slice = sched_rr_timeslice;
  	for_each_sched_rt_entity(rt_se) {
  		if (rt_se->run_list.prev != rt_se->run_list.next) {
  			requeue_task_rt(rq, p, 0);
  			resched_curr(rq);
  			return;
  		}
  	}
}

恶霸的原则就是谁拳头硬(有效优先级高)谁就先说话:

static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flags)
{
	if (p->prio < rq->curr->prio) {
		resched_curr(rq);
		return;
	}
}

As we know,实时进程优先级是肯定是要高于普通进程的:

综上,大多数情况下,恶霸(实时进程)一旦来了,除非他自己捐出所有家产归隐山林(主动让出CPU并离开运行列队),打倒恶霸开仓放粮给老百姓(抢占实时进程腾出CPU给普通进程)是不现实的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值