操作系统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实验为我们提供了一个宝贵的学习机会,让我们对操作系统有了更深入的了解。

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

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

  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()方法。

相关文档
最新文档