操作系统nachos课程设计实验报告

合集下载

Nachos实验报告10

Nachos实验报告10

计算机科学与技术学院实验报告:10实验题目:具有二级索引的文件系统姓名:李威日期:2013-12-1 学号:201100300259Email:sduliwei@实验目的:Nachos的文件系统中保存文件内容所在扇区索引的“文件头“目前只占用一个扇区,为了可以使Nachos文件系统创建较大的文件,将”文件头”扩大到两个扇区,也就是实现二级索引。

硬件环境:软件环境:Linux操作系统,Nachos操作系统实验步骤:1,通过实验5的扩展文件大小的实验,了解了nachos 系统的对文件系统的管理。

本次实验的目的主要是扩大Nachos系统可以创建的文件的大小,使用两个扇区来保存文件头的信息。

为了达到这个目的,首先了解nachos 自带的文件系统的文件头的结构:保存在一个扇区中,第一个int保存了文件的字节数(numBytes),第二个int保存了使用的扇区数(numSectors),第三个数据结构是文件所在的各个扇区号(dataSectors[NumDiresct])。

也就是说,Nachos系统采用的是索引式的文件管理方式。

因而,要实现nachos文件系统的二级索引,可以使第一个索引节点(也就是原有的文件头那个扇区)的dataSectors数组的最后一个元素保留第二个索引节点(也就是第二个扇区)的引用(也就是扇区号)。

如果文件大小不超过一个索引节点可以保留的内容,则这个最后一个元素的值为-1。

2,通过分析可知,需要修改中的内容。

代码如下:boolFileHeader::Allocate(BitMap *freeMap, int fileSize){numBytes = fileSize;numSectors = divRoundUp(fileSize, SectorSize);if (freeMap->NumClear() < numSectors)return FALSE; // not enough space/*如果文件大小超过索引节点中保存扇区号的数目,则返回false*/else if(NumDirect + NumDirect2 <= numSectors)return FALSE;//the filesys cannot support such big file/*toNextNode 是保留第二个索引节点的扇区号*/int toNextNode=NumDirect-1; //toNextNode is the Sector number of the second node of the filehd//if the second node is not needed, then dataSector[toNextNode]=-1if(numSectors < toNextNode){for (int i = 0; i < numSectors; i++)dataSectors[i] = freeMap->Find();//为文件分配扇区dataSectors[toNextNode] = -1;}//If the numSectors excends the rage of dataSectors,else{for (int i = 0; i < toNextNode; i++)dataSectors[i] = freeMap->Find();dataSectors[toNextNode] = freeMap->Find();//找一个空闲的扇区,作为第二个扇区,索引节点//this is the content,i.e.filehdr of the allocated sectors, of the second nodeint dataSectors2[NumDirect2];for (int i = 0; i < numSectors - NumDirect; i++)dataSectors2[i] = freeMap->Find();//为文件分配扇区//the fefault synchDisk->WriteSector do not include the second node//so write back the new build nodesynchDisk->WriteSector(dataSectors[toNextNode], (char *)dataSectors2); }return TRUE;/*revised*/}voidFileHeader::Deallocate(BitMap *freeMap){/*toNextNode 是保留第二个索引节点的扇区号*/int toNextNode= NumDirect - 1;// test if has the second nodeif(dataSectors[toNextNode]==-1){for (int i = 0; i < numSectors; i++){ASSERT(freeMap->Test((int) dataSectors[i])); // ought to be marked!freeMap->Clear((int) dataSectors[i]);}}//has a second node, then find it, then clean the bitmap, thenelse{//clear the first n-1 bit,remain the toNextNodeint i=0;for ( ; i < toNextNode; i++){ASSERT(freeMap->Test((int) dataSectors[i])); // ought to be marked!freeMap->Clear((int) dataSectors[i]);}int dataSectors2[NumDirect2];synchDisk->ReadSector(dataSectors[toNextNode], (char *)dataSectors2);freeMap->Clear((int) dataSectors[toNextNode]);//clear the toNextNodefor( ; i < numSectors; i++)freeMap->Clear((int) dataSectors2[i-toNextNode]);//toNextNode==the number of filehdr item }}intFileHeader::ByteToSector(int offset){ASSERT(offset<=numBytes);/*toNextNode 是保留第二个索引节点的扇区号*/int toNextNode = NumDirect - 1; //test if offset excedes the first nodeif(offset / SectorSize < toNextNode)return(dataSectors[offset / SectorSize]);else{int dataSectors2[NumDirect2];synchDisk->ReadSector(dataSectors[toNextNode], (char *)dataSectors2);return (dataSectors2[offset / SectorSize - toNextNode]);}}voidFileHeader::Print(){/*revised*/int i, j, k;/*toNextNode 是保留第二个索引节点的扇区号*/int toNextNode = NumDirect - 1;char *data = new char[SectorSize];//test if there is a second nodeif(dataSectors[toNextNode] == -1){printf("FileHeader contents. File size: %d. File blocks:\n", numBytes); for (i = 0; i < numSectors; i++)printf("%d ", dataSectors[i]);printf("\nFile contents:\n");for (i = k = 0; i < numSectors; i++) {synchDisk->ReadSector(dataSectors[i], data);for (j = 0; (j < SectorSize) && (k < numBytes); j++, k++) {if ('\040' <= data[j] && data[j] <= '\176') // isprint(data[j])printf("%c", data[j]);elseprintf("\\%x", (unsigned char)data[j]);}printf("\n");}}// If there is a secondary index,// first read in the dataSectors2 from the Disk.// Then, deallocate the data blocks for this file.// At last, deallocate the block that dataSector2 locates.else{int dataSectors2[NumDirect2];synchDisk->ReadSector(dataSectors[toNextNode], (char *)dataSectors2);//1, print the filedre itemsprintf("FileHeader contents. File size: %d. File blocks:\n", numBytes);for (i = 0; i < toNextNode; i++)printf("%d ", dataSectors[i]);for(; i < numSectors; i++)printf("%d ", dataSectors2[i - toNextNode]);printf("\nFile contents:\n");//2,print the content of the first node pointedfor (i = k = 0; i < toNextNode; i++) {synchDisk->ReadSector(dataSectors[i], data);for (j = 0; (j < SectorSize) && (k < numBytes); j++, k++) {if ('\040' <= data[j] && data[j] <= '\176') // isprint(data[j])printf("%c", data[j]);elseprintf("\\%x", (unsigned char)data[j]);}printf("\n");}//3,print the content of the second node pointedfor( ; i < numSectors; i++) {synchDisk->ReadSector(dataSectors2[i - toNextNode], data);for (j = 0; (j < SectorSize) && (k < numBytes); j++, k++) {if ('\040' <= data[j] && data[j] <= '\176') // isprint(data[j])printf("%c", data[j]);elseprintf("\\%x", (unsigned char)data[j]);}printf("\n");}}delete [] data;/*revised*/}boolFileHeader::AppSectors(BitMap *freeMap, int appFileSize){/*revised*/if(appFileSize <= 0)return false;int restFileSize = SectorSize * numSectors - numBytes;if(restFileSize >= appFileSize){numBytes += appFileSize;return true;}else{int moreFileSize = appFileSize - restFileSize;if(freeMap->NumClear()< divRoundUp(moreFileSize, SectorSize))return FALSE;else if(NumDirect + NumDirect2 <= numSectors + divRoundUp(moreFileSize, SectorSize)) return FALSE;int i = numSectors;numBytes += appFileSize;numSectors += divRoundUp(moreFileSize, SectorSize);/*toNextNode 是保留第二个索引节点的扇区号*/int toNextNode = NumDirect-1; //test if has the second nodeif(dataSectors[toNextNode] == -1){//test if need the second nodeif(numSectors < toNextNode)for( ; i < numSectors; i++)dataSectors[i] = freeMap -> Find();//need the second nodeelse{for( ; i< toNextNode ; i++)dataSectors[i]= freeMap ->Find();dataSectors[toNextNode] = freeMap ->Find();int dataSectors2[NumDirect2];for ( ; i < numSectors ; i++)dataSectors2[i - toNextNode] = freeMap->Find();synchDisk->WriteSector(dataSectors[toNextNode], (char *)dataSectors2);}}/** If before appending, there is already a secondary index*///First read the dataSectors2 from the Disk.//Then, append the file size.//At last, write back the secondary index block into the sector,else{int dataSectors2[NumDirect2];synchDisk->ReadSector(dataSectors[toNextNode], (char *)dataSectors2);for( ; i < numSectors; i++)dataSectors2[i-toNextNode] = freeMap -> Find();//the var toNextNode==the number of int that synchDisk->WriteSector(dataSectors[toNextNode], (char *)dataSectors2);//the fefault synchDisk}}return TRUE;/*revised*/}运行结果:首先运行命令 ./nachos –f 格式化Nachos磁盘然后运行 ./nachos –ap test/big big 若干次,知道出现提示,文件太大不能再追究为止。

Nachos实验报告9

Nachos实验报告9

计算机科学与技术学院实验报告:9实验题目:设计并实现具有优先级的线程调度策略姓名:李威日期:2013-12-1 学号:201100300259 班级:11级软件3班Email:sduliwei@实验目的:Nachos系统采用基本的FCFS的线程调度策略,修改成为具有优先级的线程调度策略硬件环境:软件环境:linux操作系统,Nachos操作系统实验步骤:1.修改Thread类的构造函数,加入优先级priority属性,并且加入getPrioty方法。

以便在线程的等待队列中找到优先级最高的线程。

其中,线程优先级的范围从1到7,默认为7,即最低优先级。

修改代码如下:(,thread.h)class Thread {……………………………………public:Thread(char* debugName, int priority=7);// initialize a Thread …………………………………………………int getPriority(){return this->priority;}Thread::Thread(char* threadName, int p){if(p<1) priority = 1;else if(p>7) priority = 7;else priority = p;name = threadName;stackTop = NULL;stack = NULL;status = JUST_CREATED;#ifdef USER_PROGRAMspace = NULL;#endif}2,首先,了解Nachos系统原来的线程调度方式。

通过读,,文件中的内容了解线程调度的方式。

首先,修改 文件中的ThreadTest方法,创建有优先级的Thread,代码如下:然后,从Thread类中找到Fork方法,代码如下:这说明ThreadTest方法的目的是,实例化新的线程,调用Fork方法,也就是让新产生的线程去执行SimpleThread方法,并且把当前执行的线程加入到等待队列。

nachos系统实验报告:实验二

nachos系统实验报告:实验二

实验二一.实验目的将nachos 中的lock 和condition 类的实现补充完整,并利用这些同步机制实现两个基础功能。

二.实验内容1) 实现syncy.h 中的Lock 和Condition 类,并利用这些同步机制将实验一中所双向有序链表类修改成可以在多线程线程环境下运行。

2) 实现一个线程安全的Table 。

