惡霸調度器-實時調度器

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給普通進程)是不現實的。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章