秋霞电影网午夜鲁丝片无码,真人h视频免费观看视频,囯产av无码片毛片一级,免费夜色私人影院在线观看,亚洲美女综合香蕉片,亚洲aⅴ天堂av在线电影猫咪,日韩三级片网址入口

中南大學(xué) 操作系統(tǒng)實驗報告課程設(shè)計報告

上傳人:仙*** 文檔編號:30235322 上傳時間:2021-10-09 格式:DOC 頁數(shù):48 大小:522.50KB
收藏 版權(quán)申訴 舉報 下載
中南大學(xué) 操作系統(tǒng)實驗報告課程設(shè)計報告_第1頁
第1頁 / 共48頁
中南大學(xué) 操作系統(tǒng)實驗報告課程設(shè)計報告_第2頁
第2頁 / 共48頁
中南大學(xué) 操作系統(tǒng)實驗報告課程設(shè)計報告_第3頁
第3頁 / 共48頁

下載文檔到電腦,查找使用更方便

15 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《中南大學(xué) 操作系統(tǒng)實驗報告課程設(shè)計報告》由會員分享,可在線閱讀,更多相關(guān)《中南大學(xué) 操作系統(tǒng)實驗報告課程設(shè)計報告(48頁珍藏版)》請在裝配圖網(wǎng)上搜索。

