操作系统开发系列—13.i.进程调度 ●

上面的三个进程都是延迟相同的时间,让我们修改一下,尝试让它们延迟不同的时间。

void TestA()
{
int i = 0;
while (1) {
disp_str("A.");
milli_delay(300);
}
} void TestB()
{
int i = 0x1000;
while(1){
disp_str("B.");
milli_delay(900);
}
} void TestC()
{
int i = 0x2000;
while(1){
disp_str("C.");
milli_delay(1500);
}
}

运行后,数一数可以知道,输出*有A字母140个,B字母51个,C字母32个,所以A和B的个数之比是2.745,A和C的个数之比是4.345,这两个数字与3(进程B和A的延迟时间之比)和5(进程C和A的延迟时间之比)是基本吻合的。

操作系统开发系列—13.i.进程调度 ●

为进程表添加新的成员,proc.h:

typedef struct s_proc {
STACK_FRAME regs; /* process registers saved in stack frame */ u16 ldt_sel; /* gdt selector giving ldt base and limit */
DESCRIPTOR ldts[LDT_SIZE]; /* local descriptors for code and data */ int ticks; /* remained ticks */
int priority; u32 pid; /* process id passed in from MM */
char p_name[16]; /* name of the process */
}PROCESS;

在进程表中添加了两个成员:ticks是递减的,从某个初值到0.为了记住ticks的初值,我们另外定义一个变量priority,它是恒定不变的。当所有的进程ticks都变为0之后,再把各自的ticks赋值为priority,然后继续执行。

ticks和priority最初赋值如下,main.c的kernel_main():

	proc_table[0].ticks = proc_table[0].priority = 150;
proc_table[1].ticks = proc_table[1].priority = 50;
proc_table[2].ticks = proc_table[2].priority = 30;

对于进程调度,我们可以单独写一个函数,叫做schedule(),放在proc.c中:

PUBLIC void schedule()
{
PROCESS* p;
int greatest_ticks = 0; while (!greatest_ticks) {
for (p = proc_table; p < proc_table+NR_TASKS; p++) {
if (p->ticks > greatest_ticks) {
greatest_ticks = p->ticks;
p_proc_ready = p;
}
} if (!greatest_ticks) {
for (p = proc_table; p < proc_table+NR_TASKS; p++) {
p->ticks = p->priority;
}
}
}
}

同时修改时钟中断处理函数,clock.c:

PUBLIC void clock_handler(int irq)
{
ticks++;
p_proc_ready->ticks--; if (k_reenter != 0) {
return;
} schedule();
}

同时我们将所有进程的延迟时间全改为相同的值,把所有milli_delay的参数改成200.

make运行的结果发现,虽然各个进程延迟的时间都相同,但由于改变了它们的优先级,运行的时间明显不同,这说明我们的优先级策略生效了!

但是,当前的A、B、C三个字母的个数之比是139:71:54,大体相当于2.57:1.31:1,与进程优先级5:1.67:1(15:5:3)相差比较大。为什么呢,首先修改各个进程,让它们各自打印一个当前的ticks。然后修改一下schedule(),加上几条打印语句等等后再次运行,

操作系统开发系列—13.i.进程调度 ●

操作系统开发系列—13.i.进程调度 ●

修改clock_handler,clock.c:

PUBLIC void clock_handler(int irq)
{
ticks++;
p_proc_ready->ticks--; if (k_reenter != 0) {
return;
} if (p_proc_ready->ticks > 0) {
return;
} schedule(); }

这样,在一个进程的ticks还没有变成0之前,其他进程就不会有机会获得执行。

从运行结果可以明显看出,进程A先执行,然后是B,再然后是C,与原先有了很大的差别。原因在于进程A的ticks从150递减至0之后,才把控制权给B,B用完它的ticks(50)之后再给C,然后各自的ticks被重置,继续下一个类似的过程。可以看到,进程A在150ticks内执行8次循环,B在50ticks内执行3次循环,C在30ticks内执行2次循环。这样就很直观了。

我们再把它们的优先级改小一点:

	proc_table[0].ticks = proc_table[0].priority = 15;
proc_table[1].ticks = proc_table[1].priority = 5;
proc_table[2].ticks = proc_table[2].priority = 3;

然后把各个进程的延迟时间改成10ms:

void TestA()
{
int i = 0;
while (1) {
disp_str("A.");
milli_delay(10);
}
}

运行结果如下,可以看出,现在打印出的字符的个数之比非常接近15:5:3:

操作系统开发系列—13.i.进程调度 ●

源码

上一篇:CCNA笔记


下一篇:ES2015 中的函数式Mixin