linux rt调度器
RT(RealTime scheduler)实时调度器,对应用户设定的调度策略为 SCHED_FIFO/SCHED_RR。SCHED_FIFO 先进先出队列调度,高优先级任务一直运行,直到任务阻塞,或者主动退出,或者被更高优先级任务抢占。SCHED_RR 时间片轮转调度,每个实时任务划分一个时间片,时间片用完会切换到其他任务执行。进程几种状态表示:1.
·
RT(RealTime scheduler)实时调度器,对应用户设定的调度策略为 SCHED_FIFO/SCHED_RR。
SCHED_FIFO 先进先出队列调度,高优先级任务一直运行,直到任务阻塞,或者主动退出,或者被更高优先级
任务抢占。
SCHED_RR 时间片轮转调度,每个实时任务划分一个时间片,时间片用完会切换到其他任务执行。
进程几种状态表示:
1. TASK_RUNNING: 这里表示进程没有被阻塞,即READY和RUNNING的结合体。至于具体是READY还是 RUNNING,在需要的时候可以做如下判断:调度程序取得该进程的进程状态为TASK_RUNNING且其所在CPU的current_task就是该进程,则认定他是RUNNING,否则就是READY。需要做如上判断的情况其实并不多,所以统以TASK_RUNNING描述便已足够。
2. TASK_INTERRUPTIBLE: 进程处于BLOCK状态且可以被SIGNAL唤醒
3. TASK_UNINTERRUPTIBLE: 进程处于BLOCK状态但不能被SIGNAL唤醒
4. TASK_ZOMBIE: 进程已经结束,但描述符还没有被回收。
5. TASK_STOPPED: 进程停止运行。通常在收到SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU等信号时发生;或者在调试时收到任何信号都会发生。可向其发送SIGCONT使其继续运行。
task的状态记录在task_struct结构的state成员中。
调度程序每次从处于running状态的task中选择一个最合适的来运行。
RT调度器的核心是优先级队列,调度程序从最高优先级队列头部选择一个task运行,
调度结束会将任务放到对应的优先级队列尾部。
bitmap标示优先级,某个bit置1标示该优先级队列不为空。
struct rt_prio_array {
DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
struct list_head queue[MAX_RT_PRIO];
SCHED_FIFO 先进先出队列调度,高优先级任务一直运行,直到任务阻塞,或者主动退出,或者被更高优先级
任务抢占。
SCHED_RR 时间片轮转调度,每个实时任务划分一个时间片,时间片用完会切换到其他任务执行。
进程几种状态表示:
1. TASK_RUNNING: 这里表示进程没有被阻塞,即READY和RUNNING的结合体。至于具体是READY还是 RUNNING,在需要的时候可以做如下判断:调度程序取得该进程的进程状态为TASK_RUNNING且其所在CPU的current_task就是该进程,则认定他是RUNNING,否则就是READY。需要做如上判断的情况其实并不多,所以统以TASK_RUNNING描述便已足够。
2. TASK_INTERRUPTIBLE: 进程处于BLOCK状态且可以被SIGNAL唤醒
3. TASK_UNINTERRUPTIBLE: 进程处于BLOCK状态但不能被SIGNAL唤醒
4. TASK_ZOMBIE: 进程已经结束,但描述符还没有被回收。
5. TASK_STOPPED: 进程停止运行。通常在收到SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU等信号时发生;或者在调试时收到任何信号都会发生。可向其发送SIGCONT使其继续运行。
task的状态记录在task_struct结构的state成员中。
调度程序每次从处于running状态的task中选择一个最合适的来运行。
RT调度器的核心是优先级队列,调度程序从最高优先级队列头部选择一个task运行,
调度结束会将任务放到对应的优先级队列尾部。
bitmap标示优先级,某个bit置1标示该优先级队列不为空。
struct rt_prio_array {
DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
struct list_head queue[MAX_RT_PRIO];
};
task入队操作:
/*
* Adding/removing a task to/from a priority array:
*/
static void
enqueue_task_rt(struct rq *rq, struct task_struct *p, int flags)
{
struct sched_rt_entity *rt_se = &p->rt;
if (flags & ENQUEUE_WAKEUP)
rt_se->timeout = 0;
//flag为0的话,将实体的run_list 加入优先级队列queue尾部,否则插入头部,优先调度。
enqueue_rt_entity(rt_se, flags & ENQUEUE_HEAD);
//p不是当前rq正在运行进程,并且p可以在其他cpu上运行,就将p进入rq pushable_tasks,可以做负载均衡时使用,
if (!task_current(rq, p) && p->nr_cpus_allowed > 1)
enqueue_pushable_task(rq, p);
inc_nr_running(rq);
inc_hmp_sched_stats_rt(rq, p);
}
//先将实体所做task group删除队列,然后再依次入队列
static void enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
{
dequeue_rt_stack(rt_se);
for_each_sched_rt_entity(rt_se)
__enqueue_rt_entity(rt_se, head);
}
static void dequeue_rt_stack(struct sched_rt_entity *rt_se)
{
struct sched_rt_entity *back = NULL;
//从下往上遍历,支持task group
for_each_sched_rt_entity(rt_se) {
rt_se->back = back;
back = rt_se;
}
//从上往下遍历,依次出队
for (rt_se = back; rt_se; rt_se = rt_se->back) {
if (on_rt_rq(rt_se))
__dequeue_rt_entity(rt_se);
}
}
static void __dequeue_rt_entity(struct sched_rt_entity *rt_se)
{
struct rt_rq *rt_rq = rt_rq_of_se(rt_se);//实体所在rq
struct rt_prio_array *array = &rt_rq->active; //优先级数组
list_del_init(&rt_se->run_list);//list中删除实体
if (list_empty(array->queue + rt_se_prio(rt_se)))//该实体所在优先级队列为空
__clear_bit(rt_se_prio(rt_se), array->bitmap);//bitmap标识对应优先级queue 是否为空
dec_rt_tasks(rt_se, rt_rq);
if (!rt_rq->rt_nr_running)
list_del_leaf_rt_rq(rt_rq);
}
//入队,调度实体加入对应优先级队列中
static void __enqueue_rt_entity(struct sched_rt_entity *rt_se, bool head)
{
struct rt_rq *rt_rq = rt_rq_of_se(rt_se);//实体所在rq
struct rt_prio_array *array = &rt_rq->active;//优先级数组
struct rt_rq *group_rq = group_rt_rq(rt_se);//实体所属group
struct list_head *queue = array->queue + rt_se_prio(rt_se);//优先级队列
/*
* Don't enqueue the group if its throttled, or when empty.
* The latter is a consequence of the former when a child group
* get throttled and the current group doesn't have any other
* active members.
*/
if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running))
return;
if (!rt_rq->rt_nr_running)
list_add_leaf_rt_rq(rt_rq);
if (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);
inc_rt_tasks(rt_se, rt_rq);
}
//出队操作,更新rq当前task 状态,实体出队,然后实体加入队列尾部
static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int flags)
{
struct sched_rt_entity *rt_se = &p->rt;
update_curr_rt(rq);
dequeue_rt_entity(rt_se);
dequeue_pushable_task(rq, p);
dec_nr_running(rq);
dec_hmp_sched_stats_rt(rq, p);
}
static void dequeue_rt_entity(struct sched_rt_entity *rt_se)
{
dequeue_rt_stack(rt_se); //先从运行队列删除调度实体
for_each_sched_rt_entity(rt_se) {
struct rt_rq *rt_rq = group_rt_rq(rt_se);
if (rt_rq && rt_rq->rt_nr_running)
__enqueue_rt_entity(rt_se, false);//将调度实体再重新加入队列尾部
}
}
//RT调度器选择下个task过程:
static struct task_struct *pick_next_task_rt(struct rq *rq)
{
struct task_struct *p = _pick_next_task_rt(rq);
/* The running task is never eligible for pushing */
//p接下来将开始运行,自然不需要再push到其他rq
if (p)
dequeue_pushable_task(rq, p);
#ifdef CONFIG_SMP
/*
* We detect this state here so that we can avoid taking the RQ
* lock again later if there is no need to push
*/
rq->post_schedule = has_pushable_tasks(rq);
#endif
return p;
}
static struct task_struct *_pick_next_task_rt(struct rq *rq)
{
struct sched_rt_entity *rt_se;
struct task_struct *p;
struct rt_rq *rt_rq;
rt_rq = &rq->rt;
//TASK_RUNNIG 数目
if (!rt_rq->rt_nr_running)
return NULL;
if (rt_rq_throttled(rt_rq))
return NULL;
do {//处理组调度,task group 父进程在子进程的后面
rt_se = pick_next_rt_entity(rq, rt_rq);
BUG_ON(!rt_se);
rt_rq = group_rt_rq(rt_se);//实体在这个rq上
} while (rt_rq);
/*
* Force update of rq->clock_task in case we failed to do so in
* put_prev_task. A stale value can cause us to over-charge execution
* time to real-time task, that could trigger throttling unnecessarily
*/
if (rq->skip_clock_update > 0) {
rq->skip_clock_update = 0;
update_rq_clock(rq);
}
p = rt_task_of(rt_se);
p->se.exec_start = rq_clock_task(rq);//rt优先级可能会调整为nice?
return p;
}
//找个rq最高优先级队列第一个进程
static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq,
struct rt_rq *rt_rq)
{
struct rt_prio_array *array = &rt_rq->active;
struct sched_rt_entity *next = NULL;
struct list_head *queue;
int idx;
//第一个为1的bit代表了优先级queue的idx
idx = sched_find_first_bit(array->bitmap);
BUG_ON(idx >= MAX_RT_PRIO);
queue = array->queue + idx;
next = list_entry(queue->next, struct sched_rt_entity, run_list);
return next;
}
更多推荐
已为社区贡献3条内容
所有评论(0)