上一篇中我们是用Milli_Delay函数调用系统调用Get_Ticks并在用户级的进程调用Milli_Delay来延迟不同的时间来实现进程优先级的,这其实并不好,进程调度应该是在内核态下执行的,而这里是在用户态实现的。我们就想办法在内核态中实现,我们应该为每个进程设置一个优先级别,因此应该在PCB中添加这个字段,每发生一次调度这个值就减1,那总有减到0的时候,到时候还得恢复原值,还得添加一个字段,这个字段是常量,到时候提供原值,那么就修改PCB结构:
- typedef struct s_proc_item
- {
- Stack_Frame stack_frame;
- u16 LDT_Selector;
- Descriptor ldts[2];
- int ticks;
- int priority;
- }PCB;
接下来在Init_PCB函数中初始化它:
- PCB_Tables[0].ticks = PCB_Tables[0].priority = 150;
- PCB_Tables[1].ticks = PCB_Tables[1].priority = 50;
- PCB_Tables[2].ticks = PCB_Tables[2].priority = 30;
然后修改Clock_Handler中的进程调度部分,不再是时间片轮转了,并把当前进程的PCB的ticks减1:
- void Clock_Handler(u32 irq_no)
- {
- Ticks++;
- p_Resume_PCB->ticks--;
- if(Is_Reenter != 0)
- {
- Disp_Color_Str("!",0xe);
- return;
- }
- PCB *p_PCB;
- int greatest_ticks = 0;
- while(!greatest_ticks)
- {
- for(p_PCB = PCB_Tables ; p_PCB < PCB_Tables + PROC_NUM ; p_PCB++)
- {
- if(p_PCB->ticks > greatest_ticks)
- {
- greatest_ticks = p_PCB->ticks;
- p_Resume_PCB = p_PCB;
- }
- }
- if(!greatest_ticks)
- {
- for(p_PCB = PCB_Tables ; p_PCB < PCB_Tables + PROC_NUM ; p_PCB++)
- {
- p_PCB->ticks = p_PCB->priority;
- }
- }
- }
- }
在此算法中,先遍历PCB表,找到ticks值最高的进程,指定为要恢复的进程,如果每个进程的ticks值都为0,便把每个进程的ticks值恢复为各自进程的priority的值。
既然已经实现优先级,那么就把各个进程的执行体中的延迟函数的参数都改为200吧,修改过程略掉。
编译链接,运行,结果如图所示:
可以看到,每个进程的执行体的延迟时间是一样的,但是还是有优先级的区别。
让我们来统计一下各字母的数量,结果如下:
它们之间的比大概为A:B:C = 2.49:1.4:1,与直观上的优先级比15:5:3 = 5:1.67:1差距较大,为什么会这样呢?休息一下再说。