函数goodness()就是用来衡量一个处于可运行状态的进程值得运行的程度。该函数综合使用了上面我们提到的五项,给每个处于可运行状态的进程赋予一个权值(weight),调度程序以这个权值作为选择进程的唯一依据。函数主体如下(为了便于理解,笔者对函数做了一些改写和简化,只考虑单处理机的情况):
static inline int goodness(struct task_struct * p, struct
mm_struct *this_mm)
{ int weight; /* 权值,作为衡量进程是否运行的唯一依据 *
weight=-1;
if (p->policy&SCHED_YIELD)
goto
out; /*如果该进程愿意“礼让(yield)”,则让其权值为-1 */
switch(p->policy)
{
/*
实时进程*/
case SCHED_FIFO:
case SCHED_RR:
weight = 1000 + p->rt_priority;
/*
普通进程 */
case SCHED_OTHER:
{ weight = p->counter;
if(!weight)
goto out
/*
做细微的调整*/
if (p->mm=this_mm||!p->mm)
weight = weight+1;
weight+=20-p->nice;
}
}
out:
return weight; /*返回权值*/
}
其中,在sched.h中对调度策略定义如下:
#define SCHED_OTHER
0
#define SCHED_FIFO
1
#define SCHED_RR
2
#define SCHED_YIELD
0x10
这个函数比较很简单。首先,根据policy区分实时进程和普通进程。实时进程的权值取决于其实时优先级,其至少是1000,与conter和nice无关。普通进程的权值需特别说明两点:
(1) 为什么进行细微的调整?如果p->mm为空,则意味着该进程无用户空间(例如内核线程),则无需切换到用户空间。如果p->mm=this_mm,则说明该进程的用户空间就是当前进程的用户空间,该进程完全有可能再次得到运行。对于以上两种情况,都给其权值加1,算是对它们小小的奖励。
(2) 进程的优先级nice是从早期Unix沿用下来的负向优先级,其数值标志“谦让”的程度,其值越大,就表示其越“谦让”,也就是优先级越低,其取值范围为-20~+19,因此,(20-p->nice)的取值范围就是0~40。可以看出,普通进程的权值不仅考虑了其剩余的时间片,还考虑了其优先级,优先级越高,其权值越大。
有了衡量进程是否应该运行的标准,选择进程就是轻而易举的事情了,弱肉强食,谁的权值大谁就先运行。
根据进程调度的依据,调度程序就可以控制系统中的所有处于可运行状态的进程并在它们之间进行选择。