1、操作系統(tǒng)實驗報告 界面設(shè)計 l 菜單 菜單包括菜單欄,菜單,菜單項,一個菜單欄可以包括N個菜單,一個菜單可以包括菜單項。C語言設(shè)計菜單的思想是用雙向鏈表,先保存繪圖區(qū)的內(nèi)容,再在上面畫菜單。 l 菜單結(jié)構(gòu)圖 菜單欄 菜單1 菜單2 菜單n …….…. 尾指針 頭指針 當(dāng)前指向菜單 菜單項1 菜單項2 。 。 。 。 菜單項n 頭指針 其他菜單項結(jié)構(gòu)類似 結(jié)尾指針 l 數(shù)據(jù)結(jié)構(gòu) 1. 菜單欄: typedef struct menubar_s{ int number,x,y,barheight,baritemwidth;/*numbe

2、r用來記錄菜單項的數(shù)目,x,y用來記錄菜單欄在屏幕上的位置,barheight用來控制菜單欄的高度,baritemwidth用來控制每項菜單的寬度*/ struct menu_s *mhead; /*指向第一個菜單*/ struct menu_s *mtail; /*指向最后一個菜單*/ struct menu_s *mpoint; /*當(dāng)用戶按下左右箭頭時用來記錄指向那個菜單,初始指向mhead*/ void (* docommand)(); /*菜單時間的處理函數(shù)*/ }MenuBar; 2. 菜單: typedef struct menu_s{ int numb

3、er; /*菜單是菜單欄中的第幾項*/ int subwidth; /*菜單項的寬度*/ int subcount; /*菜單項的數(shù)目*/ char *content; /*菜單顯示的字符串/ struct menu_s *next; /*指向下一個菜單,如果是結(jié)尾菜單,則為NULL*/ struct menu_s *before; /*指向前一個菜單,如果是頭菜單,則為NULL*/ struct submenu_s *sub; /*指向當(dāng)前激活的菜單項*/ struct submenu_s *head; /*指向第一個菜單項*/ struct submenu_

4、s *tail; /*指向最后一個菜單項*/ }Menu; 3. 菜單項: typedef struct submenu_s{ int number; /*菜單項是菜單中的第幾項*/ int isactive; /*是否激活*/ char *content; /*顯示的字符串*/ struct submenu_s *next; /*指向下一個菜單項*/ struct submenu_s *before; /*指向前一個菜單項*/ }submenu; l 函數(shù)實現(xiàn) 1. 菜單構(gòu)造函數(shù) /*該函數(shù)的功能主要是根據(jù)指定的menutitle字符串,往菜單欄中添加一項菜

5、單*/ void addmenu(char *menutitle){ if(Mb==NULL){/*如果Mb(全局MenuBar類型的變量)為NULL,說明沒有初始化菜單欄,要初始化*/ if((Mb=(MenuBar *)malloc(sizeof(MenuBar)))==NULL) doerror("System error"); Mb->number=0; /*菜單欄中菜單數(shù)目為0*/ Mb->mpoint=Mb->mhead=Mb->mtail=NULL; Mb->x=0; Mb->y=0; /*位置于屏幕上(0,0)*/ Mb->ba

6、rheight=18; /*菜單欄高度為18*/ Mb->baritemwidth=100; /*每項菜單的寬度為100*/ Mb->docommand=docommand; /*設(shè)置事件處理函數(shù)為docommand()*/ } if(Mb->mtail==NULL){ /*如果Mb->mtail為NULL,說明要先構(gòu)造Mb->mhead*/ if((Mb->mhead=(Menu *)malloc(sizeof(Menu)))==NULL) doerror("System error"); Mb->mhead->before=NULL; Mb->

7、mtail=Mb->mhead; }else { if((Mb->mtail->next=(Menu *)malloc(sizeof(Menu)))==NULL) doerror("System error"); Mb->mtail->next->before=Mb->mtail; Mb->mtail=Mb->mtail->next; } Mb->mtail->number=Mb->number; /*當(dāng)前添加進(jìn)去的菜單位置,下面有Mb->number的自加*/ Mb->mtail->subwidth=0; /*菜單項的寬度為0*/ Mb->mta

8、il->subcount=0; /*菜單項數(shù)目為0/ Mb->mtail->content=menutitle; /*把菜單的字符串指針指向menutitle*/ Mb->mtail->next=NULL; Mb->mtail->sub=Mb->mtail->head=Mb->mtail->tail=NULL; /*把菜單項全部置NULL*/ Mb->number++;/*菜單欄中number加1,表示加進(jìn)去了一個菜單*/ } 2. 菜單項構(gòu)造函數(shù) /*該函數(shù)的功能是根據(jù)menu指定的字符串,往該菜單中添加以itemtitle為字符串的菜單項比如additem(“Fil

9、e”,”O(jiān)pen”)則執(zhí)行向File菜單中添加一項itemtitle菜單項*/ void additem(char *menu,char *itemtitle){ Mb->mpoint=Mb->mhead; /*先把指針指向菜單頭,這里借用Mb中的mpoint為了不用額外的變量*/ while(Mb->mpoint!=NULL){ if(stricmp(Mb->mpoint->content,menu)==0) /*遍歷menu鏈表,如果找到一項和menu指定字符串相等的,則記錄下來,跳出,*/ break; Mb->mpoint=Mb->mpoint-

10、>next; } if(Mb->mpoint->tail==NULL){ /*如果tail為空,則說明沒有構(gòu)造頭節(jié)點head*/ if((Mb->mpoint->head=(submenu *)malloc(sizeof(submenu)))==NULL) doerror("System error"); Mb->mpoint->head->before=NULL; Mb->mpoint->sub=Mb->mpoint->tail=Mb->mpoint->head; }else { if((Mb->mpoint->tail->next

11、=(submenu *)malloc(sizeof(submenu)))==NULL) doerror("System error"); Mb->mpoint->tail->next->before=Mb->mpoint->tail; Mb->mpoint->tail=Mb->mpoint->tail->next; } if(strlen(itemtitle)>Mb->mpoint->subwidth) Mb->mpoint->subwidth=strlen(itemtitle); /*該語句主要計算一下剛加進(jìn)來的菜單項的字符數(shù),如果比菜單的寬度還

12、要大,則把該寬度賦值給subwidth,主要是為了畫菜單是寬度足夠*/ Mb->mpoint->subcount++;/*菜單項數(shù)目加一*/ Mb->mpoint->tail->number=Mb->mpoint->subcount; Mb->mpoint->tail->isactive=0; Mb->mpoint->tail->content=itemtitle; Mb->mpoint->tail->next=NULL; } 3. 繪畫菜單欄 void drawmenu(){ Mb->mpoint=Mb->mhead; rectangle(0

13、,0,getmaxx()-1,Mb->y+Mb->barheight);/*畫一個方框*/ while(Mb->mpoint!=NULL){ outtextxy(Mb->mpoint->number*Mb->baritemwidth+Mb->x+5,Mb->y+6,Mb->mpoint->content); /*在菜單欄中逐項畫出菜單的內(nèi)容*/ Mb->mpoint=Mb->mpoint->next; } } 4. 繪畫當(dāng)前激活的菜單 void drawsubmenu(){ submenu *temp; int x; /*x記錄當(dāng)前畫菜單的x位置*/ x=M

14、b->mpoint->number*Mb->baritemwidth+Mb->x; temp=Mb->mpoint->head; copyimage(x,Mb->barheight+2,x+Mb->mpoint->subwidth*8+5,(Mb->mpoint->subcount+1)*Mb->barheight+3); /*保存繪畫區(qū)的內(nèi)容,copyimage為自寫的函數(shù)*/ setfillstyle(1,getbkcolor()); bar(x,Mb->barheight+2,x+Mb->mpoint->subwidth*8+5,(Mb->mpoint->subcount

15、+1)*Mb->barheight+3); /*用背景色把繪畫區(qū)覆蓋一下*/ rectangle(x,Mb->barheight+2,x+Mb->mpoint->subwidth*8+5,(Mb->mpoint->subcount+1)*Mb->barheight+3); /*畫一個方框*/ while(temp!=NULL){ if(temp->isactive){ /*如果是當(dāng)前激活的菜單,則畫一個紅色方框背景*/ setfillstyle(1,RED); bar(x+2,temp->number*Mb->barheight+4,x+Mb->mpoint->s

16、ubwidth*8+3,(temp->number+1)*Mb->barheight-1); } outtextxy(x+5,temp->number*Mb->barheight+5,temp->content); temp=temp->next; } } 4. 進(jìn)入菜單 /*根據(jù)menu指定的字符串,說明用戶從哪項菜單進(jìn)入菜單, 如gotomenucur(”File”)說明用戶激活了“File”菜單*/ void gotomenucur(char *menu){ Mb->mpoint=Mb->mhead; while(Mb->mpoint->next!

17、=NULL){ if(stricmp(Mb->mpoint->content,menu)==0) break; Mb->mpoint=Mb->mpoint->next; } Mb->mpoint->sub=Mb->mpoint->head; Mb->mpoint->sub->isactive=1; drawsubmenu(); } 5. 菜單按鍵處理 void menukey(){ int key; while(1){ key=get_key(); switch(key){ case KEY_LEFT: /*說明用戶按下了向

18、左按鍵,Mb->mpoint應(yīng)該向前移一項*/ Mb->mpoint->sub->isactive=0; backimage(Mb->mpoint->number*Mb->baritemwidth+Mb->x,Mb->barheight+2); if(Mb->mpoint->before!=NULL) /*如果當(dāng)前已經(jīng)是mhead了,應(yīng)該指向mtail*/ Mb->mpoint=Mb->mpoint->before; else Mb->mpoint=Mb->mtail; Mb->mpoint->sub=Mb->mpoin

19、t->head; Mb->mpoint->sub->isactive=1; drawsubmenu();/*重畫菜單,跳出*/ break; case KEY_RIGHT: /*說明用戶按下了向右鍵,解釋同KEY_LEFT*/ Mb->mpoint->sub->isactive=0; backimage(Mb->mpoint->number*Mb->baritemwidth+Mb->x,Mb->barheight+2); if(Mb->mpoint->next!=NULL) Mb->mpoint=Mb->mpoin

20、t->next; else Mb->mpoint=Mb->mhead; Mb->mpoint->sub=Mb->mpoint->head; Mb->mpoint->sub->isactive=1; drawsubmenu(); break; case KEY_UP: /*說明用戶按下了向上鍵,應(yīng)把當(dāng)前激活的菜單項向上移一項*/ Mb->mpoint->sub->isactive=0; backimage(Mb->mpoint->number*Mb->baritemwidth+Mb->x,Mb->barhe

21、ight+2); if(Mb->mpoint->sub->before!=NULL) Mb->mpoint->sub=Mb->mpoint->sub->before; else Mb->mpoint->sub=Mb->mpoint->tail; Mb->mpoint->sub->isactive=1; drawsubmenu(); break; case KEY_DOWN: /*說明用戶按下了向下鍵,當(dāng)前菜單項應(yīng)向下移一項*/ Mb->mpoint->sub->isactive=0; back

22、image(Mb->mpoint->number*Mb->baritemwidth+Mb->x,Mb->barheight+2); if(Mb->mpoint->sub->next!=NULL) Mb->mpoint->sub=Mb->mpoint->sub->next; else Mb->mpoint->sub=Mb->mpoint->head; Mb->mpoint->sub->isactive=1; drawsubmenu(); break; case ENTER: /*說明用戶按下了回車鍵,調(diào)用Mb->d

23、ocommand()*/ Mb->mpoint->sub->isactive=0;backimage(Mb->mpoint->number*Mb->baritemwidth+Mb->x,Mb->barheight+2);Mb->docommand();return; case ESC: /*說明用戶按下了退出鍵,把拷貝的屏幕區(qū)域放回,不作任何處理*/ Mb->mpoint->sub->isactive=0;backimage(Mb->mpoint->number*Mb->baritemwidth+Mb->x,Mb->barheight+2);return; } } }

