《操作系统课程设计实验报告1.doc》由会员分享,可在线阅读,更多相关《操作系统课程设计实验报告1.doc(32页珍藏版)》请在三一办公上搜索。
1、操作系统课程设计报告专 业 计算机科学与技术 班 级 0905班 学 号 姓 名 指 导 教 师 时 间 2011-12-1 湖 北 师 范 学 院计 算 机 科 学 与 技 术 学 院目 录1、 处理器调度1.1实验内容11.2实验目的11.3实验题目11.4实验代码51.5实验小结91.6模拟运行92、主存存储器空间的分配和回收2.1实验内容112.2实验目的112.3实验题目112.4实验代码122.5实验小结182.6模拟运行193、 驱动调度3.1实验内容213.2实验目的213.3实验题目213.4实验代码243.5实验小结303.6模拟运行31实验一 处理器调度一、实习内容:选择
2、一个调度算法,实现处理器调度。二、实习目的:在采用多道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。本实习模拟在单处理器情况下的处理器调度,帮助学生加深了解处理器调度的工作。三、实习题目:本实习有两个题,学生可选择其中的一题做实习。第一题:设计一个按优先数调度算法实现处理器调度的程序。提示:(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表,进程控制块的格式为:进程名指针要求运行时间优先数状态其中,进程名作为进程的标识,假设五个进程的进程名分别为P1,P2,P3,P4,P5。指针按优先数的大小把
3、五个进程连成队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程中的指针为“0”。要求运行时间假设进程需要运行的单位时间数。优先数赋予进程的优先数,调度时总是选取优先数大的进程先执行。状态可假设有两种状态,“就绪”状态和“结束”状态。五个进程的初始状态都为“就绪”,用“R”表示,当一个进程运行结束后,它的状态为“结束”,用“E”表示。(2) 在每次运行你所设计的处理器调度程序之前,为每个进程任意确定它的“优先数”和“要求运行时间”。(3) 为了调度方便,把五个进程按给定的优先数从大到小连成队列。用一单元指出队首进程,用指针指出队列的连接情况。例: 队首标志 K2 K1P1 K2P2 K
4、3P3 K4P4 K5P50K4K5K3K12312415342RRRRRPCB1PCB2PCB3PCB4PCB5(4) 处理器调度总是选队首进程运行。采用动态改变优先数的办法,进程每运行一次优先数就减“1”。由于本实习是模拟处理器调度,所以,对被选中的进程并不实际的启动运行,而是执行:优先数-1要求运行时间-1来模拟进程的一次运行。提醒注意的是:在实际的系统中,当一个进程被选中运行时,必须恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行结束。在这里省去了这些工作。(5) 进程运行一次后,若要求运行时间0,则再将它加入队列(按优先数大小插入,且置队首标志);若要求运行时间=0,则把它
5、的状态修改成“结束”(E),且退出队列。(6) 若“就绪”状态的进程队列不为空,则重复上面(4)和(5)的步骤,直到所有进程都成为“结束”状态。(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次被选中进程的进程名以及运行一次后进程队列的变化。(8) 为五个进程任意确定一组“优先数”和“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中进程的进程名以及进程控制块的动态变化过程。第二题:设计一个按时间片轮转法实现处理器调度的程序。提示:(1) 假定系统有五个进程,每一个进程用一个进程控制块PCB来代表。进程控制块的格式为:进程名指针要求运行时间已运行时间状态其中,进程名作为
6、进程的标识,假设五个进程的进程名分别为Q1,Q2,Q3,Q4,Q5。指针进程按顺序排成循环队列,用指针指出下一个进程的进程控制块的首地址,最后一个进程的指针指出第一个进程的进程控制块首地址。要求运行时间假设进程需要运行的单位时间数。已运行时间假设进程已经运行的单位时间数,初始值为“0”。状态有两种状态,“就绪”和“结束”,初始状态都为“就绪”,用“R”表示。当一个进程运行结束后,它的状态为“结束”,用“E”表示。(2) 每次运行所设计的处理器调度程序前,为每个进程任意确定它的“要求运行时间”。(3) 把五个进程按顺序排成循环队列,用指针指出队列连接情况。另用一标志单元记录轮到运行的进程。例如,
7、当前轮到P2执行,则有:标志单元 , K2 K1Q1 K2Q2 K3Q3 K4Q4 K5Q5K2K3K4K5K12312410000RRRRRPCB1PCB2PCB3PCB4PCB5(4) 处理器调度总是选择标志单元指示的进程运行。由于本实习是模拟处理器调度的功能,所以,对被选中的进程并不实际的启动运行,而是执行:已运行时间+1来模拟进程的一次运行,表示进程已经运行过一个单位的时间。请同学注意:在实际的系统中,当一个进程被选中运行时,必须置上该进程可以运行的时间片值,以及恢复进程的现场,让它占有处理器运行,直到出现等待事件或运行满一个时间片。在这时省去了这些工作,仅用“已运行时间+1”来表示进
8、程已经运行满一个时间片。(5) 进程运行一次后,应把该进程的进程控制块中的指针值送到标志单元,以指示下一个轮到运行的进程。同时,应判断该进程的要求运行时间与已运行时间,若该进程的要求运行时间已运行时间,则表示它尚未执行结束,应待到下一轮时再运行。若该进程的要求运行时间=已运行时间,则表示它已经执行结束,应指导它的状态修改成“结束”(E)且退出队列。此时,应把该进程的进程控制块中的指针值送到前面一个进程的指针位置。(6) 若“就绪”状态的进程队列不为空,则重复上面的(4)和(5)的步骤,直到所有的进程都成为“结束”状态。(7) 在所设计的程序中应有显示或打印语句,能显示或打印每次选中进程的进程名
9、以及运行一次后进程队列的变化。(8) 为五个进程任意确定一组“要求运行时间”,启动所设计的处理器调度程序,显示或打印逐次被选中的进程名以及进程控制块的动态变化过程。四、实习报告:(1) 实习题目。(2) 程序中使用的数据结构及符号说明。(3) 流程图。(4) 打印一份源程序并附上注释。(5) 打印程序运行时的初值和运行结果。要求如下: 进程控制块的初始状态。 选中运行的进程名以及选中进程运行后的各进程控制块状态。对于要求每选中一个进程运行后都要打印。五、实验代码:#include #include typedef structchar name20;/进程名int time;/进程要求运行的时
10、间int priv;/进程优先级数char state;/进程状态DATA;/进程PCBtypedef struct PRODATA data;PRO *next;Node;typedef Node *HEAD;HEAD head;int h=5;/当前运行进程个数int k=0;/当前总进程个数int y=5;/时间片HEAD Createpro(void) /创建进程PCB链表HEAD head=(Node*)malloc(sizeof(Node);Node *p,*head1;head1=head;int i=1;int d,o,m;printf(进程个数:);scanf(%d,&m);
11、k=m;h=m;while(idata.name,&d,&o);p-data.time=d;p-data.priv=o;p-data.state=R;head1-next=p;head1=p;i+;head1-next=NULL;system(cls);return head;void prin(HEAD head)/打印所有进程信息Node *p;int i=1;if (h!=0)p=head-next;while (idata.name,p-data.time,p-data.priv,p-data.state);p=p-next;i+;elseprintf(Process run over
12、);Sleep(500);system(cls);HEAD arreng(HEAD head)/对进程优先级进行排列Node *p,*p2,*p1,*p3;p3=head; int t;p=head-next;for (;)if (t=0) break;p=head-next;p1=p-next;p2=head;int n=0;for (int l=1;ldata.privdata.priv)p-next=p1-next;p1-next=p;if (p=p3-next)p3-next=p1;elsep2-next=p1;p2=p1;p1=p-next;n+; else p2=p;p=p-nex
13、t;p1=p1-next;if (p=p3-next)p3-next=p;if (l=h-1&n=0)t=0;return p3;HEAD run(HEAD head)/执行的过程并显示当前运行进程信息Node *p,*p1,*p2;if (h!=0)system(title %s);p=head-next;printf(此次运行的进程是%s 剩余时间片为%d 当前运行进程总数%dn,p-data.name,y,h);if (p-data.priv!=0)p-data.time=p-data.time-1;y-;if (y=0)y=5;p-data.priv=p-data.priv-1;p2=
14、p;for (int i=1;inext;elsep-data.time=p-data.time-1;p2=p;for (int i=1;inext;p2-data.priv=p2-data.priv+1;if (p-data.time=0)head-next=p-next;h-;p-data.priv=0;p-data.state=E;p1=p;for (int i=k-1;i0;i-)p1=p1-next;p1-next=p;p-next=NULL;printf(当前进程运行信息 |运行时间|%4d| 优先级|%3d| 运行状态|%c|nn,p-data.time,p-data.priv,
15、p-data.state);return head;int main()HEAD head;system(title 模拟CPU优先级调度算法);head=Createpro();head=arreng(head);for (;)head=run(head);if (h1)/当进程大于1时进行排列head=arreng(head);prin(head);return 0;六、实验小结:结合CPU时间片轮转算法和优先级调度算法组成的动态优先级调度算法,初始化为每个进程分配时间片为5,当时间片结束后,优先级-1。当剩下所有进程优先级减为0时,将除当前运行进程外的其余进程优先级+1。既不违背谁优先级
16、高谁运行的原则,也运用了RR算法七、模拟运行:输入:进程个数:20第1个进程信息 进程名 运行时间 优先级:。第2个进程信息 进程名 运行时间 优先级:。以此类推输出:实验二 主存储器空间的分配和回收一、实习内容:主存储器空间的分配和回收。二、实习目的:一个好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能合理地分配和使用这些存储空间。当用户提出申请存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间的使用情况,找出足够的空闲区域分配给申请者。当作业撤离或主动归还主存资源时,则存储管理要收回作业占用的主存空间或归还部分主存空间。主存的分配和回收的实
17、现虽与主存储器的管理方式有关的,通过本实习帮助学生理解在不同的存储管理方式下应怎样实现主存空间的分配和回收。三、实习题目:模拟在分页式管理方式下采用位示图来表示主存分配情况,实现主存空间的分配和回收。提示:(1) 分页式存储器把主存分成大小相等的若干块,作业的信息也按块的大小分页,作业装入主存时可把作业的信息按页分散存放在主存的空闲块中,为了说明主存中哪些块已经被占用,哪些块是尚未分配的空闲块,可用一张位示图来指出。位示图可由若干存储单元来构成,其中每一位与一个物理块对应,用0/1表示对应块为空闲/已占用。(2) 假设某系统的主存被分成大小相等的64块,则位示图可用8个字节来构成,另用一单元记
18、录当前空闲块数。如果已有第0,1,4,5,6,9,11,13,24,31,共10个主存块被占用了,那么位示图情况如下:字 位 节 数 号01234567 011001110 101010100 200000000 310000001 400000000 500000000 600000000 700000000(3) 当要装入一个作业时,根据作业对主存的需要量,先查当前空闲块数是否能满足作业要求,若不能满足则输出分配不成功。若能满足,则查位示图,找出为“0”的一些位,置上占用标志“1”,从“当前空闲块数”中减去本次占用块数。按找到的计算出对应的块号,其计算公式为: 块号= j8+i其中,j表示
19、找到的是第n个字节,I表示对应的是第n位。根据分配给作业的块号,为作业建立一张页表,页表格式:页 号块 号012MM(4) 当一个作业执行结束,归还主存时,根据该作业的页表可以知道应归还的块号,由块号可计算出在位示图中的对应位置,把对应位的占用标志清成“0”,表示对应的块已成为空闲块。归还的块数加入到当前空闲块数中。由块号计算在位示图中的位置的公式如下:字节号 j=块号/8 ( 表示取整)位数 i=块号/8 ( 表示取余)(5) 设计实现主存分配和回收的程序。假定位示图的初始状态如(2)所述,现有一信息量为5页的作业要装入,运行你所设计的分配程序,为作业分配主存且建立页表(格式如(3)所述)。
20、然后假定有另一作业执行结束,它占用的块号为第4,5,6和31块,运行你所设计的回收程序,收回作业归还的主存块。要求能显示和打印分配或回收前后的位示图和当前空闲块数,对完成一次分配后还要显示或打印为作业建立的页表。四、实习报告:(1) 实习题目。(2) 程序中使用的数据结构及符号说明。(3) 流程图。(4) 打印一份源程序并附上注释。(5) 打印程序运行时的初值和运行结果,要求如下:打印位示图和当前空闲块数的初值;要求装入的作业对主存的申请量,为作业分配后的位示图、当前空闲块数和页表;作业归还的块号、回收作业所占主存后的位示图和当前空闲块数。五、实验代码:#include #include #i
21、nclude typedef struct BYTint byte18;int sur;BYT *next;byt;typedef byt *HEAD;HEAD head;typedef struct PAGEint byte264;char namenum16;int num;int pid;PAGE *next;page;typedef page *pagehead;pagehead head1;int surnum=64;int pronum=0;HEAD createbyt()/建立位数图表HEAD head=(byt*)malloc(sizeof(byt);HEAD head2;he
22、ad2=head;int i=0;while (i8)HEAD p=(byt*)malloc(sizeof(byt);for (int o=0;obyte1o=0;p-sur=0;head2-next=p;head2=p;i+;head2=NULL;return head;void printfbyt(HEAD head)/打印出当前位数图 HEAD p1; p1=head-next; char cmd100; sprintf(cmd,title 分页式管理方式中内存的分配和回收 当前空闲块数:%d,surnum); system(cmd); printf( 位数: 0 1 2 3 4 5 6
23、 7 n); printf(字节号:n); for (int i=0;ibyte10,p1-byte11,p1-byte12,p1-byte13,p1-byte14,p1-byte15,p1-byte16,p1-byte17,p1-sur);p1=p1-next;HEAD Distribution(HEAD head,int n)/对输入的块数经行查找和初始化分配HEAD p;int i,o;p=head-next;if (n7)o=(n)/8;i=n%8;for (int k=0;knext;p-byte1i=1;elsep-byte1n=1;return head;HEAD Initial
24、ization(HEAD head)/检查已装入块数的总数HEAD p;p=head-next;surnum=64;int l=0;for (int i=0;i8;i+)for (int o=0;obyte1o=1)l+; p-sur=l;surnum-=l;l=0;p=p-next; return head;HEAD Mount(HEAD head,pagehead head1)/申请内存HEAD p;pagehead p1;int l=0,k=0;p=head-next;p1=head1;int a=pronum;while (a)p1=p1-next;a-;pagehead p2=(pa
25、ge*)malloc(sizeof(page);printf(输入进程名称 申请信息量:n);scanf(%s %d,&p2-namenum,&p2-num);if (p2-numpid=rand();if (pronum0)while(p1-pid=p2-pid)srand(time(NULL);p2-pid=rand();if (p2-num=surnum)int numl=0;char cmd120;for (int i=0;i8;i+)for (int o=0;onum)break;if (p-byte1o=0)sprintf(cmd1,title 找到空闲:%d,numl);syst
26、em(cmd1);p2-byte2k=i*8+o;p-byte1o=1;l+;k+;p-sur+=l;surnum-=l;l=0;p=p-next;if (k=p2-num)break;p1-next=p2;p2-next=NULL;pronum+;system(cls);printfbyt(head);elseprintf(分配错误:没有足够的空间可以申请。n);return head;HEAD DROP(HEAD head,pagehead head1)/释放内存HEAD p;pagehead p1,p2;int i=0,o=0;p=head-next;p1=head1;p2=p1-nex
27、t;if (p2!=NULL|pronum!=0)system(cls);int o=0;int realnum=0;for (;p2!=NULL;p2=p2-next)if (p2-namenum0!=0) realnum+;printf(正在运行的进程:|%-15s| pid:%d| 已分配单位:%dn页表:n,p2-namenum,p2-pid,p2-num);printf(页号 快号n);int i=0;while(inum)printf(%2d %-2dn,i,p2-byte2i);i+;printf(n);if (realnum=0)printf(没有程序正在运行n);return
28、 0;printf(输入要回收的进程PID:n);int i=0;scanf(%d,&i);while (i!=p1-pid)p1=p1-next;if (p1=NULL) printf(没有此PDIn);return 0;for (int l=0;lnum;l+)p=head-next;if (p1-byte2l7)o=(p1-byte2l)/8;i=p1-byte2l-o*8;for (int k=0;knext;p-byte1i=0;elsep-byte1p1-byte2l=0;p1-namenum0=0;Initialization(head);system(cls);printfby
29、t(head);elseprintf(没有程序正在运行n);return head;int main()HEAD head;int m=1;pagehead head1=(page*)malloc(sizeof(page);head1-next=NULL;system(color F0);head=createbyt();head=Distribution(head,0);/初始化数据head=Distribution(head,1);head=Distribution(head,4);head=Distribution(head,6);head=Initialization(head);pr
30、intfbyt(head);while(m) int i=5;printf(1申请分配内存 2删除分配的内存 3退出:n);scanf(%d,&i);fflush(stdin);if (i0&i4)switch(i) case 1:Mount(head,head1); break; case 2:DROP(head,head1); break;case 3:m=0; break; elseprintf(输入了错误的指令!n);return 0;六、实验小结 : 数据结构:两个结构体,一个包含一个字节的信息(一个8位数组存放字节信息,一个占用总数信息),一个包含进程的信息(一个64位数组存放当前
31、进程存放位置,进程名,占用个数,进程PID)。(PID:为了防止有相同命名进程而给每个进程分个唯一的随机数) 程序流程:创建位示图,要求有64块,调用createbyt函数创建8个节点为字节信息的链表。初始化位示图,调用Initialization函数初始化0,1,4,6字节点。循环选择申请分配内存和删除分配的内存及退出,申请内存调用Mount函数,删除调用DROP函数。七、模拟运行:运行程序既得:选择1申请分配并输入分配信息:分配后的位示图选择2去配:去配后的位示图:实验三 驱动调度一、实习内容:模拟电梯调度算法,实现对磁盘的驱动调度。二、实习目的:磁盘是一种高速、大容量、旋转型、可直接存取
32、的存储设备。它作为计算机系统的辅助存储器,担负着繁重的输入输出任务,在多道程序设计系统中,往往同时会有若干个要求访问磁盘的输入输出请求等待处理。系统可采用一种策略,尽可能按最佳次序执行要求访问磁盘的诸输入输出请求,这就叫驱动调度,使用的算法称驱动调度算法。驱动调度能降低为若干个输入输出请求服务所需的总时间,从而提高系统效率。本实习要求学生模拟设计一个驱动调度程序,观察驱动调度程序的动态运行过程。通过实习使学生理解和掌握驱动调度的职能。三、实习题目:模拟电梯调度算法,对磁盘进行移臂调度和旋转调度。提示:(1) 磁盘是可供多个进程共享的存储设备,但一个磁盘每个时刻只能为一个进程服务。当有进程在访问
33、某个磁盘时,其它想访问该磁盘的进程必须等待,直到磁盘一次工作结束。当有多个进程提出输入输出请求而处于等待状态时,可用电梯调度算法从若干个等待访问者中选择一个进程,让它访问磁盘。选择访问者的工作由“驱动调度”进程来完成。由于磁盘与处理器是可以并行工作的,所以当磁盘在为一个进程服务时,占有处理器的另一进程可以提出使用磁盘的要求,也就是说,系统能动态地接收新的输入输出请求。为了模拟这种情况,在本实习中设置一个“接收请求”进程。“驱动调度”进程和“接收请求”进程能否占有处理器运行,取决于磁盘的结束中断信号和处理器调度策略。在实习中可用随机数来模拟确定这两个进程的运行顺序,以代替中断处理和处理器调度选择
34、进程的过程。因而,程序的结构可参考图10-1。图10-1 程序结构(2) “接收请求”进程建立一张“请求I/O”表,指出等待访问磁盘的进程要求访问的物理地址,表的格式为:进程名柱面号磁道号物理记录号MMMMMMMM假定某个磁盘组共有200个柱面,由外向里顺序编号(0-199),每个柱面上有20个磁道,编号为0-19,每个磁道分成8个物理记录,编号0-7。进程访问磁盘的物理地址可以用键盘输入的方法模拟得到。图10-2是“接收请求”进程的模拟算法。图10-2 “接收请求”模拟算法在实际的系统中必须把等待访问磁盘的进程排入等待队列,由于本实习模拟驱动调度,为简单起见,在实习中可免去队列管理部分,故设
35、计程序时可不考虑“进程排入等待队列”的工作。(3) “驱动调度”进程的功能是查“请求I/O”表,当有等待访问磁盘的进程时,按电梯调度算法从中选择一个等待访问者,按该进程指定的磁盘物理地址启动磁盘为其服务。对移动臂磁盘来说,驱动调度分移臂调度和旋转调度。电梯调度算法的调度策略是与移动臂的移动方向和移动臂的当前位置有关的,所以每次启动磁盘时都应登记移臂方向和当前位置。电梯调度算法是一种简单而实际上用的驱动调度算法,这种调度策略总是优先选择与当前柱面号相同的访问请求,从这些请求中再选择一个能使旋转距离最短的等待访问者。如果没有与当前柱面号相同的访问请求,则根据移臂方向来选择,每次总是沿臂移动方向选择
36、一个与当前柱面号最近的访问请求,若沿这个方向没有访问请求时,就改变臂的移动方向。这种调度策略能使移动臂的移动频率极小化,从而提高系统效率。用电梯调度算法实现驱动调度的模拟算法如图10-3。(4) 图10-1中的初始化工作包括,初始化“请求I/O”表,置当前移臂方向为里移;置当前位置为0号柱面,0号物理记录。程序运行前可假定“请求I/O”表中已经有若干个进程等待访问磁盘。在模拟实习中,当选中一个进程可以访问磁盘时,并不实际地启动磁盘,而用显示:“请求I/O”表;当前移臂方向;当前柱面号,物理记录号来代替图10-3中的“启动磁盘”这项工作。图10-3 电梯调度模拟算法四、实习报告:(1) 实习题目
37、。(2) 程序中使用的数据结构及其说明。(3) 打印一份源程序并附上注释。(4) 打印驱动调度进程每次选择访问请求的“请求I/O”表以及每次选中的进程名、访问的柱面号、物理记录号和当前移臂方向(用up代表里移,down代表外移)。打印格式为:“请求I/O”表进程名柱面号物理记录号方向五、实验代码:#include #include #include #include #include typedef struct iochar Pro13;int Cylinder;int Track;int Record;io *next;io,*HEAD;HEAD head;int CurrentCylinder=0;/当前柱面号int Direction=1;/方向int last=200; /初始化差值int pronum=0;/调度次数int m=0;int Direction1=0;HEAD Createio()/创建头指针HEAD head=(HEAD)mal