Table 有一个固定大的Entery 数组。

3) 实现一个大小受限的BoundBuffer ,可以完成读.写功能,其中读写的size 可以超过设定的buffer 大小,当读的东西太快或写的太慢时,就将其挂起。

当buffer 里重新有写的空间或读的空间时在将其线程放入就绪队列中。

三.实验结果1.锁机制的实现 **因为lock 和condition 都有两个版本,所以当调用取得锁和释放锁的函数时我 用的是GetLock()和ReleaseLock(),而不是lock->Acquire(),Condition 同理用的是Signal ()和Wait ()。

这些函数会根据运行程序时输入的参数来决 定用哪个版本的锁或者不用锁。

a)主要代码分析 Lock 类的主要成员{public : void Acquire(); // 得到锁 void Release(); // 解放锁private: Thread *LockedThread ; // 用于储存现在拥有 lock 的线程 LockStatus status ; // 表示此时lock 的状态(Busy ,Free ) List *queue // 用于保存挂起的 线程}Lock 类中Acquire 函数得到锁,如果此时别的线程拥有锁,则此时线程被 挂起放在queue 队列中,直到有人释放锁时,Release 函数将queue 中的一 个线程加入就绪队列,每次只能由一个线程得到锁。

Condition 类主要成员{ public: void Wait(LockO *conditionLock); void Signal(LockO *conditionLock); private:List *queue ; char* name;}Condition 类的所有操作都在线程得到锁时进行操作,且运行其函数时,都 先检测 lock 是否被currentThread 锁拥有。

nachos实验报告

nachos实验报告

nachos实验报告nachos实验报告一、引言操作系统是计算机系统中的核心软件之一,它负责管理计算机的硬件资源和提供各种服务。

为了更好地理解操作系统的原理和设计,我们在课程中进行了一系列的实验,其中之一就是使用nachos操作系统进行实验。

本报告将对我们在nachos实验中的学习和体验进行总结和分享。

二、nachos简介nachos是一个教学用的操作系统,它是为了帮助学生更好地理解操作系统的原理和设计而开发的。

nachos的设计简单、模块化,易于理解和扩展。

通过使用nachos,我们可以深入了解操作系统的各个组成部分,如进程管理、内存管理、文件系统等,并通过实验来加深对这些概念的理解。

三、实验一:进程管理在第一个实验中,我们学习了进程管理的基本原理和实现。

通过使用nachos,我们可以创建和管理多个进程,并学习它们之间的通信和同步机制。

我们了解了进程的状态转换、进程调度算法以及进程间通信的方法,如共享内存和消息传递等。

通过实验,我们更深入地理解了进程管理的重要性和挑战。

四、实验二:内存管理在第二个实验中,我们学习了内存管理的原理和实现。

nachos提供了虚拟内存的支持,我们可以通过设置页表和实现页面置换算法来管理内存。

我们了解了内存分页和分段的概念,以及常见的页面置换算法,如FIFO、LRU等。

通过实验,我们深入了解了内存管理的工作原理和性能优化方法。

五、实验三:文件系统在第三个实验中,我们学习了文件系统的原理和实现。

nachos提供了一个简单的文件系统接口,我们可以通过创建、读取和写入文件来学习文件系统的操作。

我们了解了文件系统的组织结构,如目录、文件和索引节点等,并学习了文件系统的一致性和恢复机制。

通过实验,我们更好地理解了文件系统的工作原理和性能优化方法。

六、实验四:网络通信在第四个实验中,我们学习了网络通信的原理和实现。

nachos提供了一个简单的网络模拟器,我们可以创建和管理多个网络节点,并通过网络进行通信。

Nachos文件系统实习报告

Nachos文件系统实习报告
• 在本次实习中,我深入了解了Nachos文件 系统的设计、实现和应用。通过实践操作 ,我掌握了Nachos文件系统的基本原理和 核心功能,并对其在实际应用中的优缺点 有了更深刻的认识。
THANK YOU
感谢观看
实习目的
01 掌握Nachos文件系统的基本原理和架构。
02 了解文件系统的数据结构、存储管理、I/O 操作等核心组件。
03
通过实践操作,提高解决实际问题的能力 。
04
培养对文件系统领域的兴趣,为未来的学 习和工作打下基础。
02
Nachos文件系统概述
Nachos文件系统简介
01
Nachos文件系统是一种分布式文件系统,旨在为大
灵活性
支持多种存储介质和存储架构,可根据实际 需求进行配置和扩展。
易用性
提供友好的用户界面和丰富的API接口,方 便用户进行开发和集成。
Nachos文件系统的应用场景
科学计算
适用于气象、生物信息学、物理模拟等领域,提供大规模数据存储和处理能力。
云计算
作为云平台的底层存储基础设施,为虚拟机和容器提供文件存储服务。
Nachos文件系统 实习报告
汇报人: 202X-01-07
目 录
• 引言 • Nachos文件系统概述 • 实习内容与过程 • 实习成果与收获 • 总结与展望
01
引言
实习背景
• 在当今信息时代,文件系统作为 计算机存储和管理数据的关键组 件,其重要性不言而喻。 Nachos是一款模拟真实文件系 统的开源软件,为学习和研究文 件系统提供了良好的实验平台。 本次实习旨在通过实践Nachos 文件系统,深入了解文件系统的 基本原理、实现机制以及性能优 化等方面的知识。

实验三-操作系统实验Nacho

实验三-操作系统实验Nacho

实验内容 利用事实验三 操作系统实验Nacho、实验人员:、实验目的:本次实验的目的在于掌握使用 nachos 中的线程序解决较为复杂的并发问题。

分三部分:实现事件栅栏原语并进行正确性测试; 实现闹钟原语并进行正确性测试; 件栅栏和闹钟原语来解决电梯问题(详细内容请看 nachos-labs.pdf )。

三、实验内容:1. 实现事件栅栏原语2. 实现闹钟原语3. 解决电梯问题四、实验步骤:1. 实现事件栅栏原语#ifndef EVENTBARRIER_H#defi ne EVENTBARRIER_H#in clude "syn ch-sem.h"#defi ne SIGNALED 1#defi ne UNSIGNALED 0 class Eve ntBarrier{ public:Eve ntBarrier();~Eve ntBarrier();void Wait();void Sig nal();void Complete。

;int Waiters。

; private:bool state;Con diti on *waits;Con diti on *waitc;Lock *barrier;Lock *in barrier;int waiter;};#en dif#i nclude "Eve ntBarrier.h"#in clude "thread.h"Even tBarrier::Eve ntBarrier()waits=new Con diti on ("waitsig nal");waitc=new Condition("waitcomplete");barrier=new Lock("barrier"); inbarrier=new Lock("inbarrier");state=UNSIGNALED;waiter=0;}EventBarrier::~EventBarrier() {delete waits;delete waitc;}void EventBarrier::Wait(){barrier->Acquire();waiter++;while(state==UNSIGNALED)waits->Wait(barrier);barrier->Release();}void EventBarrier::Signal()barrier->Acquire();state=SIGNALED;waits->Broadcast(barrier);barrier->Release();inbarrier->Acquire();waitc->Wait(inbarrier);inbarrier->Release();state=UNSIGNALED;}void EventBarrier::Complete(){inbarrier->Acquire();waiter--;if(waiter==0){waitc->Broadcast(inbarrier);}else{waitc->Wait(inbarrier);}inbarrier->Release();int Even tBarrier::Waiters(){return waiter;}2. 实现闹钟原语#defi ne ALARM_H#in clude "system.h"#i nclude "list.h" class Alarm{ public:Alarm();~Alarm();void Pause(i nt howL on g); void Wakeup();int Getpause num(); private:List *queue;int pause num;int leftime;};#en dif#in elude "system.h"#in elude "thread.h"#in elude "Alarm.h"exter n Alarm *alarm;void check(i nt which){while(alarm->Getpause num ()!=0){curre ntThread->Yield();}curre ntThread->Fi nish();}Alarm::Alarm(){queue=new List();pause num=0;}Alarm::~Alarm()queue->~List();}void Alarm::Pause(int howLong){Thread *t;pausenum++;if(pausenum==1){t=new Thread("forked thread");t->Fork(check,0);}if(howLong<=0)return;leftime=stats->totalTicks+howLong*TimerTicks*10000;IntStatus oldlevel=interrupt->SetLevel(IntOff);queue->SortedInsert(currentThread,leftime);currentThread->Sleep();(void) interrupt->SetLevel(oldlevel);}void Alarm::Wakeup()Thread *thread;int ptime=-1;IntStatus oldLevel = interrupt->SetLevel(IntOff);thread = (Thread *)queue->SortedRemove(&ptime);(void) interrupt->SetLevel(oldLevel);while( thread != NULL ){if(stats->totalTicks>=ptime){scheduler->ReadyToRun(thread);pausenum--;oldLevel = interrupt->SetLevel(IntOff);thread = (Thread *)queue->SortedRemove(&ptime);(void) interrupt->SetLevel(oldLevel);continue;}else{oldLevel = interrupt->SetLevel(IntOff);queue->SortedInsert(thread,ptime);(void) interrupt->SetLevel(oldLevel);break;}intAlarm::Getpause num() {retur n pause num;}3. 实现单个电梯class Elevator{public:Elevator(char *debug name,i nt nu mfloors,i nt myid);~Elevator();char *getName() { return n ame; }void OpenDoors(); /* 电梯开门 */void CloseDoors(int i); /* 电梯关门 */bool VisitFloor(int floor); /*查看电梯是否访问某层 */bool Enter(int id); /* 乘客进入电梯 */void Exit(int id); /* 乘客离开电梯 */void RequestFloor(int floor); /* 乘客阻塞在电梯内部 */ intGetlD(){return id;}void SetState(int i);bool IFEMPTY();void GoUp();void GoDown();private:char *name;int id;int numFloorsint currentfloor;int occupancy;int MaxNumber;int states; /* 设置电梯状态*//* 电梯是否为空*//* 电梯上行*//* 电梯下行*/; /* 电梯所能到达的最大楼层*//* 目前所在楼层*//* 目前乘客数目*//* 最大乘客数目*//* 电梯状态*/int GetFloor(){return currentfloor;}int GetState(){return states;}EventBarrier *eventbarrier; /* 电梯栅栏 */bool *ifvisitfloor;/* 判断电梯是否停留某楼层的数组 */Lock *occlock;};class Buildingpublic:Building(char *debugname,int numfloors,int numelevators);~Building();char *getName() { return name; }void CallUp(int fromFloor);void CallDown(int fromFloor);Elevator *AwaitUp(int fromFloor); /* 乘客等待,阻塞 ,返回电梯指针 */ Elevator *AwaitDown(int fromFloor); /* 乘客等待,阻塞,返回电梯指针 */ bool GetDownLight(int floor){return DownLight[floor];}bool GetUpLight(int floor){return UpLight[floor];}void SetDownLight(int t,bool i);void SetUpLight(int t,bool i);void WakeUp();void WakeDown();Elevator *TellElevator();private:char *name;int NumElevators; /* 电梯数目 */int NumFloors; /* 楼层数目 */EventBarrier *eventbarrier_up;/* 上行栅栏 */EventBarrier *eventbarrier_down;/* 下行栅栏 */Elevator *elevator; /* 一个电梯 */bool *UpLight; /*楼层上行按键*/};#i nclude "syn ch-sleep.h" #in clude "system.h" #i nclude "Eve ntBarrier.h" Even tBarrier::Eve ntBarrier(){eve ntlock=new Lock("eve ntlcok"); complete=new Con diti on ("complete");sig nal=new Con diti on ("sig nal"); SIGNALED=false;waiters_co un t=0;}Even tBarrier::~Eve ntBarrier(){delete even tlock;delete sig nal;delete complete;void EventBarrier::Wait(){eventlock->Acquire();waiters_count++;while(!SIGNALED)/* 如果事件栅状态是 UNSIGNALED, 则阻塞 */signal->Wait(eventlock);eventlock->Release();}void EventBarrier::Signal(){eventlock->Acquire();SIGNALED=true;/* 设置事件栅栏的状态为 SIGNALED*///printf("\n set SIGNALED=true,waiting for all forks WakeUp");signal->Broadcast(eventlock);/* 唤醒所有阻塞于 Signal 的线程 */ complete->Wait(eventlock); /* 阻塞于 Complete*///printf("\n has already signaled all waiting forks");SIGNALED=false;/* 恢复事件栅栏的状态为 UNSIGNALED*///printf("\n has already reset SIGNALED=false\n"); eventlock->Release(); }void EventBarrier::Complete()eve ntlock->Acquire();waiters_co un t--;if(waiters_count==O)/* 最后一个应答,唤醒所有阻塞在complete 的线程*/ complete->Broadcast(eve ntlock);else if(waiters_cou nt>0)/* 并非最后一个应答,阻塞在 complete*/complete->Wait(eve ntlock);elseprin tf("\n waiters_cou nt error!");eve ntlock->Release();}int Even tBarrier::Waiters(){retur n waiters_co unt;}五、实验结果1. 事件栅栏测试结果2•闹钟测试结果3.电梯测试结果普通情况严C^1L4018@C56;电梯满六、实验总结本次实验关于电梯的程序难度较大,特别是电梯部分。