24、 游標(biāo)與滾屏 l 思想 在屏幕上顯示的是兩個隊列,一個是等待隊列,一個是就緒隊列。設(shè)置了一個游標(biāo),可以用上下鍵移動指向每個進(jìn)程,然后對指向進(jìn)程進(jìn)行各種操作,包括掛起,解掛,刪除。我設(shè)置的屏幕上最多只能顯示12個進(jìn)程,就緒最多6個,等待最多6個,那么當(dāng)進(jìn)程多于此數(shù)時,在用戶按上下鍵時,應(yīng)該有滾屏功能。滾屏的思想如下:假設(shè)有就緒隊列里有N1個進(jìn)程,每個進(jìn)程編號1,2,3…….N1-1,N1。等待隊列中有N2個進(jìn)程,每個進(jìn)程編號1,2,3……N2-1,N2。假設(shè)當(dāng)前游標(biāo)指向的進(jìn)程編號小于6,則繪畫1到6個進(jìn)程(如果進(jìn)程數(shù)小于6則畫出所有進(jìn)程),如果當(dāng)前游標(biāo)指向的進(jìn)程編號為N(N>6),則繪畫

25、N-6到N個,這樣就實現(xiàn)了滾屏。當(dāng)當(dāng)前游標(biāo)位置位于就緒隊列結(jié)尾,則當(dāng)用戶按下向下按鍵時,應(yīng)該將游標(biāo)移動到等待隊列的第一個;當(dāng)當(dāng)前游標(biāo)位置位于就緒隊列第一個,則當(dāng)用戶按下向上按鍵時,應(yīng)該移動到等待隊列最后一個;同理,當(dāng)當(dāng)前游標(biāo)位于等待隊列隊尾對首時,應(yīng)移動就緒隊列隊首隊尾。 l 函數(shù)實現(xiàn) 因為我把等待隊列和就緒隊列放在同一個鏈表里,所以要實現(xiàn)上面的功能可能有點problem,但多用幾個函數(shù)就能實現(xiàn)。 1. /*這個函數(shù)用來給每個進(jìn)程編號*/ void updateprocess(){ int i=1,j=1; process *temp; temp=phead; whil

26、e(temp){ if(temp->isrun){ /*給就緒隊列中的進(jìn)程編號*/ temp->pos=i++; }else {/*給等待隊列中的進(jìn)程編號*/ temp->pos=j++; } temp=temp->next; } } 2. /*這個函數(shù)用來得到列表中就緒隊列中的第一個*/ process *getfirstrun(){ process *temp; if(!phead) return NULL; temp=phead; while(temp!=NULL){ if(temp->isrun)

27、{ /*找到第一個,就跳出循環(huán)*/ break; } temp=temp->next; } return temp->isrun?temp:NULL; /*如果找到就返回,否則就返回NULL,因為可能存在唯一一個等待隊列中的*/ } 3. /*該函數(shù)用來獲取列表中就緒隊列中的最后一個*/ process *gettailrun(){ process *temp; if(!ptail) /*如果列表為空,則返回NULL*/ return NULL; temp=ptail; /*從列表尾部開始找*/ while(t

28、emp!=NULL){ if(temp->isrun){ /*如果找到,就跳出循環(huán)*/ break; } temp=temp->before; } return temp->isrun?temp:NULL; /*判斷找到的是不是就緒隊列中的如果不是就返回NULL,因為可能存在只有一個等待隊列中的*/ } 4. /*這個函數(shù)用來找相對于p的下一個就緒隊列中的進(jìn)程*/ process *getnextrun(process *p){ process *temp; if(!p) return NULL; temp=p-

29、>next; while(temp!=NULL){ if(temp->isrun) /*如果找到,就跳出循環(huán)*/ break; temp=temp->next; } return temp; } 5. /*這個函數(shù)用來找相對于p的前一個就緒隊列中的進(jìn)程*/ process *getbeforerun(process *p){ process *temp; if(!p) return NULL; temp=p->before; while(temp!=NULL){ if(temp->isrun)

30、 break; temp=temp->before; } return temp; } 6. /*這個函數(shù)用來找等待隊列中的第一個,一下三個函數(shù)原理跟就緒隊列中的操作函數(shù)一樣,,只是把查找的條件改成!temp->isrun*/ process *getfirstready(){ process *temp; if(!phead) return NULL; temp=phead; while(temp!=NULL){ if(!temp->isrun){ break; } temp=temp->ne

31、xt; } return temp->isrun?NULL:temp; } 7. process *gettailready(){ process *temp; if(!ptail) return NULL; temp=ptail; while(temp!=NULL){ if(!temp->isrun){ break; } temp=temp->before; } return temp->isrun?NULL:temp; } 8. process *getnextready(process

32、*p){ process *temp; if(!p) return NULL; temp=p->next; while(temp!=NULL){ if(!temp->isrun) break; temp=temp->next; } return temp; } 9. process *getbeforeready(process *p){ process *temp; if(!p) return NULL; temp=p->before; while(temp!=NULL){ i

33、f(!temp->isrun) break; temp=temp->before; } return temp; } 10. /*這個函數(shù)用來得到下一個游標(biāo)的位置*/ void getnext(){ process *temp; if(phead==ptail){/*如果鏈表中只有一個進(jìn)程,則什么也不處理,返回*/ ppoint=phead; return; } if(ppoint==gettailrun()){/*如果當(dāng)前游標(biāo)位置是就緒隊列中的最后一個*/ temp=getfirstready();/*則指

34、向第一個等待隊列*/ ppoint=temp?temp:getfirstrun(); }else if(ppoint==gettailready()){/*如果當(dāng)前游標(biāo)位置是等待隊列中的最后一個*/ temp=getfirstrun();/*則指向就緒隊列中的第一個*/ ppoint=temp?temp:getfirstready(); }else if(ppoint->isrun){ /*如果當(dāng)前隊列在就緒隊列中移動*/ ppoint=getnextrun(ppoint); /*移向就緒隊列中的下一個*/ }else { ppoint

35、=getnextready(ppoint); /*移向等待隊列中的下一個*/ } } 11. /*這個函數(shù)用來得到上一個游標(biāo)的位置,基本的解釋同getnext()差不多*/ void getbefore(){ process *temp; if(phead==ptail) { ppoint=phead; return; } if(ppoint==getfirstrun()){ temp=gettailready(); ppoint=temp?temp:gettailrun(); }else if(ppoint==g

36、etfirstready()){ temp=gettailrun(); ppoint=temp?temp:gettailready(); }else if(ppoint->isrun){ ppoint=getbeforerun(ppoint); }else { ppoint=getbeforeready(ppoint); } } 12. /*按鍵處理函數(shù)*/ void key_U_D(int key){ switch(key){ case KEY_DOWN:if(!phead) ppoint=NULL;else getnext

37、();break;/*如果按下的是向下鍵*/ case KEY_UP:if(!ptail) ppoint=NULL;else getbefore();break; /*如果按下的是向上鍵*/ } if(ppoint){ /*drawl_r(int,int)這個函數(shù)根據(jù)傳遞進(jìn)來的兩個參數(shù)指明應(yīng)該畫的起始編號*/ if(ppoint->pos>6){ if(ppoint->isrun){ drawl_r(ppoint->pos-6,0); }else { drawl_r(0,ppoint->pos-6); } }else dra

38、wl_r(0,0); }else drawl_r(0,0); } 獲取用戶按鍵 C語言庫函數(shù)提供的getch(),或bioskey()在處理字符和菜單輸入時有點麻煩,改寫了一個函數(shù) int get_key() { union REGS rg; rg.h.ah=0; int86(0x16,&rg,&rg); if(rg.h.al==0){/*說明按下了修飾鍵,把這個值左移8位*/ return rg.h.ah<<8; } return rg.h.al; /*直接返回按下的鍵值,實際上是ASCII*/ } 舉例: 當(dāng)用戶按下ALT+F時,

