04_实验四_时间片轮转

线程调度

实验目的

  • 调试EOS的线程调度程序,熟悉基于优先级的抢先式调度。
  • 为EOS添加时间片轮转调度,了解其它常用的调度算法。

预备知识

基于优先级的抢先式调度

EOS使用双向链表存储同一个优先级的队列,用数组存放32个这种双向链表,并用下标表示不同优先级大小,同时设置一个32位就绪位图表示索引为n的队列中是否有线程

对于不同优先级的线程,优先级越大越优先被调度,同一优先级中的线程则采用FCFS的方式“先来先服务”。

调度程序执行的时机和流程

线程调度运用到了中断,要了解调度的流程首先要了解中断处理的流程。

EOS中有中断处理函数Interrupt,中断时首先调用InterEnter保存中断时CPU现场到KernelContext中,随后调用KiDispatchInterrupt派遣中断至中断处理服务程序,完成调用IntExit退出中断,恢复现场

调度时首先正常执行中断处理流程,在IntExit中调用PspSelectNextThread函数,决定要恢复的CPU现场,即选择一个线程获得CPU,这个函数就是调度程序

中断不仅可以由外部设备产生,也可以由线程主动调用48号软中断产生,这样就实现了线程调度

调度程序的流程可以由伪代码表示如下

PspSelectNextThread
if 被中断线程State == Running then:
	if 存在更高优先级线程 then:
		被中断线程State = Ready
		return 最高优先级就绪队首线程
	else
		return 被中断线程
else
	return 最高优先级就绪队首线程

时间片轮转调度

当线程调度执行时,把CPU分配给队首线程,待线程的时间片用完后,会重新为它分配一个时间片,并将它移动到就绪队列的末尾,从而让新的队首线程开始执行。

实验步骤

为EOS添加时间片轮转调度

给出实现方法的简要描述、源代码、测试及结果等

简要描述及源代码

image-20231206093506391

参考流程图5-11编写即可

// 被中断的线程处于运行态且不为空
if (NULL != PspCurrentThread && Running == PspCurrentThread->State) {
	// 减少时间片
	PspCurrentThread->RemainderTicks--;
	if(PspCurrentThread->RemainderTicks == 0) {
		// 如果时间片为0重置时间片
		PspCurrentThread->RemainderTicks=TICKS_OF_TIME_SLICE;
		// 存在和被中断线程优先级相同的就绪线程
		if(BIT_TEST(PspReadyBitmap, PspCurrentThread->Priority)) {
			// 将被中断线程转入就绪状态,并插入队尾
			PspReadyThread(PspCurrentThread);
		}
	}
}

思考与练习

  1. 结合线程调度执行的时机,说明在 ThreadFunction 函数中,为什么可以使用“关中断”和“开中断”的方法来保护控制台这种临界资源。一般情况下,应该使用互斥信号量(MUTEX)来保护临界资源,但是在ThreadFunction函数中却不能使用互斥信号量,而只能使用“关中断”和“开中断”的方法,结合线程调度的对象说明这样做的原因。

关中断后CPU就不会响应任何由外部设备发出的硬中断,包括定时计数器中断和键盘中断等,也就不会发生线程调度了,从而保证各个线程可以互斥访问控制台。

函数中绝对不能使用互斥信号量来保护临界资源,如果使用了,则那些由于访问临界区而被阻塞的线程,就会被放入互斥信号量的等待队列,就不会在响应优先级的就绪队列中了,而时间片调度算法时对就绪队列的线程进行轮转调度,而不是对这些被阻塞的线程,使用“关中断”和“开中断”不会改变线程状态。

  1. 时间片轮转调度发现被中断线程的时间片用完后,而且在就绪队列中没有与被中断线程优先级相同的就绪线程时,为什么不需要将被中断线程转入“就绪”状态?如果此时将被中断线程转入了“就绪”状态又会怎么样?

在就绪队列中没有与被中断线程优先级相同的就绪线程时,由于不能使其他优先队列的线程等待时间过程,所以不需要将被中断线程转入“就绪”状态,以此来减少线程等待时间。如果将中断线程转入“就绪”状态,则只有当该线程执行完毕后,其他队列的线程才能有机会进入就绪队列。

  1. EOS内核时间片大小取60ms(和Windows操作系统完全相同),在线程比较多时,就可以观察出线程轮流执行的情况(因为此时一次轮转需要60ms,10个线程轮流执行一次需要60×10=600ms,所以EOS的控制台上可以清楚地观察到线程轮流执行的情况)。但是在Windows、Linux等操作系统启动后,正常情况下都有上百个线程在并发执行,为什么觉察不到它们被轮流执行,并且每个程序都运行的很顺利呢?

因为时间片选取合适,线程轮流执行,体现了其虚拟性。

posted @ 2023-12-07 23:25  彬彬zhidao  阅读(571)  评论(0编辑  收藏  举报