nachos-Lab8实习报告

nachos-Lab8实习报告

通信机制实习报告目录内容一:总体概述 (3)内容二:任务完成情况 (3)任务完成列表(Y/N) (3)具体Exercise的完成情况 (3)内容三:遇到的困难以及解决方法 (9)内容四:收获及感想 (10)内容五:对课程的意见和建议 (10)内容六:参考文献 (10)内容一:总体概述本次lab的主要内容是实现线程之间的消息传递,主要分为理论和实践两个部分,理论方面,我们需要了解Linux消息传递机制,实践方面,我们需要利用nachos模拟Linux消息传递机制并进行相关测试。

内容二:任务完成情况任务完成列表(Y/N)Exercise1 Exercise2 Exercise3Y Y Y具体Exercise的完成情况本实习希望通过修改Nachos系统平台的底层源代码,达到“实现通信机制”的目标。

Exercise 1 调研Linux中进程通信机制的实现Linux中进程通信机制主要包括消息传递,共享内存,管道和套接字(1)消息传递消息传递通过消息缓冲区实现。

消息缓冲区是消息的链表,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。

Linux维护消息队列向量表(msgque)表示系统中所有的消息队列。

消息克服了信号信息少,管道只能支持无格式字节流和缓冲区受限的缺点。

(2)共享内存相互通信的进程间需要建立公共内存区域,来实现进程间的信息交换。

