实验环境:Redhat Linux 9.0
NachOS-4.1
实验内容:
本项目在实践的过程中需要注意以下要点: Nachos中线程管理特点
Nachos中线程管理特点1 ------线程个数没有限制
? 一般的操作系统,进程的数目是有限的,但是Nachos 中线程数目是无限的(没有
限制)(当然,用户进程的数目应该也是有限的。当虚拟机内存以及虚拟内存都耗尽时,就不能产生新的用户线程)。因为线程的控制结构和系统线程的运行是占用宿主机的。能够开多少线程完全由宿主机条件限制,理论上是无限的。
Nachos中线程管理特点2 ------线程调度简单
? 启动了时钟中断的情况下,当时钟中断到来时。如果就绪线程队列中有就绪线程,
就必须进行线程切换。
没有启动时钟中断的情况下,Nachos 使用非抢占式调度。 ? 概念:
非抢占式调度:进程在运行过程中不会切换到其它进程运行,除非其主动放弃处理机或者运行结束
抢占式调度:为了确保没有一个进程单独运行的时间太长,几乎所有的计算机系统都内置了时钟,周期性地进行时钟中断,在每一次时钟中断时,由进程调度程序负
责判断是否有就绪进程比正在运行的进程更加适合占用CPU。
? 缺点:由于进程的运行有不可预见性,有可能一个进程会占用处理机达几个小时,甚
至一个编写错误的进程会一直占用处理机不放,以致其他进程会被饿死。
Nachos中线程管理特点3 ------线程数据结构简单
? Nachos中线程数据结构定义简单,没用户ID,线程ID,无法根据线程ID实现通信,
同步互斥,也没有全局性的线程管理机制。
升级后,Nachos线程管理特点
? 1. Nachos中有了对线程数量的限制,最多同时存在128个用户线程。
? 2. Nachos中线程将以“优先级调度”的抢占式调度方式调度,即是,在中断发生
时,查看就绪队列中等待的线程是否存在优先级较当前线程高的线程,有的话,就使其抢占CPU,不存在的话就并不切换进程 ? 3. 通过真假一个“公共信箱”,总大小为4K,每封信大小为128byte,实现了两个进
程的通信 实现方案
1.对线程数量的限制
由于限制了最多线程数,所以在Thread::Thread(构造函数)上加了信号量的判断处理:当threadnumEmpty(在kernel.h中定义)有效时,即还有空间可以创建新线程时才继续进行线程的构造,不然进入睡眠;当构造操作结束时,将threadnumFull(在kernel.h中定义)信号量激活,即内存中的线程数目加一。
当进行线程析构操作时,先判断threadnumFull(其实默认的认为此时该变量应该有效),结束之后对threadnumEmpty信号量进行更新,即可创建空间数目加一。
threadnumFull和threadnumEmpty变量的初始化是在系统初始化时进行的,此时threadnumFull的初始值为0;threadnumEmpty的初始值为MAX_THREAD_COUNT的值(在kernel.h中定义为128)。
threadnumMutex信号量(在kernel.h中定义)是用于记录系统的整个线程计数变量threadCount(在kernel.h中定义)的控制方面,即每当进行新线程的创建时,在Thread::thread构造函数中用该信号量进行限制,而且threadCount每次加一之后直接成为当前创建中的线程的线程ID。
2.线程以 优先级调度”的抢占式调度方式调度 采用了时间片轮转法,并采用了动态优先权调用。 权限值的设置方式为该值最小的线程的优先级最高(因为List机制上可以实现取出参数值最小的单元)。
当线程创建时初始权限值设置成100(CreatePriority宏,在scheduler.h中定义),进入睡眠之后唤醒时的权限值为60(BlockedPriority宏,在scheduler.h中定义)。
线程切换的最小时间间隔设置于MinSwitchPace宏(在scheduler.h中定义),使得防止频繁的线程切换。
每当时钟中断发生时,将当前的优先级值进行调整,公式为
priority = priority +(当前时间-lastSwitchTick)/PriorityRate (注:PriorityRate宏值设为20)。
再进行就绪队列中线程的权限值都增加AdaptPace(设为5)。 取出下一个线程的成员函数FindNextToRun中的思路为:
当该操作是发生于上一个线程结束后的话,简单的取出就绪队列中的第一个元素;不然,进行与当前进程进行优先级比较,当取出来的线程优先级高时才进行切换。
3.实现通过公共信箱,进程互相访问 系统中开辟长度为4k的空间用作邮箱,每个邮箱的状态由Mail类来负责,读写操作以及其之后其处理由TransportMail和Accept函数来负责。
Thread中设置了两个成员函数SendMail和ReceiveMail,以及一个所收到的消息队列mailList成员变量。
当线程调用SendMail来进行送消息时,先判断有没有空箱,以及有没有先到地写者,之后再利用Transport来进行具体操作。
Transport的流程为先得到空箱位置,在那儿保存该信息之后,通过就绪队列中的搜索,给收信者的消息队列里添加该邮箱号码,此时要使没有找到收信者线程,则认为该消息为垃圾信息,将它删掉;若成功,则将与该邮箱对应的Mail对箱上设置为满的。
当线程调用来接受消息时,将取出自己消息队列中的第一个邮箱号码,然后用AcceptMail函数读入消息,再进行对应邮箱数据的修改。
(一) 要求一相关函数
1) 函数Initialize()——kernel.cc
功能描述:初始化nachos虚拟机 入口参数:无 返回值:无
函数流程: 主流程与原来的函数一样。 添加了初始化变量threadnumMutex, threadnumEmpty, threadnumFull, threadCount的步骤。 2) 构造函数Thread::Thread(char *threadName)
功能描述:Thread类的构造函数 入口参数: char * ――线程名 返回值:无 函数流程:
threadnumEmpty->P(); name = threadName; stackTop = NULL; stack = NULL;
status = JUST_CREATED; #ifdef USER_PROGRAM space = NULL; #endif
priority=CreatePriority; mailList = new List; threadnumMutex->P(); threadCount++; totalThread++;
threadID = threadCount; threadnumMutex->V(); threadnumFull->V();
3)析构函数Thread::~Thread()
功能描述:类Thread析构函数 入口参数: 无 返回值:无 函数流程:
threadnumFull->P(); threadnumEmpty->V();
(二) 要求二相关函数 1) Thread:: Print
功能描述:显示当前线程号、线程名、优先级。 入口参数: 无 返回值:无
函数流程: 一句printf调用。 2) Thread::Sleep 功能描述:线程休眠。 入口参数: 无 返回值:无
函数流程: 主流程与原nachos一样。 添加了修改线程优先级的步骤,即给priority成员变量赋BlockedPriority值。
3) Scheduler::FlushPriority
功能描述:重新计算所有就绪队列中线程的优先级,当时钟中断发生时调用 入口参数: 无 返回值:无 函数流程:
只有一句代码:readyList->Apply((VoidFunctionPtr)UpdatePriority),其中函数指针UpdatePriority是用来重新计算线程的优先级的。 4) Scheduler::ReadyToRun
功能描述:将指定线程加入就绪队列。 入口参数: Thread* 返回值:无 函数流程:
1,将线程状态改为就绪态。
2,用插入排序法根据优先级排序就绪队列中的线程。 5) Scheduler::FindNextToRun
功能描述:返回下一个要运行的线程给CPU
相关推荐: