LINUX进程调度分析源码,Linux 实时调度(源码分析)

为了弄清楚在多cpu系统中是如何实现实时调度的,先引入以下几个概念:

cpu的状态:

我们知道,在linux系统中,任务的优先级为0~140。

INVALID:(-1)该cpu不可用

IDLE(0):140

NORMAL(1):100~139对应于普通任务的优先级

RT0~RT99(2~102):对应于实时任务的优先级

进程优先级:

在linux内核中,每个进程都有一个task_struct,其中与优先级相关的属性包括

1、prio:对于非实时进程而言prio==normal_prio=99-rt_priority(prio的值越大,则进程的优先级越小)

2、normal_prio:99-rt_priority

3、static_prio:=100+nice

4、rt_priority:0:非实时任务;[1,99]实时任务,值越大,优先级越高。

在调度时使用了prio,其数值0对应最高优先级,99为最低实时优先级。Prio和normal_prio数值越大优先级越小,而rt_priority的数值越大优先级越大。

task balance:

在多cpu系统中,为了保证各个cpu上实时任务的负载均衡,引入了push和pull操作:

1、push操作:

当当前cpu上有多于一个的实时任务,那么需要使用pull操作看看是否可以将还未运行的实时任务移动到其他的cpu上,主要操作由push_rt_task函数完成。static int push_rt_task(struct rq *rq)

{

struct task_struct *next_task;

struct rq *lowest_rq;

int ret = 0;

///如果当前队列不是超载状态,则直接返回

if (!rq->rt.overloaded)

return 0;

///选择rq中下一个进程

next_task = pick_next_pushable_task(rq);

if (!next_task)

return 0;

retry:

......

///如果下一个进程的优先级比当前进程的优先级高,那么需要执行的不是push操作而是重新调度

if (unlikely(next_task->prio curr->prio)) {

resched_task(rq->curr);

return 0;

}

......

///寻找那个cpu的rq符合条件,将其rq上锁

lowest_rq = find_lock_lowest_rq(next_task, rq);

///如果没有找到合适的rq,我们则需要判断:到底还要不要再找,因为在find_lock_lowest_rq函数中释放了当前rq上的锁,因此可能会导致当前rq上没有需要push的任务,在这种情况下我们就不用再试,如果需要push的任务还在,那么则进入retry继续尝试。

if (!lowest_rq) {

struct task_struct *task;

task = pick_next_pushable_task(rq);

if (task_cpu(next_task) == rq->cpu && task == next_task) {

goto out;

}

if (!task)

goto out;

put_task_struct(next_task);

next_task = task;

goto retry;

}

///执行任务迁移相关的工作。

deactivate_task(rq, next_task, 0);

set_task_cpu(next_task, lowest_rq->cpu);

activate_task(lowest_rq, next_task, 0);

ret = 1;

resched_task(lowest_rq->curr);

double_unlock_balance(rq, lowest_rq);

out:

put_task_struct(next_task);

return ret;

}

2、pull操作

与push操作相反,pull操作用于当前cpu的rq比较空闲,想要主动调入实时任务,该操作主要由

pull_rt_task完成。static int pull_rt_task(struct rq *this_rq)

{

int this_cpu = this_rq->cpu, ret = 0, cpu;

struct task_struct *p;

struct rq *src_rq;

if (likely(!rt_overloaded(this_rq)))

return 0;

///查找每一个超载的cpu

for_each_cpu(cpu, this_rq->rd->rto_mask) {

......

///src_rq:需要pull的cpu。

src_rq = cpu_rq(cpu);

///如果src_rq的下一个任务的优先级高于当前cpu的优先级,则什么都不用做,因为src_cpu会主动执行pull操作。

if (src_rq->rt.highest_prio.next >=

this_rq->rt.highest_prio.curr)

continue;

double_lock_balance(this_rq, src_rq);

///判断是否有需要被pull的任务,没有则退出

if (src_rq->rt.rt_nr_running <= 1)

goto skip;

///找到src_rq上最高优先级的任务

p = pick_next_highest_task_rt(src_rq, this_cpu);

if (p && (p->prio rt.highest_prio.curr)) {

WARN_ON(p == src_rq->curr);

WARN_ON(!p->on_rq);

if (p->prio curr->prio)

goto skip;

ret = 1;

deactivate_task(src_rq, p, 0);

set_task_cpu(p, this_cpu);

activate_task(this_rq, p, 0);

}

skip:

double_unlock_balance(this_rq, src_rq);

}

return ret;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值