进程可以向该共享内存区域写也可以从该共享内存区域读。

共享内存是最快的IPC 机制,但由于linux本身不能实现对其同步控制,需要用户程序进行并发访问控制,因此它一般结合了其他通信机制实现了进程间的通信,例如信号量。

(3)管道管道是Linux支持的最初IPC方式,利用缓冲传输介质(内存或文件)连接两个相互通信的进程,管道可分为无名管道和有名管道。

无名管道是半双工的,只能支持数据的单向流动,两进程间需要通信时需要建立起两个管道。

无名管道使用pipe()函数创建,只能用于父子进程或者兄弟进程之间。

nachos 实验报告

nachos 实验报告

nachos 实验报告
《Nachos 实验报告》
在计算机科学领域,操作系统是一个非常重要的概念。

它是计算机系统的核心组成部分,负责管理计算机的资源并提供用户和应用程序之间的接口。

为了更好地理解操作系统的工作原理,我们进行了一项名为Nachos的实验。

Nachos是一个用于教学目的的操作系统内核。

它是在加州大学伯克利分校开发的,旨在帮助学生学习操作系统的基本概念和原理。

在这个实验中,我们使用Nachos来深入了解操作系统的各个方面,包括进程管理、内存管理、文件系统和网络通信等。

首先,我们学习了Nachos的基本结构和架构。

它由多个模块组成,每个模块负责不同的功能。

通过阅读Nachos的源代码和文档,我们逐渐理解了操作系统内核的组成和工作原理。

接着,我们进行了一系列的实验,来探索Nachos的各种功能。

我们实现了进程管理模块,通过创建和调度多个进程来理解进程的概念和调度算法。

我们还实现了内存管理模块,通过分配和释放内存来了解内存管理的重要性。

此外,我们还实现了文件系统和网络通信模块,以便更好地理解操作系统对外部设备和网络的支持。

通过这些实验,我们不仅加深了对操作系统的理解,还提高了编程和调试的能力。

Nachos实验让我们从理论知识转化为实际操作,让我们更加深入地理解了操作系统的工作原理。

总的来说,Nachos实验为我们提供了一个宝贵的学习机会,让我们对操作系统有了更深入的了解。

通过这个实验,我们不仅学到了知识,还培养了解决问题
的能力和团队合作精神。

希望未来能够继续深入研究操作系统,为计算机科学领域做出更多的贡献。

nachos Lab4实习报告

nachos Lab4实习报告

虚拟内存实习报告目录内容一:总体概述 (3)内容二:任务完成情况 (3)任务完成列表(Y/N) (3)具体Exercise的完成情况 (3)内容三:遇到的困难以及解决方法 (23)内容四:收获及感想 (24)内容五:对课程的意见和建议 (24)内容六:参考文献 (24)内容一:总体概述实习的主要内容是了解和改进nachos存储管理相关实现,主要分为三个部分。