39、返回的是8448,而按下F時,返回的是F的ASCII 圖形屏幕下獲取用戶的輸入 因為這次課程設(shè)計只需獲得用戶輸入的整數(shù),所以處理也比較簡單。 long getinput(char *mess){/*輸入框提示的信息*/ char desc[50],number[10],*endptr,*image; int i=0,key,width,x=200,y=300,size,color; width=strlen(mess)+10; /*計算窗口的寬度,按字符數(shù)來算,其中輸入的數(shù)字長度最大為10*/ size=imagesize(x,y,x+width*6,y+50);

40、 /*把窗口內(nèi)的屏幕保存下來*/ if((image=(char *)malloc(size))==NULL) doerror("System error"); getimage(x,y,x+width*6,y+50,image); setfillstyle(1,getbkcolor()); bar(x,y,x+width*6,y+50); rectangle(x,y,x+width*6,y+50); /*用背景色覆蓋一下,相當(dāng)于清屏*/ strcpy(desc,mess); outtextxy(x+10,y+20,mess); while((key=ge

41、t_key())!=ENTER){ /*如果沒有按下回車,則不退出*/ if(key==ESC){ /*如果按下ESC,則把拷貝的屏幕放回去,返回-1*/ putimage(x,y,image,0); free(image); return -1; } if(key>=48&&key<=57||key==8){ /*如果按下的是數(shù)字鍵或者是退格鍵*/ if(key==8){ /*如果是退格鍵,就用背景色把原來的字符畫一遍,相當(dāng)于覆蓋,然后去掉結(jié)尾一個,用前景色畫字符,就相當(dāng)于刪掉一個字符(實際上也刪掉了)*/ color=getcol

42、or(); setcolor(getbkcolor()); outtextxy(x+10,y+20,strcat(desc,number)); setcolor(color); number[--i]=\0; /*這句相當(dāng)于刪掉一個字符*/ }else if(i<10){ number[i++]=key; /*把字符附加到末尾*/ number[i]=\0; } desc[strlen(mess)]=\0; outtextxy(x+10,y+20,strcat(desc,number)); }

43、 } putimage(x,y,image,0); free(image); return strtol(number,&endptr,10); /*把輸入的字符轉(zhuǎn)換為數(shù)字返回*/ } 程序執(zhí)行流程 首先說明一下handle()函數(shù)的功能: void handler(){ int time,i,j,pos;/*time用來記錄上次執(zhí)行handle到這次執(zhí)行handle的時間間隔,i,j用來控制循環(huán),pos用來記錄光標(biāo)(用來指向每個進(jìn)程的一個小方塊)的位置*/ if(ppoint!=NULL){ if(ppoint->pos>6){ /*因為每個隊列最多只能顯示

44、6個隊列,所以當(dāng)當(dāng)前光標(biāo)指向的進(jìn)程的pos>6時,pos一定是底部 pos=6; }else { pos=ppoint->pos; } bar((1-ppoint->isrun)*450,(pos-1)*50+80,(1-ppoint->isrun)*450+15,(pos-1)*50+85); }/*畫一個游標(biāo) if(stop) /*stop是全局變量(為這是一個模擬程序,所以當(dāng)用戶想暫?;蛘呤裁吹?,可以暫停)果stop是true,則什么事都不做 return; i=getnum(1); /*獲取就緒隊列中的進(jìn)程總數(shù)*/ j=getnu

45、m(0); /*獲取等待隊列中的進(jìn)程總數(shù)*/ if((i+j)<=0){ /*如果兩個隊列為空*/ stop=1; fresh();/*刷新一下屏幕*/ return; } if(i0&&canrun){ /*如果就緒隊列中的進(jìn)程數(shù)小于maxrun(maxrun為就緒隊列中的最大數(shù)目)且等待隊列不為空,且有足夠的內(nèi)存(maxrun為true時表示有足夠內(nèi)存)*/ getfromeready();/*從等待隊列中選取一個優(yōu)先級最高,時間最少的*/ coverfront();/*把游標(biāo)重畫一遍(這里放這個函數(shù)好像有點多余)*/ }

46、 gettime(&t2); time=(t2.ti_hour-t1.ti_hour)*60*60*100+(t2.ti_min-t1.ti_min)*60*100+(t2.ti_sec-t1.ti_sec)*100+t2.ti_hund-t1.ti_hund; /*計算兩次執(zhí)行handle的時間差,其實可以用gettime()這個庫函數(shù),但當(dāng)時沒發(fā)現(xiàn)。*/ runtime-=time; /*runtime是時間片大小,是個全局變量*/ drawsector();/*畫屏幕中間的時間片轉(zhuǎn)盤*/ if(runtime<=0){ /*如果當(dāng)前時間片用完了*/ update

47、pri();/*更新一下進(jìn)程優(yōu)先權(quán),防止餓死*/ drawl_r(0,0); /*重畫進(jìn)程列表*/ Find_H_P();/*從就緒隊列中找優(yōu)先級最高的,時間最少的*/ runtime=roundtime; /*roundtime是用來供用戶設(shè)定時間片大小的,把runtime的大小設(shè)為roundtime*/ }else { drawcur(time); /*畫運(yùn)行進(jìn)程,這實際是個動畫。*/ } t1=t2; /*更新t1的值,作為下次時間計算的標(biāo)準(zhǔn)*/ setfillstyle(1,RED); /*重新設(shè)定填充模式,因為drawcru(time)函數(shù)中可

48、能改變了填充模式*/ } Handle函數(shù)流程圖: 判斷stop 等隊列中的進(jìn)程總數(shù)小于maxrun且等待隊列中有進(jìn)程且有足夠內(nèi)存, 從等待隊列中選取一個優(yōu)先級最高,時間最少的進(jìn)程進(jìn)就緒隊列 從運(yùn)行隊列中減去所運(yùn)行了的時間,并用進(jìn)度條在屏幕上顯示出來 False 是 否 因為程序中用到了菜單,所以程序要保證執(zhí)行handle(),同時又不能耽誤用戶的輸入對菜單的操作,有兩種方法。 方法一:利用DOS的時鐘中斷 int 21HAH=0x1C每秒產(chǎn)生18.2次中斷。在main函數(shù)中添加 oldhandler = getvect(INTR); setvect(INTR

49、, handler); 其中INTR為宏定義#define INTR 0x1c 程序的流程圖: 等待用戶按鍵 捕獲按鍵,進(jìn)行相應(yīng)處理 處理結(jié)束 產(chǎn)生時鐘中斷,調(diào)用handle函數(shù) 產(chǎn)生中斷 方法二:用kbhit()檢測是否有有按鍵按下,如果有,則調(diào)用相應(yīng)的按鍵處理函數(shù),如果沒有則執(zhí)行handle函數(shù),然后調(diào)用delay函數(shù)延遲下一個循環(huán)。 程序流程圖: 是否有鍵盤按下 捕獲按鍵進(jìn)行相應(yīng)處理 處理結(jié)束 執(zhí)行handle函數(shù) 本次循環(huán)延世 沒有 有 算法描述: 進(jìn)程調(diào)度算法:如果stop為false,說明用戶開始程序模擬,檢查等待隊列中的進(jìn)程總數(shù)是否為m

50、axrun(為系統(tǒng)運(yùn)行的負(fù)載),如果小于,則檢查等待隊列中是否有進(jìn)程,如果有,則再檢查是否有足夠內(nèi)存,如果都滿足,則從等待隊列中選取優(yōu)先級最高,時間最少的進(jìn)程運(yùn)行。 當(dāng)一個時間片運(yùn)行完時,則加大就緒隊列中相對低優(yōu)先級的優(yōu)先級數(shù),然后再選取下一個優(yōu)先級最高,時間最少的運(yùn)行。這樣可以防止低優(yōu)先級進(jìn)程的餓死。 內(nèi)存分配算法:在選進(jìn)程進(jìn)入就緒隊列前,先看看當(dāng)前內(nèi)存分配算法是最佳適應(yīng)還是最先適應(yīng),看內(nèi)存中是否存在一塊足夠的內(nèi)存,如果足夠,則從內(nèi)存中劃去這一塊,如果這一塊相同大,則要刪除該鏈表節(jié)點。 內(nèi)存回收算法:當(dāng)一個進(jìn)程運(yùn)行結(jié)束時,要回收內(nèi)存,先記錄下該內(nèi)存塊的起始和終止地址,遍歷內(nèi)存鏈表,看該

51、塊內(nèi)存的相鄰兩塊是不是也是空閑的,這時候可能會出現(xiàn)三種情況: 情況一:相鄰兩塊只有一塊是空閑的,則直接合并進(jìn)去; 情況二:相鄰兩塊都是空閑的,則要把這三塊合并成一塊,并刪除一個節(jié)點; 情況三:相鄰兩塊都不空閑,則直接創(chuàng)建一個內(nèi)存節(jié)點,放入隊尾。 最佳適應(yīng)算法:遍歷空閑內(nèi)存塊鏈表,找出大于所需內(nèi)存大小且是最小的一塊。 最先適應(yīng)算法:從兩表頭開始,只要找到一塊大于所需大小的就停止。 PCB數(shù)據(jù)結(jié)構(gòu) typedef struct process_t{ int pid;/*進(jìn)程的pid*/ int isrun; /*進(jìn)程是否在就緒隊列中,因為所有狀態(tài)的進(jìn)程都在一個隊列中,所以必須

52、有這些標(biāo)識符變量來識別,實際操作系統(tǒng)中不是這樣的*/ int ishalt; /*進(jìn)程是否被掛起*/ int pos; /*進(jìn)程在屏幕中的位置,從1開始按等待和就緒遞增*/ int priority; /*進(jìn)程的優(yōu)先級*/ int time_total; /*所需時間總數(shù)*/ int time_left; /*還剩下的時間*/ long startaddr; /*內(nèi)存的起始地址*/ long size; /*內(nèi)存的大小*/ void (*fun)(); /*函數(shù)入口*/ struct process_t *next; /*指向下一個pcb*/ struc

53、t process_t *before; /*指向上一個pcb*/ }process; 內(nèi)存空閑塊數(shù)據(jù)結(jié)構(gòu) typedef struct memory_t{ long startaddr;/*內(nèi)存的起始地址*/ long size;/*空閑內(nèi)存的大小*/ struct memory_t *next; /*指向下一個空閑內(nèi)存塊*/ struct memory_t *before; /*指向上一個空閑內(nèi)存塊*/ }memory; 屏幕畫圖 菜單畫法: 先計算當(dāng)前所畫菜單的大小,在內(nèi)存開辟一個區(qū)域保存所畫區(qū)域內(nèi)容,然后從菜單頭節(jié)點開始畫一直畫到鏈表末尾,如果用戶取消了或

54、者按下了回車只要把保存的內(nèi)容放回原來的地方。 進(jìn)程在屏幕上的畫法: 由于鏈表只有一個,而有就緒,等待,運(yùn)行三個隊列,其實運(yùn)行中只有一個進(jìn)程,只要在用一個process指針指向當(dāng)前運(yùn)行進(jìn)程就可以了。那么怎么把同一個鏈表中的進(jìn)程分別畫在屏幕兩邊的就緒和等待隊列中呢?(1-process->isrun)*screenweidth,這樣,如果它是就緒隊列中的(它的isrun是1),它就在屏幕的左邊,如果它是等待隊列中的(它的isrun是0),它就在屏幕的右邊。 關(guān)于集成圖形驅(qū)動做成exe文件 在tc里頭,生成的exe文件如果是文本模式的,則可以運(yùn)行,而如果是圖形模式的,生成的exe老是提示你沒

55、有初始化圖形驅(qū)動,可以把圖形驅(qū)動集成到graphic里頭,方法如下: 注冊圖形驅(qū)動: bgiobj EGAVGA 回車 得到EGAVGA.OBJ TLIB LIB\GRAPHICS.LIB+EGAVGA.OBJ回車即可 在程序中用registerbgidriver(EGAVGA_driver); 其它對應(yīng)的如下 CAG.BGI CGA_driver EGA.VGA.BGI EGAVGA_driver HERC.BGI HERC_driver ATT.BGI ATT_driver PC3270.BGI PC3270_driver IBM8514.BGI IBM

56、8514_driver 注冊字體: bgiobj trip|litt|sans|goth分別對應(yīng)字體trip.chr|litt.chr|sans.chr|goth.chr tlib lib\graphics.lib+litt.obj 字型驅(qū)動 registerbgifont() litt.chr tlib得到的字符名入"samll_font" 源程序: #include #include #include #include #include #include

57、h.h> #include /*包含一些必要的頭文件*/ #define INTR 0X1C/*定義時鐘中斷號*/ #define ENTER 13/*定義回車鍵*/ #define KEY_UP 18432/*定義向上鍵的整數(shù)值*/ #define KEY_DOWN 20480/*定義向下鍵的整數(shù)值*/ #define KEY_LEFT 19200/*定義向左鍵的整數(shù)值*/ #define KEY_RIGHT 19712/*定義向右鍵的整數(shù)值*/ #define ALT_F 8448/*定義按下alt+f返回的整數(shù)值*/ #define ALT_S 79

58、36/*定義按下alt+s返回的整數(shù)值*/ #define ALT_O 6144/*定義alt+o返回的整數(shù)值*/ #define ALT_H 8960/*定義alt+h返回的整數(shù)值*/ #define ESC 27/*定義esc返回的整數(shù)值,以上這些鍵值都是有g(shù)et_key()函數(shù)獲得*/ typedef struct menubar_s{ int number,x,y,barheight,baritemwidth; struct menu_s *mhead; struct menu_s *mtail; struct menu_s *mpoint; void (*

59、 docommand)(); }MenuBar; /*定義一個菜單欄數(shù)據(jù)結(jié)構(gòu),在上面已經(jīng)解釋過*/ typedef struct menu_s{ int number; int subwidth; int subcount; char *content; struct menu_s *next; struct menu_s *before; struct submenu_s *sub; struct submenu_s *head; struct submenu_s *tail; }Menu; /*定義一個菜單結(jié)構(gòu)體,具體在上面已經(jīng)解釋過*/ typ

