操作系统开发系列—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的延迟时间之比)是基本吻合的。

为进程表添加新的成员,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(),加上几条打印语句等等后再次运行,

修改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:

 

源码

posted @ 2016-05-15 15:02  是非猫  阅读(444)  评论(0编辑  收藏  举报