第一部分的主要内容是实现TLB相关异常处理和置换算法,第二部分的主要内容是实现全局内存管理机制,使得nachos内存可以同时存在复数线程,第三部分的主要内容是实现程序运行时载入所需页面。

扩展部分主要是增加线程挂起状态以及实现倒排页表。

内容二:任务完成情况任务完成列表(Y/N)Exercise1 Exercise2 Exercise3 Exercise4 Exercise5 Exercise6 Exercise7 Y Y Y Y Y Y Y Challenge1 Challenge2Y Y具体Exercise的完成情况一、TLB异常处理目前,Nachos系统对于内存的管理是基于软件模拟的TLB机制。

其工作原理、异常处理、替换算法等方面,与分页式内存管理非常相像。

Exercise1 源代码阅读阅读code/userprog/,着重理解nachos执行用户程序的过程,以及该过程中与内存管理相关的要点。

阅读code/machine目录下的machine.h(cc),translate.h(cc)文件和code/userprog目录下的exception.h(cc),理解当前Nachos系统所采用的TLB 机制和地址转换机制(1)用户程序执行过程userprog/定义函数StartProcess主要功能是实现用户程序启动,如果我们希望执行test中的用户程序,那么我们进入userprog,执行./nachos -x ../test/(用户程序),通过识别-x参数,nachos调用StartProcess执行用户程序(具体实现在threads/)StartProcess的基本流程是,通过文件系统定义的OpenFile打开相关文件,通过AddrSpace的构造函数建立用户空间,装载文件,通过AddrSpace的InitRegisters函数初始化用户寄存器,通过AddrSpace的RestoreState函数装载页表,通过machine的Run函数运行用户程序AddrSpace的构造函数实现在userprog/,主要流程是,获取文件头,大小端做适宜转换,通过文件头计算文件所需空间,包括代码段,初始化数据段,未初始化数据段,栈空间4个部分,通过文件所需空间计算出文件所需的虚拟页面数量,创建用户空间页表,指示了第i个虚拟页对应第i个物理页,将用户程序的正文段和相关数据依次调入内存AddrSpace的InitRegisters函数实现在userprog/,主要流程是初始化普通寄存器(初始化为0),初始化当前指令指针(PC,初始化为0),初始化下一条指令指针(初始化为4),初始化栈指针(地址空间尾部适当前移)AddrSpace的RestoreState函数实现在userprog/,主要流程是将页表装载到machine类中,准备执行用户程序machine的Run函数实现在machine/,基本流程是通过OneInstruction函数完成指令译码和执行,通过interrupt的OneTick函数使得时钟前进machine的Run函数通过machine的ReadMem函数读内存数据,通过machine 的WriteMem函数写内存数据,两个函数的实现在machine/,核心是translate函数,translate函数实现在machine/,主要功能是实现虚拟地址到物理地址的转换,translate函数可能返回相应的错误,在这样的情况下,ReadMem函数/WriteMem函数调用RaiseException函数进行处理,RaiseException函数定义在machine/,基本流程是将错误信息存储在特定位置,调用ExceptionHandler函数处理不同的错误,ExceptionHandler 函数实现在userprog/,主要流程是根据错误信息处理不同错误。

操作系统实验报告一

操作系统实验报告一

实验报告课程名称:操作系统(nachos)Array实验项目名称:进程调度实验时间:2010-09-08班级:姓名:学号:实验目的:用高级语言编写和调试一个有 N个进程并行的进程调度程序,以加深对进程的概念及进程调度算法的理解。

实验环境:PC机、windows XP 操作系统、Visual C++6.0开发工具/Win-TC实验内容及过程:实验内容:设计一个有N个进程并行的进程调度程序。

进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。

具体描述如下:每个进程有一个进程控制块( PCB)表示。

进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。

分析:进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。

进程的到达时间为进程输入的时间。

进程的运行时间以时间片为单位进行计算。

每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。

就绪进程获得 CPU后都只能运行一个时间片。

用已占用CPU时间加1来表示。

如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后按照优先数的大小把它插入就绪队列等待CPU。

每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。

重复以上过程,直到所要进程都完成为止。

调度算法的参考流程图如下:实验过程:1.在win-tc环境中编写一个有N个进程并行的进程调度程序,包括最高优先数优先的调度算法和先来先服务算法,代码见附录中。

2.在上机环境中编译、调试程序。

3.设计输入数据,得出程序的执行结果。

实验结果及分析:1、选择最高优先数优先的调度算法调度两个进程:输出进程名、进程cpu时间、进程还需时间、进程优先数及进程状态,最高优先数优先的调度算法调度三个进程:2、选择先来先服务算法调度两个进程:输出进程名、进程开始时间及结束时间,先来先服务算法调度三个进程:实验心得:操作系统第一份实验刚开始确实有点没头绪,而且也刚接触一点儿进程调度的,对它只是大概了解些。

Nachos操作系统部分实验说明

