多核进程调度中,相关task_struct 结构中代表进程与CPU之间关系的变量
struct task_struct{
...
int has_cpu, processor;
unsigned long cpus_allowed;
...
}
has_cpu:表示当前进程在CPU上正在运行;
processor:表示在哪个CPU上运行;
cpus_allowed:一个位图变量,其中一位,置1,表示允许这个进程接受调度在置1编号的CPU上运行。
系统中的进程调度
当一个CPU通过schedule()从系统的就绪队列中挑选一个进程作为运行的下一个进程next,其task_struct结构中的has_cpu字段置成1,并将processor设置成该CPU的逻辑编号。进行任务切换也就是进程状态、内存、寄存器、堆栈的切换,以及TLB的是否刷新等等。
asmlinkage void schedule(void)
{
...
/*
* 1.Default process to select..
*/
next = idle_task(this_cpu);
...
/*
* 2.从运行队列中找到能够调度运行的进程next。
*/
list_for_each(tmp, &runqueue_head) {
____p = list_entry(tmp, struct task_struct, run_list);
____if (can_schedule(p, this_cpu)) {
________int weight = goodness(p, this_cpu, prev->active_mm);
________if (weight > c)
____________c = weight, next = p;
____}
}
...
/*
* 3.如果是多核处理器,则更新进程 task_struct 中的标志
*/
next->has_cpu = 1
next->processor = this_cpu;
...
/*
* 4. prepare_to_switch()
*/
____{
________struct mm_struct *mm = next->mm;
________struct mm_struct *oldmm = prev->active_mm;
________if (!mm) { /* 如果是内核线程*/
____________if (next->active_mm) BUG();
____________next->active_mm = oldmm;
____________atomic_inc(&oldmm->mm_count);
____________enter_lazy_tlb(oldmm, next, this_cpu);/*暂时先不更新TLB*/
________} else { /*如果是用户空间线程*/
____________if (next->active_mm != mm) BUG();
____________switch_mm(oldmm, mm, next, this_cpu);/**/
________}
________if (!prev->mm) {
____________prev->active_mm = NULL;
____________mmdrop(oldmm);
________}
____}
...
/*
* 5.
____ * This just switches the register state and the
____ * stack.
____ */
____switch_to(prev, next, prev);
/*
* 6. 尝试再次运行:在剩下的CPU中,寻找能替换的进程,也就是“运行优先级”最低的进程。
*/
______schedule_tail(prev);
...
}
根据在CPU中运行的prev进程与next进程的不同,所处理细节也不同。prev进程发生切换的方式主要如下:
- 自愿礼让: (prev->policy &= ~SCHED_YIELD) && (prev->state = TASK_RUNNING)
- 被剥夺: (prev->policy & SCHED_YIELD == FALSE) && (prev->state = TASK_RUNNING)
2.被剥夺再次尝试运行:reschedule_idle()
2.1 首先尝试在当前CPU再次运行
can_schedule(p, p->processor)
2.2 如果不能在当前CPU运行,则考察系统中所有CPU。如果找到能运行的CPU,当前这个CPU上运行的进程为被剥夺的候选对象。找出所有可被剥夺的所有候选对象中最合适的那个,然后替换执行。
被替换进程最合适的标准:运行时间最长,资格最低的进程。