实时调度类

来源:互联网 发布:具体营销数据分析 编辑:程序博客网 时间:2024/06/07 10:13

2.7 实时调度类
按照POSIX标准的强制要求,除了“普通”进程之外,Linux还支持两种实时调度类。调度器结构使得实时进程可以平滑地集成到内核中,而无须修改合兴调度器,这显然是调度类带到的好处。
rt_task宏通过检查其优先级来正式给定进程是否实时进程,而task_has_rt_poliey则检测进程是否关联实时调度策略。

2.7.1 性质
实时进程与普通进程又一个根本的不同之处:如果系统中有一个事实进程且可运行,那么调度器总是会选中它运行,除非有一个优先级更高的实时进程。
现有的两种实时类,不同之处如下所示。
*循环进程(SCHED_RR)有时间片,其至在进程运行时会减少,就像是普通进程。在所有的时间段都到期后,则该值重置为初始值,而进程则置于队列的末尾。这确保了在有几个优先级相同的SCHED_RR进程的情况下,他们总是一次执行
*先进先出进程(SCHED_FIFO)没有时间片,在被调度器选择执行后,可以运行任意长时间。很明显,如果实时进程编写的比较差,系统可能变得无法使用。只有写一个无限循环,循环体内部进入睡眠即可。在编写实时应用程序时,应该多加小心。

2.7.2 数据结构
实时进程得分调度类定义如下
kernel/sched-rt.c
const struct shced_class rt_sched_class = {
.next = &fair_sched_class,
.enqueue_task = enqueue_task_rt,
.dequeue_task = dequeue_task_rt,
.yiedld_task = yield_task_rt,
.check_next_task = pick_next_task_rt,
.put_prev_task = put_prev_task_rt,
.set_curr_task = set_curr_task_rt,
.task_tick = task_tick_rt,
}

实时调度类的实现比完全公平调度器简单。核心调度器的就绪队列也包含了用于实时进程的子就绪队列,是一个嵌入的struct rt_rq实现。
实时调度器类中对应于update_cur的是update_curr_rt,该函数将当前进程在CPU上执行花费的时间记录在sum_exec_runtime中。

2.7.3 调度器操作
进程的入队和离队都比较简单。只须p->prio为索引访问queue数组queue[p->prio],即可获得正确的链表,将进程加入链表或链表删除即可。如果队列中至少有一个进程,则将为图中对应的比特位置位;如果队列中没有进程,则清除位图中对应的比特位。请注意,新进程总是排列在每个链表的末尾。
两个比较有趣的操作分别是;如何选择下一个将要执行的进程,以及如何处理抢占。
sched_find_first_bit 是一个标准函数,可以找到active.bitmap中第一个置为的比特位,这意味着高的实时优先级,因此在较低的实时优先级之前处理。取出所选链表的第一个进程,并将 se.exec_start设置为就绪队列的当前实际时钟值,即可。
static void task_tick_rt()
如果当前进程是循环进程,则减少其时间片。在尚未超出时间段时,没什么可作的,进程可继续执行。
*使用deactivate_task将进程从当前队列移除。
*在task_struct中设置试试优先级和调度类
如果进程此前不再任何就绪队列上,那么只需要设置调度类和新的优先级数值。停止进程活动重激活则是不必要的。
要注意,只有具有root权限的进程执行了sched_setscheduler系统调用,才能修改调度器或优先级。否则,下列规则使用。、
*调度类只能从sched_normal该为SCHED_BATCH,或反过来。改为SHED_FIFO是不可能的
*只有目标进程UID或EUID与调用者进程的EUID相同时,才能修改目标进程的优先级。此时优先级只能降低,不能提升。

0 0