Nachos操作系统部分实验说明
} 5、修改 文件中的调度类成员函数,使其按线程优先数大
………
新的设计的实验内容和步骤:
重新执行../lab2中的make 重新执行./nachos –rs 10
可以看到新内核的输出按规定的静态优先数次序在并发执行:
Name:Main Num:0 looped:0 Name:T1 Num:1 looped:0 Name:T2 Num:2 looped:0 Name:T1 Num:1 looped:1 Name:T2 Num:2 looped:1 Name:T1 Num:1 looped:2 ……
以上设计实验输出结果的分析:
主线程首先执行后放弃CPU,T1优先级最高排在队首先被选中。主线程由于优 先级最低被排在队列尾。
T1 线程放弃 CPU,当前 T2 在队首先被选中。T1 优先级最高又被排在队首。 T2线程放弃CPU,当前T1在队首先被选中。T2被排在队首。 如此重复5次,T1和T2线程执行结束,队列中仅有主线程了。主线程连续执行 4次后结束工作。
………… private:
………….. int Priority;//线程的优先数 } 4、在构造线程类时为线程设置一个静态优先数: 在 中的 Thread::Thread(char * debugName,int priority)
{ ……. Priority = priority;
一、内核线程调度策略设计
设计目标:
在 Nachos 系统中实现按优先数调度线程, 研究各种调度策略算法的实现, 分析各种调度算法的性能。 …..
设计背景:
从 Nachos 系统的基本内核./threads/ 文件中可以看出 Nachos 系统的基本内核实现了先进先出的调度策略。
调度类 Scheduler 管理着一个就绪队列 list。它的成员函数 ReadyToRun(currentThread)将当前线程挂入该队列的队尾: Scheduler::ReadyToRun (Thread *thread) {

操作系统nachos课程设计实验报告

操作系统nachos课程设计实验报告

一题目project1:实现nachos操作系统的project1中的join()方法,condition2类,Alarm类,Communicator类,PriorityScheduler类和Boat类project2:实现nachos操作系统的project2中的creat open read write close unlink 文件系统调用,修改UserProcess.readVirtualMemory 和UserProcess.writeVirtualMemory使操作系统能够运行多用户程序,实现exec join exit系统调用,实现LotteryScheduler类二实验目的熟悉nachos操作系统,深入理解操作系统内核了解用户程序的加载过程以及多用户进程的内存分配机制三实验要求完成nachos,提交设计文档和你的代码四实验说明,程序代码及测试结果Project1:1 join()要求实现join()方法,注意,其他线程没必要调用join函数,但是如果它被调用的话,也只能被调用一次。

join()方法第二次调用的结果是不被定义的,即使第二次调用的线程和第一次调用的线程是不同的。

无论有没有被join,一个进程都能够正常结束(a)设计思想当线程B执行A.join()时,将B放入A的等待队列,直到A完成时,唤醒在等待队列中的所有线程,因此需要实现join()方法和修改finish方法(b)源代码public void join() {Lib.debug(dbgThread, "Joining to thread: " + toString());Lib.assertTrue(this != currentThread);Lib.assertTrue(join_counter == 0);join_counter++;boolean status = Machine.interrupt().disable();if (this.status != statusFinished) {waitQueue.waitForAccess(KThread.currentThread());currentThread.sleep();}Machine.interrupt().restore(status);}public static void finish() {Lib.debug(dbgThread, "Finishing thread: " +currentThread.toString());Machine.interrupt().disable();Machine.autoGrader().finishingCurrentThread();Lib.assertTrue(toBeDestroyed == null);toBeDestroyed = currentThread;currentThread.status = statusFinished;KThread thread = currentThread().waitQueue.nextThread();if (thread != null){thread.ready();}sleep();}(c)程序截图线程1每次执行打出执行的次数,每次执行过后放弃cpu,线程2打出successful,线程2执行thread1.join().通过截图可以看出代码正确2 Condition2通过使用开关中断提供原子性来直接实现条件变量,我们利用信号量提供了一个简单的实现方式,你的工作就是不直接使用信号量提供相同的实现(你或许使用锁,即使它们也间接的使用了信号量)。

山东大学操作系统课设nachos

山东大学操作系统课设nachos

操作系统课程设计实验报告——对Nachos系统的完善班级:计软13.4分组:第八组Phase 0一、写在前面二、需要明确的是:Run nachos → ThreadKernel is called to create nachos kernel → initialize() initializes nachos kernel → selfTest() tests this kernel → run() is supposed to run user programs latterSome Crucial requirements:1. Only modify nachos.conf according to the project specifications.2. Do not modify any classes in the nachos.machine package, the nachos.ag package, or the nachos.security package.3. Do not add any new packages to your project.4.Do not modify the API for methods that the autograder uses.5.Do not directly use Java threads (the ng.Thread class).6. Do not use the synchronized keyword in any of your code.7. Do not directly use Java File objects (in the java.io package).Phase 1:Build a thread system for kernel processes Task 1.1Implements Join() method一、问题描述1. Note that another thread does not have to call join(), but if it is called, it must be called only once.2. A thread must finish executing normally whether or not it is joined.二、解决方案线程B在线程A运行的过程中调用join方法,阻塞线程A的运行获取运行权,此时线程A 等待线程B完成运行后重新运行。

NachOS实验报告(4个全)

NachOS实验报告(4个全)

四川大学操作系统课程设计报告学院:软件学院专业:软件工程专业年级:08级组编号:组成员:提交时间:2010年6月24日指导教师评阅意见:.. . . .指导教师评阅成绩:::实验项目一项目名称:开发Shell程序试验背景知识Shell此处的shell是指命令行式的shell。

文字操作系统与外部最主要的接口就叫做shell。

shell是操作系统最外面的一层。

shell管理你与操作系统之间的交互:等待你输入,向操作系统解释你的输入,并且处理各种各样的操作系统的输出结果。

shell提供了你与操作系统之间通讯的方式。

这种通讯可以以交互方式(从键盘输入,并且可以立即得到响应),或者以shell script(非交互)方式执行。

shell script是放在文件中的一串shell和操作系统命令,它们可以被重复使用。

本质上,shell script是命令行命令简单的组合到一个文件里面。

Shell基本上是一个命令解释器,类似于DOS下的。

它接收用户命令(如ls等),然后调用相应的应用程序。

较为通用的shell有标准的Bourne shell (sh)和C shell (csh)。

交互式shell和非交互式shell交互式模式就是shell等待你的输入,并且执行你提交的命令。

这种模式被称作交互式是因为shell与用户进行交互。

这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。

当你签退后,shell也终止了。

shell也可以运行在另外一种模式:非交互式模式。

在这种模式下,shell不与你进行交互,而是读取存放在文件中的命令,并且执行它们。

当它读到文件的结尾,shell也就终止了。

实验目的:Shell是一个命令处理器(command processor)——是一个读入并解释你输入的命令的程序,它是介于使用者和操作系统之核心程序(kernel)间的一个接口。

它是一个交互性命令解释器。

shell 独立于操作系统,这种设计让用户可以灵活选择适合自己的shell。

山东大学操作系统实验二实验报告

山东大学操作系统实验二实验报告

实验报告
实验题目:安装Nachos系统学号: 201100300038
日期:2013-10-22 班级: 11级3班姓名:陶旭涛
Email: 1595242630@
实验目的:
1.练习安装、编译和测试基本 Nachos 系统
2.了解基本 Nachos 系统组织结构
3.熟悉 C++语言和系统开发调试工具
硬件环境:linux
软件环境: gcc
实验步骤:
1. 将 gcc 和 nachos 拷贝到主文件夹中,解压nachos。

$ tar xzvf nachos-3.4-2011.tar.gz
2. 以root 身份进入系统目录/usr/local,将文件Gcc-2.8.1-mips.tar.gz 复制
到/usr/local 目录中:

cp gcc-2.8.1-mips.tar.gz /usr/local
使用 shell 命令安装:
$tar xzvf gcc-2.8.1-mips.tar.gz
3. cd /nachos3.4/code/threads
make
./nachos
结果如下
结论分析与体会:
通过这次实验,我熟悉了操作系统实验的环境,进一步了解了Nachos的构成,对我以后顺利熟练的完成操作系统实验有很大的帮助!。

操作系统实验nachos01

操作系统实验nachos01

操作系统实验 nachos01实验一体验Nachos下的并发程序设计一、实验人员:二、实验目的:对nachos进行熟悉,并初步体验nachos下的并发程序设计三、实验内容:1、安装Nachos2、用C++实现双向有序链表;3、在nachos系统中使用所写的链表程序并演示一些并发错误四、实验步骤:1、安装Nachos,具体细则如下下载code-linux.tar.gz并上传到服务器建立目录(推荐建立主目录下的nachos)cd到新建目录中tar zxvf code-linux.tar.gz的完整路径cd nachos-3.4/codemake2、阅读材料阅读nachos-3.4/code/Makefilenachos-3.4/code/Makefile.depnachos-3.4/code/monnachos-3.4/code/threads/Makefile初步了解各Makefile的构成和相互关系。

阅读nachos-3.4/code/threads/了解nachos如何开始。

阅读nachos-3.4/code/threads/的Initialize函数中与debug相关的部分及nachos-3.4/code/threads/了解DEBUG的实现与使用,以此进一步熟悉nachos系统。

阅读nachos-3.4/code/threads/,了解nachos中线程的概念及其运作方式。

3、编写相关的dllist.h,,文件,具体代码如下dllist.hclass DLLElement {public:DLLElement( void *itemPtr, int sortKey ); // initialize a list elementDLLElement *next; // next element on list// NULL if this is the lastDLLElement *prev; // previous element on list// NULL if this is the firstint key; // priority, for a sorted listvoid *item; // pointer to item on the list};class DLList {public:DLList(); // initialize the listDLList(int type);~DLList(); // de-allocate the listvoid Prepend(void *item); // add to head of list (set key = min_key-1)void Append(void *item); // add to tail of list (set key = max_key+1) void *Remove(int *keyPtr); // remove from head of list // set*keyPtr to key of the removed item// return item (or NULL if list is empty)bool IsEmpty(); // return true if list has elements // routines toput/get items on/off list in order (sorted by key)void SortedInsert(void *item, int sortKey); void *SortedRemove(int sortKey); // remove first item with key==sortKey// return NULL if no such item existsprivate:DLLElement *first; // head of the list, NULL if empty DLLElement*last; // last element of the list, NULL if empty int err_type;};#include "copyright.h"#include "dllist.h"#include "system.h"DLLElement::DLLElement( void *itemPtr, int sortKey ) // initialize a list element{item=itemPtr;key=sortKey;next=NULL;prev=NULL;}DLList::DLList() // initialize the list{first=NULL;last=NULL;err_type=0;}DLList::DLList(int type){first=NULL;last=NULL;err_type=type;}DLList::~DLList() // de-allocate the list{while (Remove(NULL)!=NULL);}void DLList::Prepend(void *item) // add to head of list (set key = min_key-1){DLLElement *elm=new DLLElement(item,0);if (IsEmpty()){first=elm;last=elm;}else{elm->key=first->key-1;elm->next=first;elm->prev=NULL;first->prev=elm;first=elm;}}void DLList::Append(void *item) // add to tail of list (set key = max_key+1){DLLElement *elm=new DLLElement(item,0);if (IsEmpty()){first=elm;last=elm;}else{elm->key=last->key+1;elm->next=NULL;elm->prev=last;last->next=elm;last=elm;}}void *DLList::Remove(int *keyPtr) // remove from head of list {DLLElement *element;if (IsEmpty()){return NULL;}void *retitem;element=first;*keyPtr=first->key;if (err_type==1){printf("Remove error\n");currentThread->Yield();}retitem=element->item;if (first==last){first=NULL;last=NULL;}else{if (err_type==1){printf("Remove error\n");currentThread->Yield();}first=element->next;first->prev=NULL;}delete element;return retitem;}bool DLList::IsEmpty() // return true if list has elements {if ((first==NULL)&&(last==NULL))return true;else if((first!=NULL)&&(last!=NULL))return false;elseprintf("error!either the first or the last is NULL!\n");return false;}void DLList::SortedInsert(void *item, int sortKey) // routines to put/get items on/off listin order (sorted by key){DLLElement *insertItem=new DLLElement(item,sortKey);DLLElement *ptr=first;if (IsEmpty()){first=insertItem;if (err_type==2){printf("SortedInsert error,first!=last\n");currentThread->Yield();}last=insertItem;}else{for (;ptr!=NULL; ptr=ptr->next)if (ptr->key>sortKey) break;if (err_type==3){printf("SortedInsert error,the postion lost\n"); currentThread->Yield();}if (ptr==NULL){insertItem->prev=last;last->next=insertItem;last=insertItem;last->next=NULL;}elseif (ptr==first){insertItem->next=first;first->prev=insertItem;first=insertItem;first->prev=NULL;}else{ptr->prev->next=insertItem;insertItem->prev=ptr->prev;if (err_type==4){printf("SorteadInsert error,sort error\n");currentThread->Yield();}insertItem->next=ptr;ptr->prev=insertItem;}}}void *DLList::SortedRemove(int sortKey) // remove first item with key==sortKey{ // return NULL if no such item existsDLLElement *ptr=first;if (IsEmpty())return NULL;for (;ptr!=NULL; ptr=ptr->next)if (ptr->key>sortKey) break;if (ptr==NULL){printf("Remove error!No such a key!");return NULL;}else if (ptr==first){first=first->next;first->prev=NULL;}else if (ptr==last){last=last->prev;last->next=NULL;}else{ptr->prev->next=ptr->next; ptr->next->prev=ptr->prev; }return ptr->item;}#include <stdlib.h>#include "copyright.h"#include "dllist.h"#include "system.h"#include <time.h>void Insert(int t,int n,DLList *dllist){int i,ll;srand(time(0));for (i=0; i<n; i++){ll=rand()%101;dllist->SortedInsert(NULL,ll);printf("Thread %d : inserted key=%d\n",t,ll);}}void Remove(int t,int n,DLList *dllist){int i,keyll;for (i=0; i<n; i++){dllist->Remove(&keyll);printf("Thread %d : removed key=%d\n",t,keyll);}}4、将上述要的链表文件拷贝nachos-3.4/code/threads/中,修改nachos-3.4/code/mon中的THREAD_H、THREAD_C、THREAD_O,在nachos-3.4/code/threads/目录中依次执行make depend和make修改nachos-3.4/code/threads/和nachos-3.4/code/threads/实现两个线程调用链表功能,重新编译threads子系统修改nachos-3.4/code/threads/,在适当位置插入currentThread->Yield()调用以强制线程切换(注意相应文件中应该包含对外部变量currentThread的声明并include thread.h),重新编译threads子系统monTHREAD_H =../threads/copyright.h\../threads/list.h\../threads/dllist.h\THREAD_C =../threads/\../threads/\../threads/\../threads/\THREAD_O =main.o dllist.o dllist-driver.o list.o 添加线程数,结点个数,错误类型,以及参数的修改#ifdef THREADSextern int testnum;extern int threadnum;extern int n;extern int err_type;#endif#ifdef THREADSfor (argc--, argv++; argc > 0; argc -= argCount, argv += argCount) {argCount = 1;switch (argv[0][1]) {case 'q':testnum = atoi(argv[1]); argCount++;break;case 't':threadnum = atoi(argv[1]); argCount++;break;case 'n':n = atoi(argv[1]); argCount++;break;case 'e':err_type = atoi(argv[1]); argCount++;break;default:testnum = 1;break;}}ThreadTest();#endif 将双向链表的功能嵌入,设置测试号为 2// testnum is set in int testnum = 1,threadnum=1,n,err_type=0;DLList *dllist;voidDLListThread(int t){Insert(t,n,dllist);Remove(t,n,dllist); }voidThreadTest2(){DEBUG('t',"Entering ThreadTest2");dllist=new DLList(err_type);for (int i=1; i<threadnum; i++){Thread *t=new Thread("forker thread");t->Fork(DLListThread,i);}DLListThread(threadnum); }//----------------------------------------------------------------------// ThreadTest// Invoke a test routine.//----------------------------------------------------------------------voidThreadTest(){switch (testnum) {case 1:ThreadTest1();break;case 2:ThreadTest2();break;default:printf("No test specified.\n");break;}5、相关并发错误分析参照如下示例运行nachos./nachos –q 2 –t 2 –n 2 –e 0-q 2表示选择双向链表模式-t为线程数-n 为插入结点数-e 为错误号(1)无并发错误./nachos –q 2 –t 2 –n 2(2) 在remove中,由于线程切换,使返回值指向出错./nachos –q 2 –t 2 –n 4 –e 1相关代码段:void *retitem;element=first;*keyPtr=first->key;if (err_type==1){printf("Remove error\n");currentThread->Yield();}retitem=element->item;(3) SortedInsert且链表为空时,由于进程切换,导致first与last指向有可能不一致。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一题目project1:实现nachos操作系统的project1中的join()方法,condition2 类,Alarm类,Communicator类,PriorityScheduler类和Boat类project2:实现nachos操作系统的project2中的creat open read write close unlink 文件系统调用,修改UserProcess.readVirtualMemory和UserProcess.writeVirtualMemory使操作系统能够运行多用户程序,实现exec join exit系统调用,实现LotteryScheduler类二实验目的熟悉nachos操作系统,深入理解操作系统内核了解用户程序的加载过程以及多用户进程的内存分配机制三实验要求完成nachos,提交设计文档和你的代码四实验说明,程序代码及测试结果Project1:1 join()要求实现join()方法,注意,其他线程没必要调用join函数,但是如果它被调用的话,也只能被调用一次。

join()方法第二次调用的结果是不被定义的,即使第二次调用的线程和第一次调用的线程是不同的。

无论有没有被join,一个进程都能够正常结束(a)设计思想当线程B执行A.join()时,将B放入A的等待队列,直到A完成时,唤醒在等待队列中的所有线程,因此需要实现join()方法和修改finish方法(b)源代码public void join(){Lib.debug(dbgThread, "Joining to thread:" + toString());Lib.assertTrue(this!=currentThread);Lib.assertTrue(join_counter == 0);join_counter++;boolean status=Machine.interrupt().disable();if (this.status != statusFinished) {waitQueue.waitForAccess(KThread.currentThread());currentThread.sleep();}Machine.interrupt().restore(s tatus);}public static void finish(){Lib.debug(dbgThread, "Finishing thread:" +currentThread.toString());Machine.interrupt().disable();Machine.autoGrader().finishingCurrentThread();Lib.assertTrue(toBeDestroyed == null);toBeDestroyed= currentThread;currentThread.status = statusFinished;KThread thread= currentThread().waitQueue.nextThread();if (thread!= null){thread.ready();}sleep();}(c)程序截图线程1每次执行打出执行的次数,每次执行过后放弃cpu,线程2 打出successful,线程2 执行thread1.join().通过截图可以看出代码正确2 Condition2通过使用开关中断提供原子性来直接实现条件变量,我们利用信号量提供了一个简单的实现方式,你的工作就是不直接使用信号量提供相同的实现(你或许使用锁,即使它们也间接的使用了信号量)。

一旦你实现了,你将会有两种可选择的实现方式来提供相同的功能。

你的第二种条件变量的实现必须放在Condition2 中(a)设计思想Condition2 是对使用该条件变量的线程进行管理,所以要把在这个条件变量上等待的进程储存起来,因此可以使用一个队列。

sleep()方法是把等待该条件变量的线程阻塞,放入等待队列,直到执行了wake()并且获得cpu 才能继续执行,执行步骤:关中断,释放锁,把线程放入等待队列,获得锁,开中断。

wake()方法是把条件变量中的线程移出,放入就绪队列。

执行步骤:关中断,线程移出等待队列移入就绪队列,开中断wakeAll()方法是将条件变量中的所有线程移出,移入就绪队列(b)源代码public void sleep(){Lib.assertTrue(conditionLock.isHeldByCurrentThread());boolean status=Machine.interrupt().disable();conditionLock.release();waitqueue.waitForAccess(KThread.currentThread());KThread. currentThread().sleep();conditionLock.acquire();Machine.interrupt().restore(s tatus);}public void wake(){Lib.assertTrue(conditionLock.isHeldByCurrentThread());boolean status=Machine.interrupt().disable();KThread thread=waitqueue.nextThread();if (!(thread==null))thread.ready();Machine.interrupt().restore(s tatus);}public void wakeAll(){Lib.assertTrue(conditionLock.isHeldByCurrentThread());boolean status=Machine.interrupt().disable();KThread thread=waitqueue.nextThread();while(!(thread==null)){ thread.ready();thread=waitqueue.nextThread();}Machine.interrupt().restore(s tatus);}(c)程序截图线程1线程 2 分别请求锁和条件变量,然后释放锁和条件变量,图中可以看出代码正确3 Alarm类实现Alarm 类,线程调用waitUntil方法之后会终止,直到传入的时间之后才可以执行。

线程没必要在等待的时间之后立刻执行,只是把它放入ready队列,等待分配cpu。

可以使用一个线程队列,但是不能产生额外的线程。

(a)设计思想waitUntil()方法使用了一个队列可以存放线程以及唤醒时间,这个队列以时间为序的有序队列。

每次调用时,把当前线程和唤醒时间加入队列,等待唤醒。

timerInterrupt()方法在每一次timer 产生时间中断时遍历队列,检查队列中的时间状态,当线程到了等待的时间就把线程从队列中取出放入就绪队列。

KThreadWakeTime类是一个内部类用于联系线程和唤醒时间(b)源代码public void waitUntil(long x) {boolean status=Machine.interrupt().disable();long waketime= Machine.timer().getTime() + x;KThreadWakeTime kthreadwaketime=newKThreadWakeTime(KThread.currentThread(),waketime);int size=linkedlist.size();if (size== 0)linkedlist.add(kthreadwaketime);elsefor (int i = 0; i <size; i++){if (waketime< linkedlist.get(i).getWakeTime()){ linkedlist.add(i, kthreadwaketime);break;}if (i==size-1&& waketime>= linkedlist.get(i).getWakeTime())linkedlist.add(i + 1, kthreadwaketime);}KThread. currentThread().sleep();Machine.interrupt().restore(s tatus);}public void timerInterrupt(){boolean status=Machine.interrupt().disable();long currenttime= Machine.timer().getTime();int size=linkedlist.size();if (size== 0);elsefor (int i = 0; i <size; i++){if (currenttime< linkedlist.get(i).getWakeTime());else {KThread thread= linkedlist.get(i).getThread();thread.ready();linkedlist.remove(i);size--;i = 0;currenttime= Machine.timer().getTime();}}KThread.currentThread ().yield();Machine.interrupt().restore(s tatus);}public class KThreadWakeTime{private KThread thread= null;private long waketime=0;public KThreadWakeTime(KThread thread,long waketime){this.thread = thread;this.waketime =waketime;}public KThread getThread(){return thread;}public long getWakeTime(){return waketime;}}(c)程序截图创建一个线程在70时中止,等待500后唤醒。

图中可以看出代码正确4 Communicator利用条件变量编写发送和接收一个消息来实现Communicator类的speak ()和listen()方法。

相关文档
最新文档