60、edef struct submenu_s{ int number; int isactive; char *content; struct submenu_s *next; struct submenu_s *before; }submenu; /*定義一個菜單項,具體已在上面解釋過*/ typedef struct process_t{ int pid; int isrun; int ishalt; int pos; int priority; int time_total; int time_left; long startaddr

61、; long size; void (*fun)(); struct process_t *next; struct process_t *before; }process; /*定義一個pcb,在上面已經(jīng)解釋過*/ typedef struct memory_t{ long startaddr; long size; struct memory_t *next; struct memory_t *before; }memory; /*定義一個空閑內(nèi)存塊結(jié)構(gòu),在上面已經(jīng)解釋過*/ void docommand(); void drawprocess(p

62、rocess *,int,int,int,int); void readfile(); void writefile(); void drawl_r(int,int); void addprocess(); long getinput(char *); void savefile(); void fresh(); int findm_f_f(process *p); int findm_b_f(process *p); long getfreesize(); void acceptm_f_f(process *p); void drawmembar(); void c

63、reatememory(long,long); void rancreatep(long num); void randomcreate(); void setmemsize();/*一些函數(shù)聲明,一下開始定義全局變量*/ MenuBar *Mb; /*一個菜單欄*/ void *buff; /*用來保存畫菜單時預(yù)先保存的區(qū)域*/ process *phead,*ptail,*prunning,*ppoint; /*用來保存進(jìn)程隊列的頭,尾,正在運(yùn)行,和當(dāng)前游標(biāo)指向的一個進(jìn)程*/ struct time t1,t2; /*定義兩個time結(jié)構(gòu)體類型,用來記錄在兩次handle函數(shù)

64、執(zhí)行之間的時間差*/ memory *mhead,*mtail; /*空閑內(nèi)存塊的頭尾指針*/ int roundtime=500,runtime=500,maxrun=5,stop=1,canrun=1,memway=1; /*roundtime用來保存時間片大小,runtime用來保存當(dāng)前時間片大小,maxrun用來保存系統(tǒng)所能運(yùn)行的最大進(jìn)程數(shù),stop用來控制是否停止模擬,canrun用來記錄系統(tǒng)是否有足夠內(nèi)存,memway用來記錄當(dāng)前內(nèi)存的適應(yīng)方式(最佳適應(yīng)還是最先適應(yīng))*/ long memorysize=35460L; /*用來定義內(nèi)存大小*/ int get_key()

