操作系统实验nachos01.docx
- 文档编号:7446343
- 上传时间:2023-01-24
- 格式:DOCX
- 页数:17
- 大小:54.65KB
操作系统实验nachos01.docx
《操作系统实验nachos01.docx》由会员分享,可在线阅读,更多相关《操作系统实验nachos01.docx(17页珍藏版)》请在冰豆网上搜索。
操作系统实验nachos01
实验一体验Nachos下的并发程序设计
一、实验人员:
二、实验目的:
对nachos进行熟悉,并初步体验nachos下的并发程序设计
三、实验容:
1、安装Nachos
2、用C++实现双向有序链表;
3、在nachos系统中使用所写的链表程序并演示一些并发错误
四、实验步骤:
1、安装Nachos,具体细则如下
下载code-linux.tar.gz并上传到服务器
建立目录(推荐建立主目录下的nachos)
cd到新建目录中
tarzxvfcode-linux.tar.gz的完整路径
cdnachos-3.4/code
make
2、阅读材料
阅读nachos-3.4/code/Makefile
nachos-3.4/code/Makefile.dep
nachos-3.4/code/Makefilemon
nachos-3.4/code/threads/Makefile
初步了解各Makefile的构成和相互关系。
阅读nachos-3.4/code/threads/main.cc了解nachos如何开始。
阅读nachos-3.4/code/threads/system.cc的Initialize函数中与debug相关的部分与nachos-3.4/code/threads/utility.cc了解DEBUG的实现与使用,以此进一步熟悉nachos系统。
阅读nachos-3.4/code/threads/threadtest.cc,了解nachos中线程的概念与其运作方式。
3、编写相关的dllist.h,dllist.cc,dllist-driver.cc文件,具体代码如下
dllist.h
classDLLElement{
public:
DLLElement(void*itemPtr,intsortKey);//initializealistelement
DLLElement*next;//nextelementonlist
//NULLifthisisthelast
DLLElement*prev;//previouselementonlist
//NULLifthisisthefirst
intkey;//priority,forasortedlist
void*item;//pointertoitemonthelist
};
classDLList{
public:
DLList();//initializethelist
DLList(inttype);
~DLList();//de-allocatethelist
voidPrepend(void*item);//addtoheadoflist(setkey=min_key-1)
voidAppend(void*item);//addtotailoflist(setkey=max_key+1)
void*Remove(int*keyPtr);//removefromheadoflist
//set*keyPtrtokeyoftheremoveditem
//returnitem(orNULLiflistisempty)
boolIsEmpty();//returntrueiflisthaselements
//routinestoput/getitemson/offlistinorder(sortedbykey)
voidSortedInsert(void*item,intsortKey);
void*SortedRemove(intsortKey);//removefirstitemwithkey==sortKey
//returnNULLifnosuchitemexists
private:
DLLElement*first;//headofthelist,NULLifempty
DLLElement*last;//lastelementofthelist,NULLifempty
interr_type;
};
Dllist.cc
#include"copyright.h"
#include"dllist.h"
#include"system.h"
DLLElement:
:
DLLElement(void*itemPtr,intsortKey)//initializealistelement
{
item=itemPtr;
key=sortKey;
next=NULL;
prev=NULL;
}
DLList:
:
DLList()//initializethelist
{
first=NULL;
last=NULL;
err_type=0;
}
DLList:
:
DLList(inttype)
{
first=NULL;
last=NULL;
err_type=type;
}
DLList:
:
~DLList()//de-allocatethelist
{
while(Remove(NULL)!
=NULL)
;
}
voidDLList:
:
Prepend(void*item)//addtoheadoflist(setkey=min_key-1)
{
DLLElement*elm=newDLLElement(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;
}
}
voidDLList:
:
Append(void*item)//addtotailoflist(setkey=max_key+1)
{
DLLElement*elm=newDLLElement(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)//removefromheadoflist
{
DLLElement*element;
if(IsEmpty())
{
returnNULL;
}
void*retitem;
element=first;
*keyPtr=first->key;
if(err_type==1)
{
printf("Removeerror\n");
currentThread->Yield();
}
retitem=element->item;
if(first==last)
{
first=NULL;
last=NULL;
}
else
{
if(err_type==1)
{
printf("Removeerror\n");
currentThread->Yield();
}
first=element->next;
first->prev=NULL;
}
deleteelement;
returnretitem;
}
boolDLList:
:
IsEmpty()//returntrueiflisthaselements
{
if((first==NULL)&&(last==NULL))
returntrue;
elseif((first!
=NULL)&&(last!
=NULL))
returnfalse;
else
printf("error!
eitherthefirstorthelastisNULL!
\n");
returnfalse;
}
voidDLList:
:
SortedInsert(void*item,intsortKey)//routinestoput/getitemson/offlistinorder(sortedbykey)
{
DLLElement*insertItem=newDLLElement(item,sortKey);
DLLElement*ptr=first;
if(IsEmpty())
{
first=insertItem;
if(err_type==2)
{
printf("SortedInserterror,first!
=last\n");
currentThread->Yield();
}
last=insertItem;
}
else
{
for(;ptr!
=NULL;ptr=ptr->next)
if(ptr->key>sortKey)break;
if(err_type==3)
{
printf("SortedInserterror,thepostionlost\n");
currentThread->Yield();
}
if(ptr==NULL)
{
insertItem->prev=last;
last->next=insertItem;
last=insertItem;
last->next=NULL;
}
else
if(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("SorteadInserterror,sorterror\n");
currentThread->Yield();
}
insertItem->next=ptr;
ptr->prev=insertItem;
}
}
}
void*DLList:
:
SortedRemove(intsortKey)//removefirstitemwithkey==sortKey
{//returnNULLifnosuchitemexists
DLLElement*ptr=first;
if(IsEmpty())
returnNULL;
for(;ptr!
=NULL;ptr=ptr->next)
if(ptr->key>sortKey)break;
if(ptr==NULL)
{
printf("Removeerror!
Nosuchakey!
");
returnNULL;
}
elseif(ptr==first)
{
first=first->next;
first->prev=NULL;
}
elseif(ptr==last)
{
last=last->prev;
last->next=NULL;
}
else
{
ptr->prev->next=ptr->next;
ptr->next->prev=ptr->prev;
}
returnptr->item;
}
Dllist-driver.cc
#include
#include"copyright.h"
#include"dllist.h"
#include"system.h"
#include
voidInsert(intt,intn,DLList*dllist)
{
inti,ll;
srand(time(0));
for(i=0;i { ll=rand()%101; dllist->SortedInsert(NULL,ll); printf("Thread%d: insertedkey=%d\n",t,ll); } } voidRemove(intt,intn,DLList*dllist) { inti,keyll; for(i=0;i { dllist->Remove(&keyll); printf("Thread%d: removedkey=%d\n",t,keyll); } } 4、将上述要的链表文件拷贝nachos-3.4/code/threads/中,修改nachos-3.4/code/Makefilemon中的THREAD_H、THREAD_C、THREAD_O,在nachos-3.4/code/threads/目录中依次执行makedepend和make 修改nachos-3.4/code/threads/threadtest.cc和nachos-3.4/code/threads/main.cc实现两个线程调用链表功能,重新编译threads子系统 修改nachos-3.4/code/threads/threadtest.cc,在适当位置插入currentThread->Yield()调用以强制线程切换(注意相应文件中应该包含对外部变量currentThread的声明并includethread.h),重新编译threads子系统 Makefilemon THREAD_H=../threads/copyright.h\ ../threads/list.h\ ../threads/dllist.h\ THREAD_C=../threads/main.cc\ ../threads/dllist.cc\ ../threads/dllist-driver.cc\ ../threads/list.cc\ THREAD_O=main.odllist.odllist-driver.olist.o Main.cc添加线程数,结点个数,错误类型,以与参数的修改 #ifdefTHREADS externinttestnum; externintthreadnum; externintn; externinterr_type; #endif #ifdefTHREADS for(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 Threadtest.cc将双向链表的功能嵌入,设置测试号为2 //testnumissetinmain.cc inttestnum=1,threadnum=1,n,err_type=0; DLList*dllist; void DLListThread(intt) { Insert(t,n,dllist); Remove(t,n,dllist); } void ThreadTest2() { DEBUG('t',"EnteringThreadTest2"); dllist=newDLList(err_type); for(inti=1;i { Thread*t=newThread("forkerthread"); t->Fork(DLListThread,i); } DLListThread(threadnum); } //---------------------------------------------------------------------- //ThreadTest //Invokeatestroutine. //---------------------------------------------------------------------- void ThreadTest() { switch(testnum){ case1: ThreadTest1(); break; case2: ThreadTest2(); break; default: printf("Notestspecified.\n"); break; } 5、相关并发错误分析 参照如下示例运行nachos ./nachos–q2–t2–n2–e0 -q2表示选择双向链表模式 -t为线程数 -n为插入结点数 -e为错误号 (1)无并发错误 ./nachos–q2–t2–n2 (2)在remove中,由于线程切换,使返回值指向出错 ./nachos–q2–t2–n4–e1 相关代码段: void*retitem; element=first; *keyPtr=first->key; if(err_type==1) { printf("Removeerror\n"); currentThread->Yield(); } retitem=element->item; (3)SortedInsert且链表为空时,由于进程切换,导致first与last指向有可能不一致。 ./nachos–q2–t2–n4–e2 相关代码段: if(IsEmpty()) { first=insertItem; if(err_type==2) { printf("SortedInserterror,first! =last\n"); currentThread->Yield(); } last=insertItem; } (4)SortedInsert时,将结点插入链表中时,由于进程切换,导致原来找到的结点位置丢失 ./nachos–q2–t2–n4–e3 相关代码段: for(;ptr! =NULL;ptr=ptr->next) if(ptr->key>sortKey)break; if(err_type==3) { printf("SortedInserterror,thepostionlost\n"); currentThread->Yield(); } (5)SortedInsert时,将结点插入链表中时,由于进程切换,导致结点间连接混乱 ./nachos–q2–t2–n4–e4 相关代码段: if(ptr==NULL) { insertItem->prev=last; last->next=insertItem; last=insertItem; last->next=NULL; } else if(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("SorteadInserterror,sorterror\n"); currentThread->Yield(); } insertItem->next=ptr; ptr->prev=insertItem; } 实验心得: (1)在dllist-driver.cc中引用stdlib库时,若将库的引用的次序置于system.h与time.h之后,将可能引发声明的相关问题。 (2)在引用外部变量以与外部函数的时候必须要用extern声明。 (3)关于双向链表操作的代码其实并不难,关键是在对双向链表进行操作的时候,在适当的位置进行切换会引起不同的并发错误。 通过本次实验,熟悉了nachos中与本次实验相关的容,了解了线程的切换以与线程切换可能引发的并发错误。 实验分工: 实验代码编写三人先各自编写,最后讨论得出最终代码。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 实验 nachos01