65、 { union REGS rg; rg.h.ah=0; int86(0x16,&rg,&rg); if(rg.h.al==0){ return rg.h.ah<<8; } return rg.h.al; }/*這個函數(shù)用來獲取按鍵值,在上面已經(jīng)解釋過*/ void doerror(char *s){ int color; setfillstyle(1,getbkcolor()); bar(200,200,300,300); rectangle(300,300,400,400); outtextxy(320,340,s); g

66、etch(); closegraph(); exit(1); }/*如果系統(tǒng)內(nèi)存不足或者文件打不開,給出提示信息,并結(jié)束程序(目前也只能這樣做)*/ void addmenu(char *menutitle){ /*添加一個菜單*/ if(Mb==NULL){ /*如果Mb為NULL,說明菜單欄還沒有初始化,接下去執(zhí)行一些初始化工作*/ if((Mb=(MenuBar *)malloc(sizeof(MenuBar)))==NULL) doerror("System error");/*分配一塊內(nèi)存區(qū)域*/ Mb->number=0; Mb->mpoint=Mb->mhead=Mb->mtail=NULL; Mb->x=0; Mb->y=0; Mb->barheight=18; Mb->baritemwidth=100; Mb->docommand=docommand; /*初始化Mb中的一些變量,具體的變量含義已在上面解釋過*/ } if(Mb->mtail==NULL){ /*如果當(dāng)

展開閱讀全文
溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!