第一篇:操作系统第一次实验报告(大全)
操作 系统 实验报告
实验名称:
线程 控制实验
计算机科学与技术学院
目录
一、实验目的和要求 2 二、实验内容 2 三、实验步骤 2 四、实验结果与分析 3 1.单线程 3 2.单线程(睡眠 4s)3 3.多线程 4 4.多线程(每个子线程睡眠 1s)4 5.单线程与多线程对比 5 五、程序源代码 5 1.单线程实验代码 5 2.单线程实验代码 6 六、实验体会 7
一、实验目的和要求
通过本实验掌握在 Linux 操作系统中遵循 Posix线程标准接口进行多线程程序编程,熟练掌握线程的创建 pthread_create(),线程的终止 pthread_exit(),等待线程合并 pthread_join()等线程控制操作,利用信号量或者互斥锁实现线程建的同步。
二、实验内容
问题:求 1000000 个浮点数(精确到小数点后 4 位)的平均值(和,最大值,最小值),具体的问题描述流程图如下图图 1 所示:
三、实验 步骤
1、随机生成 1000000个浮点数; 2、创建 4个子线程,分别求 250000个浮点数之和; 3、完成 1000000 个浮点数之和并打印结果; 4、统计多线程并发执行完成计算的时间; 5、写一个单线程程序,同样完成 1000000 个随机数求和的计算,统计计算时间,并和前面结果进行对比; 6、让单线程程序睡眠四秒钟、多线程程序各子程序睡一秒的条件下(两个程序总的睡眠时间相同),对比执行结果; 7、分析两次对比结果的差异,写出自己的见解。
四、实验结果与分析 1、单线程完成 1000000 个浮点数的求和运算所用的时间情况如下图图 2 所示:
图 图 2 单线程计算 时间
分析:实验中每次随机产生一个 0 到 1 之间的浮点数,1000000 个这样的数相加的话的平总和大概就在 500000 左右(按照随机数的平均值原理),实验中 sum=,显然结果正确,整个计算运行时间为。
2、单线程完成 1000000 个浮点数的求和运算,单线程中睡眠 4 秒钟,所用的时间情况如下图图3 所示:
图 图 3 单线程计算 时间(睡眠 4 秒)分析:根据上一次单线程的执行情况来看,这一次让单线程睡眠 4 秒钟,最后执行时间刚好就是4 秒加上计算时间。也就是说计算 1000000 个浮点数的总和平均时间约为。
3、四个子线程共同完成 1000000 个浮点数的求和计算所用时间情况如下图图 4所示:
图 图 4 多线程计算时间
分析:因为这次是 4 个子线程并发运行,每个子线程只需计算 250000个浮点数的总和,理想情况下这时候的运行时间应该是这单线程中计算时间的四分之一。从图中可以看到执行时间是,很显然这个时间约为单线程求 1000000 个浮点数之和的时间()的四分之一,符合预期的结果。
4、四个子线程共同完成 1000000 个浮点数的求和计算,其中每个子线程睡眠 1 秒钟,最终所用时间情况如下图图 5所示:
图 图 5 多线程计算时间(每个 子线程眠 睡眠 1 秒)
分析:这里四个子线程每个子线程睡眠一秒,但由于四个子线程并发同步的在执行,当一个子线程在睡眠时,另外一个子线程却仍然在继续求和计算,因此他们一起合作同步完成1000000个浮点数的计算所需的时间就是 1 秒加上上图中不睡眠的时候的计算时间。从图中可以
看到≈1s+,所以最终的结果符合预期值。
5、单线程计算时间(睡眠 4s)与多线程计算时间(每个子线程睡眠 1s)对比效果如下图图 6 所示:
图 图 6 单线程(睡眠 4s)与 与 多线程(每个眠 子线程睡眠 1s)计算时间 对比图 五、程序源代码 /************************* *FileName:
*Author:
*Date:2013/11/22 ***************************/ #include <> #include <> #include <> #include <> #include
int i;
srand(time(NULL));
for(i=0;i { SUM +=(float)(rand()/(float)RAND_MAX); } sleep(4);} int main(){ pthread_t p; int result; float time; struct timeval start; struct timeval end; gettimeofday(&start,NULL); result=pthread_create(&p,NULL,ADD,NULL); if(result!=0) { printf(“Create Thread of ADD Failuren”); exit(-1); } pthread_join(p,NULL); gettimeofday(&end,NULL); time =((float)-*1000000+(float) -)/1000000; printf(“Signal_Thread_Sum:%.4fn”,SUM); printf(“Signal_Thread_Execution_Time:%.4fs(sleep 4 sec)n”,time); return 0;} /************************* *FileName: *Author:wangtao *Date:2013/11/22 ***************************/ #include <> #include <> #include <> #include <> #include int i; srand(time(NULL)); for(i=0;i { pthread_mutex_lock(&mutex); SUM +=(float)((float)rand()/RAND_MAX); pthread_mutex_unlock(&mutex); } printf(“pthread%d:%.4fn”,*k,SUM); sleep(1);} int main(void){ pthread_t p1,p2,p3,p4; int result1,result2,result3,result4; int k1=1,k2=2,k3=3,k4=4; struct timeval start; struct timeval end; float time; gettimeofday(&start,NULL); pthread_mutex_init(&mutex,NULL); result1=pthread_create(&p1,NULL,(void*)ADD,&k1); result2=pthread_create(&p2,NULL,(void*)ADD,&k2); result3=pthread_create(&p3,NULL,(void*)ADD,&k3); result4=pthread_create(&p4,NULL,(void*)ADD,&k4); if(result1!=0||result2!=0||result3!=0||result4!=0) { printf(“Create Child Thread Failure!n”); exit(1); } pthread_join(p1,NULL); pthread_join(p2,NULL); pthread_join(p3,NULL); pthread_join(p4,NULL); gettimeofday(&end,NULL); time =((float)-*1000000 +(float)-)/1000000; printf(“SUM = %.4fn”,SUM); printf(“Multi_thread_time = %.4fs(Each child thread sleep 1 sec)n”,time); return 0;} 六、实验体会 这是第一次使用多线程编程编写代码,第一次直观感受到这种多线程编程对程序的执行速率的影响。虽然说操作系统课程已经上了好几个星期了,课堂上一直在学习多线程编程的算法思想,但是那只是书面上的讲授,真正直观的感受和体会还是得依靠实验来了解。 因为之前就接触过 linux 系统,所以对于程序的编译执行方面还是问题不大,最主要的就是代码的编写问题。一开始到实验室完全不知道要做什么,因为根本连实验内容都不知道,直到助教在大屏幕上显示这个实验题目,我才开始了解实验的题目和要求。这里我就是想建议一下老师您可以应该给我们实验题目,让我们在实验前就了解一下实验内容,不然到了实验室都不知道到底要干嘛。读懂了解题意之后,我就开始参考所给的一些线程创建函数说明来编写多线程同步完成1000000个浮点数的求和运算。因为对这些线程函数不是很了解,在使用 pthread_create()函数创建线程时,老是传入函数参数不对,后来百度之后了解到传入的子线程函数的类型应该为 void *(*start_thread)(void)形式。最后运行试验与单线程的进行比较,强烈感受到多线程的并发同步运行的特点。 总之,这次试验使我对课堂知识有了更深的体会和巩固,为以后的课程学习打下了基础。 许昌学院 《操作系统》实验报告书 学号:姓名:闫金科班级:成绩: 5006140057 14物联网工程 2016年02月实验一 Linux的安装与配置 一、实验目的 1.熟悉Linux系统的基本概念,比如Linux发行版、宏内核、微内核等。2.掌握Linux系统的安装和配置过程,初步掌握Linux系统的启动和退出方法。3.熟悉Linux系统的文件系统结构,了解Linux常用文件夹的作用。 二、实验内容 1.从网络上下载VMware软件和两个不同Linux发行版镜像文件。2.安装VMware虚拟机软件。 3.在VMware中利用第一个镜像文件完成第一个Linux的安装,期间完成网络信息、用户信息、文件系统和硬盘分区等配置。 4.在VMware中利用第二个镜像文件完成第二个Linux的安装,并通过LILO或者GRUB解决两个操作系统选择启动的问题。 5.启动Linux系统,打开文件浏览器查看Linux系统的文件结构,并列举出Linux常用目录的作用。 三、实验过程及结果 1、启动VMware,点击新建Linux虚拟机,如图所示: 2、点击下一步,选择经典型,点击下一步在选择客户机页面选择Linux,版本选择Red Hat Enterprise Linux 5,如图所示: 3、点击下一步创建虚拟机名称以及所要安装的位置,如图所示: 4、点击下一步,磁盘容量填一个合适大小,此处选择默认值大小10GB,如图所示: 5、点击完成,点击编辑虚拟机设置,选择硬件选项中的CD-ROM(IDE...)选项,在右侧连接中选择“使用ISO镜像(I)”选项,点击“浏览”,找到Linux的镜像文件,如图所示: 6点击确定按钮后,点击启动虚拟机按钮,来到Linux的安装界面,如图所示: 7、到此页面之后,等待自动检测安装,如图所示: 8、等到出现如图所示页面后点击“skip”按钮,跳过检测,直接进入安装设置界面,如图所示: 9、安装设计界面如图所示: 10、点击Next按钮进入设置语言界面,设置语言为“简体中文”,如图所示: 11、点击Nest按钮进入系统键盘设置按钮,设置系统键盘为“美国英语式”,如图所示: 12、点击下一步按钮,弹出“安装号码”对话框,选择跳过输入安装号码,如图所示: 13、按照提示,一直点击下一步按钮,如图所示: 14、到设置最后一步,点击下一步按钮进入开始安装Red Hat Enterprise Linux Sever界面,如图所示: 15、安装完成后,进入欢迎界面,按照提示点击前进按钮知道进入Linux桌面,如图所示: 16、安装成功的Linux系统桌面如图所示,桌面包含五个图标,分别为:计算机、jk’s Home、回收站、RHEL/5.3 i386DVD。 四、实验总结 通过安装虚拟机等操作让我认识到Linux这系统一些基本特点,本次试验学会了安装虚拟机并且使用虚拟机安装操作系统,掌握了红帽Linux系统的安装和配置过程,以及对镜像ISO文件的使用,有别于我们机器上使用的系统,通过虚拟机这个软件还可以在已有系统的基础上使用其他操作系统。安装过程中一定要注意选择版本的时候要选择Red Hat Enterprise Linux 5版本,否则安装不能成功。自己动手成功的安装了Linux系统,自己对Linux的学习产生更大的兴趣。 实验二 Linux操作系统的运行模式 一、实验目的 1.熟悉Linux系统终端工作环境的使用,了解Linux命令的格式,使用学会利用常用的Linux命令来完成系统的管理和维护。 2.了解X-Windows的特点,熟悉Linux图形用户接口的使用,掌握GNOME桌面环境的基本操作。 3.了解和掌握在Linux环境下安装软件包的方法,如QQ for Linux等用软件的安装方法。 二、实验内容 1.启动Linux系统打开虚拟终端界面,使用Linux的在线帮助指令man或help获得ls、uname、date、cal、mkdir、cp等Linux命令的帮助手册,了解这些命令的具体使用方法。同时,也可以通过执行“命令名 –help”来显示该命令的帮助信息,如“ls –help”,试用这些命令。 2.通过uname命令的执行,查看并给出相关系统信息:操作系统的名称、系统域名、系统CPU名称等。 3.在主目录下创建一个名为myetc的子目录,将/etc目录下与网络相关的文件和子目录拷贝到该目录,并将这些文件的执行权限设置为可执行。 4.在主目录/home下创建目录program、music 和temp,然后在program下建立目录java和C,列出完成该过程的所有命令。 5.在图形界面环境中,查看GNOME桌面的面板和桌面,设置GNOME,包括屏幕保护程序、更改背景和指定关联程序等。6.实现对光盘的加载和访问,然后卸载。 三、实验过程及结果 1、打开终端,输入 【ls –help】来查看【ls】指令的使用方法,同理查看uname、date、cal、mkdir、cp的使用方法。 2、在终端中输入【uname –a】显示操作系统名系统cpu名和系统域名 3、重启系统,用【root】用户名进入系统,以获得权限。在终端中输入【mkdir myetc】,在主目录下创建【myrtc】的目录,【ls】查看是否创建。输入【cd..】返回至【/】文件,输入【cp –r etc root/myetc】讲etc中内容复制到myetc中,进入myetc文件【ls】查看。输入 【chmod u+x etc】赋予文件可执行的权限,输入【ll】查看。 4、在home下,输入【mkdir {program,music,temp}】,可在home下创立这三个目录,输入【ls】查看。在program下输入【mkdir{java,C}】,可创立java和C两个目录,【ls】查看。 5、在桌面上方选择【系统】-【首选项】,即可设置屏幕保护程序和更改背景和指定关联程序 5、在桌面上可见看到有CD光盘,双击浏览,右键【弹出】即卸载。 四、实验总结和体会 Linux的指令系统是学习Linux操作系统很重要的一部分,指令系统相当于在Windows操作系统下的doc,可以省去图形化界面。通过这次的实验让我了解了Linux的强大功能,了解到Linux有许多方便快捷的设置基本配置的方法,这使我更喜欢上Linux的使用。在使用指令的过程中,有时候对文件的操作需要一定的权限,这时需要在登陆时用户名使用【root】,而不是我们在安装时使用的用户名,这样就获得了管理员权限,可以对一些系统文件进行操作。 实验三 Linux应用软件与系统管理 一、实验目的 1.了解OpenOffice.Org集成办公软件,掌握利用OpenOffice.Org的套件来完成文档和图片的处理。 2.了解Linux网络管理的知识,熟悉Linux网络配置的方法,掌握在Linux环境下配置Web服务器和ftp服务的方法。 二、实验内容 1.配置Linux系统的网络环境,安装FTP和Web服务器,并配置相关的属性,利用FTP实现WINDOWS和Linux之间的数据交换。 2.利用FTP程序上传自己的照片到FTP服务器,利用OpenOffice的文字处理工具OpenOffice Writer制作一份表格形式的个人简历。个人简历中至少包含学号、姓名、性别、专业、照片和学习经历等内容,并保存为网页格式(html格式)。3.将个人简历网页设置为WEB服务器的首页,然后在客户端利用浏览器访问WEB服务器,查看效果。 4.通过读取proc文件系统,获取系统各种信息(如主机名、系统启动时间、运行时间、版本号、所有进程信息、CPU使用率等),并以比较容易的方式显示。 三、实验过程及结果 1.配置网络环境:在(服务.cmd).里面进行以下操作:在服务里选择3按回车 完成后,可在本地连接看到VMware已连接上网络 在虚拟机设置中设置以太网网络连接方式为 网关地址填虚拟机的网管,IP地址设为虚拟机的一个子网: 四、总结: 在linux系统下,make是我们经常用到的编译命令,所以关于make代码和他的操作指令一定要记清楚。所以,熟练掌握了make和makefile工具之后,源码安装软件就变的像windows下安装软件一样简单。 实验四 进程控制与管理 一、实验目的 1.掌握GCC编译器的用法,学会利用GCC编辑器来编辑C语言程序,学会利用GDB调试器来调试C语言程序。 2.理解进程和程序的区别和联系,3.掌握在Linux环境下观察进程运行情况和CPU工作情况的命令。4.了解fork()系统调用,掌握利用fork()创建进程的方法。 5.了解Linux系统其他与进程相关的系统调用,如exec、wait和exit等。6.了解Linux常用的进程通信机制。 二、实验内容 1.利用Linux的进程管理命令ps、top来监视和跟踪进程,体会进程和程序的关系。2.利用Linux的文字编辑器编写文件复制的C语言程序,并用gcc编译该程序,然后运行该程序。 3.编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。试观察记录屏幕上的显示结果,并分析原因。 4.修改上述程序,每一个进程循环显示一句话。子进程显示'daughter „'及'son „„',父进程显示 'parent „„',观察结果,分析原因。5.用fork()创建一个进程,再调用exec()用新的程序替换该子进程的内容。 三、实验过程及结果 1、利用Linux的进程管理命令ps、top来监视和跟踪进程,体会进程和程序的关系。<1>从用户身份切换到ROOT身份 <2>输入命令 ps 查看进程 <2>输入命令 top 跟踪进程 2、利用Linux的文字编辑器编写一个计算机100个自然数和的C语言程序,并用gcc编译该程序,然后运行该程序。 <1>创建一个.C文件 并进入进行编辑 <2>用GCC 进行编译,再查看文件,发现产生执行文件 a.out <3>执行这个可执行文件得到结果5050 1、编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示'a',子进程分别显示字符'b'和字符'c'。试观察记录屏幕上的显示结果,并分析原因。 <1>穿件一个.C文件 并进行编写程序代码 <2>反复执行2次该程序 <3>可以看出两次执行的结果 a b c 出现的顺序不同,原因是,3个进程的输出次序是随机的,并不会按规定的顺序出现,所以会出现上述结果。 4、修改上述程序,每一个进程循环显示一句话。子进程显示'daughter „'及'son „„',父进程显示 'parent „„',观察结果,分析原因。<1>重新修改代码 <3>执行这段程序 <4>原分析: 因和之前一样,可以看出执行的结果 3个单词出现的顺序不同,原因是,3个进程的输出次序是随机的,并不会按规定的顺序出现,所以会出现上述结果。 5、用fork()创建一个进程,再调用exec()用新的程序替换该子进程的内容。<1> 编写代码 <2> 执行的结果 结果表明 execl 替代了son的内容 四、实验总结和体会 这个实验考察的是进程之间存在很多可能性以及对编辑器的使用。本次实验学习了在linux环境下用gcc编译器运行c语言程序,在linux环境下编写程序用到了vi编辑器,知道了该编辑器也需要各种命令来操作。编写C语言程序时用到了fork()函数,再调用execl()用新的程序替换该子进程的内容。 实验五 进程调度模拟程序的设计与实现 一、实验目的 1.了解进程调度的概念,掌握常用进程调度算法的原理。2.掌握Linux程序设计编辑、编译和调试的技巧。 二、实验内容 1.编写程序实现进程调度调度算法先来先服务、优先级高优先和时间片轮转调度算法。(编程语言不限) 2.输入数据,输出运行结果。 三、实验过程及结果 1先来先服务 #i nclude struct { int id; float ArriveTime;float RequestTime;float StartTime;float EndTime;float RunTime;float DQRunTime;int Status;}arrayTask[4];GetTask(){ int i;float a; for(i=0;i<4;i++){arrayTask[i].id=i+1;printf(“input the number”); printf(“input the the ArriveTime of arrayTask[%d]:”,i);scanf(“%f”,&a); arrayTask[i].ArriveTime=a; printf(“input the RequestTime of arrayTask[%d]:”,i);scanf(“%f”,&a); arrayTask[i].RequestTime=a;arrayTask[i].StartTime=0;arrayTask[i].EndTime=0;arrayTask[i].RunTime=0;arrayTask[i].Status=0; } } int fcfs() { int i,j,w=0; for(i=0;i<4;i++) { if(arrayTask[i].Status==0) { t=arrayTask[i].ArriveTime; w=1; } if(w==1) break; } for(i=0;i<4;i++) { if(arrayTask[i].ArriveTime t=arrayTask[i].ArriveTime; } for(i=0;i<4;i++) { if(arrayTask[i].ArriveTime==t) return i; } } int sjf(){ int i,x=0,a=0,b=0;float g; for(i=0;i<4;i++){ if(arrayTask[i].Status==1){g=arrayTask[i].EndTime;x=1;} } if(x==0){ t=arrayTask[0].ArriveTime; for(i=0;i<4;i++){ if(arrayTask[i].ArriveTime t=arrayTask[i].ArriveTime;a=i;} } return a;} else { for(i=0;i<4;i++){ if(arrayTask[i].EndTime>g)g=arrayTask[i].EndTime;} for(i=0;i<4;i++){ if(arrayTask[i].Status==0&& arrayTask[i].ArriveTime<=g){ t=arrayTask[i].RequestTime;a=i;b=1;} /*判断有没有进程在前个进程完成前到达*/ } if(b!=0)/*有进程到达则按SJF*/ { for(i=0;i<4;i++){ if(arrayTask[i].Status==0&&arrayTask[i].ArriveTime<=g&&arrayTask[i].RequestTime return a;} else{ /*否则按FCFS*/ for(i=0;i<4;i++) {if(arrayTask[i].Status==0)t=arrayTask[i].ArriveTime;} for(i=0;i<4;i++){ if(arrayTask[i].Status==0&&arrayTask[i].ArriveTime return a;} } } new(int s)/*定义执行进程后相关数据的修改*/ { int i,g=0;for(i=0;i<4;i++){ if(arrayTask[i].Status==0)continue;else { g=1;break;} } if(g==0)/*当处理的是第一个未执行的进程时执行*/ { arrayTask[s].StartTime=arrayTask[s].ArriveTime; arrayTask[s].EndTime=arrayTask[s].RequestTime+arrayTask[s].ArriveTime;arrayTask[s].RunTime=arrayTask[s].RequestTime;arrayTask[s].Status=1;g=2;} if(g==1)/*当处理的不是第一个未执行的进程时执行*/ { arrayTask[s].Status=1;for(i=0;i<4;i++){ if(arrayTask[i].Status==1)d=arrayTask[i].EndTime;} for(i=0;i<4;i++)/*查找最后执行的进程的完成时间*/ { if(arrayTask[i].EndTime>d&&arrayTask[i].Status==1)d=arrayTask[i].EndTime;} if(arrayTask[s].ArriveTime arrayTask[s].StartTime=arrayTask[s].ArriveTime; arrayTask[s].EndTime=arrayTask[s].StartTime+arrayTask[s].RequestTime;arrayTask[s].RunTime=arrayTask[s].EndTime-arrayTask[s].ArriveTime;} arrayTask[s].DQRunTime=arrayTask[s].RunTime/arrayTask[s].RequestTime;} Printresult(int j)/*定义打印函数*/ { printf(“%dt”,arrayTask[j].id); printf(“%5.2ft”,arrayTask[j].ArriveTime);printf(“%5.2ft”,arrayTask[j].RequestTime);printf(“%5.2ft”,arrayTask[j].StartTime);printf(“%5.2ft”,arrayTask[j].EndTime);printf(“%5.2ft”,arrayTask[j].RunTime);printf(“%5.2fn”,arrayTask[j].DQRunTime);} main(){ int i,b,k,a,c=0;int d[4];clrscr(); printf(“t F.FCFS n”);printf(“t S.SFJ n”);printf(“t Q.EXIT n”);for(i=0;;i++){ if(c)break; printf(“please input the number a:n”);scanf(“%d”,&a);switch(a){ case Q: c=1;break; case F:printf(“please input the different-ArriveTime of arrayTasksn”);GetTask(); printf(“*****************************the result of fcfsn”);printf(“NumbertArrivetServertStarttFinishtTurnovetTake power turnover timen”); for(b=0;b<4;b++)/*调用两个函数改变结构体数的值*/ { k=fcfs();d[b]=k;new(k);} for(b=0;b<4;b++) Printresult(d[b]);/*调用打印函数打出结果*/ continue; case S: printf(“please input the different-RequestTime of array Tasksn”);GetTask(); printf(“******************************the result of sjfn”);printf(“NumbertArrivetRequesttStarttEndtRuntDQRun timen”);for(b=0;b<4;b++){ k=sjf();d[b]=k;new(k);} for(b=0;b<4;b++)Printresult(d[b]);continue; default:printf(“the number Error.please input another number!n”);} } } 四、实验总结和体会 通过做本实验,让我对进程或作业先来先服务、高优先权、按时间片轮转调度算法以及进程调度的概念和算法,有了更深入的认识!理解进程的状态及变化,动态显示每个进程的当前状态及进程的调度情况。进程调度是处理机管理的核心内容。优先级高优先是根据作业的优先级,总是选择优先级最高者进入队列。轮转调度算法是调度程序每次把CPU分配给就绪队列首进程/线程使用规定的时间间隔,就绪队列中都路保留巡行一个时间片。 实验二 进程调度 1.目的和要求 通过这次实验,理解进程调度的过程,进一步掌握进程状态的转变、进程调度的策略,进一步体会多道程序并发执行的特点,并分析具体的调度算法的特点,掌握对系统性能的评价方法。 2.实验内容 阅读教材《计算机操作系统》第二章和第三章,掌握进程管理及调度相关概念和原理。 编写程序模拟实现进程的轮转法调度过程,模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。假设初始状态为:有n个进程处于就绪状态,有m个进程处于阻塞状态。采用轮转法进程调度算法进行调度(调度过程中,假设处于执行状态的进程不会阻塞),且每过t个时间片系统释放资源,唤醒处于阻塞队列队首的进程。 程序要求如下: 1)输出系统中进程的调度次序; 2)计算CPU利用率。 3.实验环境 Windows操作系统、VC++6.0 C语言 4设计思想: (1) 程序中进程可用PCB表示,其类型描述如下: struct PCB_type { int pid; //进程名 int state; //进程状态 2——表示“执行”状态 1——表示“就绪”状态 0——表示“阻塞”状态 int cpu_time;//运行需要的CPU时间(需运行的时间片个数) } 用PCB来模拟进程; (2)设置两个队列,将处于“就绪”状态的进程PCB挂在队列ready中;将处于“阻塞”状态的进程PCB挂在队列blocked中。队列类型描述如下: struct QueueNode{ struct PCB_type PCB; Struct QueueNode *next;} 并设全程量: struct QueueNode *ready_head=NULL,//ready队列队首指针 *ready_tail=NULL , //ready队列队尾指针 *blocked_head=NULL,//blocked队列队首指针 *blocked_tail=NULL;//blocked队列队尾指针(3)设计子程序: start_state(); 读入假设的数据,设置系统初始状态,即初始化就绪队列和阻塞队列。 dispath(); 模拟调度,当就绪队列的队首进程运行一个时间片后,放到就绪队列末尾,每次都是队首进程进行调度,一个进程运行结束就从就绪队列中删除,当到t个时间片后,唤醒阻塞队列队首进程。 calculate(); 就绪进程运行一次,usecpu加1,当就绪队列为空时unusecpu加1,CPU利用率为use_cpu/(use_cpu+unuse_cpu)。 5源代码: #include struct PCB_type { int pid; //进程名 int state; //进程状态 //2--表示“执行”状态 //1--表示“就绪”状态 //0--表示“阻塞”状态 int cpu_time;//运行需要的CPU时间(需运行的时间片个数)};struct QueueNode{ struct PCB_type PCB; struct QueueNode *next;};struct QueueNode *ready_head=NULL,//ready队列队首指针 *ready_tail=NULL,//ready队列队尾指针 *block_head=NULL,//blocked队列队首指针 *block_tail=NULL; //blocked队列队尾指针 int use_cpu,unuse_cpu; void start_state()//读入假设的数据,设置系统初始状态 { int n,m; int i; struct QueueNode *p,*q; printf(“输入就绪节点个数n:”); scanf(“%d”,&n); printf(“输入阻塞节点个数m:”); scanf(“%d”,&m); p=(struct QueueNode *)malloc(sizeof(struct QueueNode)); p->next =NULL; ready_head=ready_tail=p; for(i=0;i { p=(struct QueueNode *)malloc(sizeof(struct QueueNode)); p->next =NULL; p->PCB.state=1; printf(“输入就绪进程%d的pid和cpu_time:”,i+1); scanf(“%d%d”,&p->PCB.pid,&p->PCB.cpu_time); ready_tail->next=p; ready_tail=p; } q=(struct QueueNode *)malloc(sizeof(struct QueueNode)); q->next =NULL; block_head=block_tail=q; for(i=0;i { q=(struct QueueNode *)malloc(sizeof(struct QueueNode)); q->next=NULL; q->PCB.state=0; printf(“输入阻塞进程%d的pid和cpu_time:”,i+1); scanf(“%d%d”,&q->PCB.pid,&q->PCB.cpu_time); block_tail->next=q; block_tail=q; } printf(“n处于就绪状态的进程有:n”); p=ready_head->next; i=1; while(p) {printf(“进程%d的pid和cpu_time:%5d%5d%5dn“,i,p->PCB.pid,p->PCB.state,p->PCB.cpu_time); p=p->next; i++; } } void dispath() //模拟调度 { int x=0,t; use_cpu=0; unuse_cpu=0; printf(”输入t:“); scanf(”%d“,&t); printf(”开始调度n“); while(ready_head!=ready_tail||block_head!=block_tail) { struct QueueNode *p,*q; if(ready_head!=ready_tail) { p=ready_head->next; ready_head->next=p->next; p->next=NULL; if(ready_head->next==NULL) { ready_tail=ready_head; } p->PCB.state=2; printf(”进程%d调度t“,p->PCB.pid); state和 use_cpu++; x++; p->PCB.cpu_time--; if(p->PCB.cpu_time) { ready_tail->next=p; ready_tail=p; } else { printf(”进程%d完成t“,p->PCB.pid); free(p); } } else { unuse_cpu++; x++; printf(”空闲一个时间片t“); } if(x==t&&block_head!=block_tail) { q=block_head->next; block_head->next=q->next; q->next=NULL; if(block_head->next==NULL) { block_tail=block_head; } ready_tail->next=q; ready_tail=q; x=0; } } } void calculate() //计算CPU利用率 { printf(”ncpu的利用率%.2fn“,(float)use_cpu/(use_cpu+unuse_cpu)); } void main(){start_state(); dispath(); calculate();} 6运行结果: 7实验总结: 实验帮我复习了数据结构和C语言,且巩固课本知识,知道了如何定义结构体,如何在链接队列中增删节点。模拟进程调度帮我们巩固了进程三状态之间的变迁。懂得调式的重要性。总之,我们明白了理论联系实际。多看书,多上机。 实验三 可变分区存储管理 1.目的和要求 通过这次实验,加深对内存管理的认识,进一步掌握内存的分配、回收算法的思想。 2.实验内容 阅读教材《计算机操作系统》第四章,掌握存储器管理相关概念和原理。编写程序模拟实现内存的动态分区法存储管理。内存空闲区使用自由链管理,采用最坏适应算法从自由链中寻找空闲区进行分配,内存回收时假定不做与相邻空闲区的合并。 假定系统的内存共640K,初始状态为操作系统本身占用64K。在t1时间之后,有作业A、B、C、D分别请求8K、16K、64K、124K的内存空间;在t2时间之后,作业C完成;在t3时间之后,作业E请求50K的内存空间;在t4时间之后,作业D完成。要求编程序分别输出t1、t2、t3、t4时刻内存的空闲区的状态。 3.实验环境 Windows操作系统、VC++6.0 C语言 4.设计思想 模拟内存分配和回收,要设置两个链队列,一个空闲区链和一个占用区链,空闲区链节点有起始地址,大小和指向下一节点的指针等数据域,占用区链节点有起始地址,大小,作业名和指向下一节点的指针等数据域,本实验用最坏适应算法,每次作业申请内存都是从空闲链队头节点分配,如果相等,就删除空闲头结点,如果小于申请的,就不分配,否则就划分内存给作业,剩下的内存大小,重新插入空闲链队,按从大到小,接着把作业占用的内存放到占用区链节点的末尾。每次作业运行完,就要回收其占用的内存大小,把作业节点按从大到小插入到空闲链队中。5.源代码: #include struct freelinkNode *next;};struct busylinkNode{ char name; int len;int address;struct busylinkNode *next;};struct freelinkNode *free_head=NULL; //自由链队列(带头结点)队首指针 struct busylinkNode *busy_head=NULL; //占用区队列队(带头结点)首指针 struct busylinkNode *busy_tail=NULL; //占用区队列队尾指针 void start(void)/* 设置系统初始状态*/ { struct freelinkNode *p; struct busylinkNode *q; free_head=(struct freelinkNode*)malloc(sizeof(struct freelinkNode)); free_head->next=NULL;// 创建自由链头结点 busy_head=busy_tail=(struct busylinkNode*)malloc(sizeof(struct busylinkNode)); busy_head->next=NULL;// 创建占用链头结点 p=(struct freelinkNode *)malloc(sizeof(struct freelinkNode)); p->address=64; p->len=640-64;//OS占用了64K p->next=NULL; free_head->next=p; q=(struct busylinkNode *)malloc(sizeof(struct busylinkNode)); q->name='S';/* S表示操作系统占用 */ q->len=64;q->address=0;q->next=NULL; busy_head->next=q;busy_tail=q;} void requireMemo(char name, int require)/*模拟内存分配*/ { freelinkNode *w,*u,*v;busylinkNode *p;if(free_head->next->len>=require){ p=(struct busylinkNode*)malloc(sizeof(struct busylinkNode)); p->name=name; p->address=free_head->next->address; p->len=require; p->next=NULL; busy_tail->next=p; busy_tail=p;} else printf(”Can't allocate“); w=free_head->next; free_head->next=w->next; if(w->len==require) { free(w);} else { w->address=w->address+require; w->len=w->len-require;} u=free_head; v=free_head->next; while((v!=NULL)&&(v->len>w->len)){ u=v; v=v->next;} u->next=w; w->next=v;} void freeMemo(char name)/* 模拟内存回收*/ { int len; int address;busylinkNode *q,*p;freelinkNode *w,*u,*v;q=busy_head; p=busy_head->next; while((p!=NULL)&&(p->name!=name)) { q=p; p=p->next;} if(p==NULL){ printf(”%c is not exist“,name);} else { if(p==busy_tail) { busy_tail=q; } else { q->next=p->next; len=p->len; address=p->address; free(p); w=(struct freelinkNode*)malloc(sizeof(struct freelinkNode)); w->len=len; w->address=address; u=free_head; v=free_head->next; while((v!=NULL)&&(v->len>len)) { u=v;v=v->next; } u->next=w; w->next=v; } } } void past(int time)/* 模拟系统过了time 时间*/ { printf(”过了时间%d后:n“,time);} void printlink()/* 输出内存空闲情况(自由链的结点)*/ { freelinkNode *p; printf(”内存的空闲情况为:n“); p=(struct freelinkNode *)malloc(sizeof(struct freelinkNode)); p=free_head->next; while(p!=NULL) { printf(”内存的起始地址和内存的大小%5dt%5d:n",p->address,p->len); p=p->next; } } void main(){ int t1=1,t2=2,t3=3,t4=4; start(); past(t1); requireMemo('A',8); requireMemo('B',16); requireMemo('C',64); requireMemo('D',124); printlink(); past(t2); freeMemo('C'); printlink(); past(t3); requireMemo('E',50); printlink(); past(t4); freeMemo('D'); printlink();} 6.运行结果: 7.实验总结: 巩固编程能力,和调式能力,复习课本知识,明白理论联系实际的重要性,动手能力非常重要,多看书,多独立思考,品味痛苦的过程,享受成功的喜悦。 操作系统实验报告 院系:数计学院 班级:大类6班 学号:100511624 姓名:明章辉 指导教师:徐军利 实验报告一 一、实验目的 通过本实验,掌握Linux的基本操作以及Linux的文本编辑,对Linux有一个基本的了解。 二、实验任务 1、Linux的基本操作 1)在图形交互方式下实现对用户、用户组和文件的管理。要求使用图形交互界面添加一个用户“mary”(密码1234)和一个用户组“dancer”,并将用户Mary添加到dancer组中,最后在Mary目录下建立一个名为test1的文件。 2)在命令方式下实现对用户、用户组和文件的管理。要求在命令交互方式下完成添加一个用户(以自己的名字命名),并以此用户名登录。3)用Vi编辑器建立一个名为test2的文件,并输入指定内容。 2、掌握Vi文本编辑器的使用 使用Vi编辑器建立、编辑、显示以及加工处理文本文件。1)进入和退出vi。 2)利用文本插入方式建立一个文件test2。输入以下内容: To the only woman that I love, For many years you have been my wife We've been through much together I love you dearly with my life and could not have picked much better.3)在新建的文本文件上移动光标。 4)对文本文件执行删除、复原、修改等操作。 三、实验设备 VMware虚拟机下的Linux操作系统 四、实验步骤 1、Linux的基本操作 第一步:添加用户: 点击“草帽”图标->“系统设置”->“用户和组群”,出现“用户管理器”界面,单击“添加用户”按钮,在弹出的“创建新用户”界面中创建用户,用户名为“mary”密码为“123456” 第二步:添加用户组: 单击“添加组群”按钮,在弹出的“创建新组群”对话框中新建组,组名为“dancer” 第三步:将用户添加到组: 选中“mary”,点击“属性”按钮或者是双击,选择“组群”,然后将该用户加入“dancer”中,单击“确定”按钮即可。 第四步:在图形界面下创建和编辑文件 单击草帽图标,选择附件中的文本编辑器。命名为“test1”,保存在“mary”所在的文件夹里 2、在命令方式下实现对用户、用户组和文件的管理。第一步:进入命令行界面 桌面上单击鼠标右键,选择“新建终端”,出现终端窗口和命令行提示符# 第二步:添加用户,使用Useradd命令,格式为:useraddwangshumin 第三步:修改密码,使用passwd命令,格式为:passwdwangshumin 第四步:注销账号,以新建的用户名登陆 实验截图如下: 3、Vi编辑器的使用 第一步、在命令行界面系统提示符下输入命令:vi test2,然后按〈Enter〉,建立新文件test2,并进入文件test2的文本编辑状态 第二步、命令方式下用i命令,输入所要求输入的文本内容 第三步、在vi编辑器下练习删除、浏览、复原等操作 第四步使用more命令查看文件内容,格式为:more test2 实验截图如下: 五、实验问题及解决方法 1、在添加用户时,密码输入四位提示错误,输入六位以上即可 2、新建用户名时组名错误,想删除却删除不了,重命名之后提示用户已存在,暂时还没解决 3、由于不是很熟悉操作,发生了很多不必要的小错误,经摸索了解了许多。 六、实验心得体会 通过此次试验,由刚开始对实验的不了解到基本了解了实验内容,刚开始不熟悉操作,中途闹出很多笑话,通过组员间的相互帮助,问题很快便迎刃而解,进一步理解了合作的重要性。同时也对linux系统产生了兴趣,掌握到双系统的相关知识。另外,针对这个专业,多动手多实践才是最重要,这一次实验下来收获颇多,也认识到自身所存在的不足,今后会多一份努力,多一份实践。 Linux实验报告一 一、实验步骤及内容 1.虚拟机软件的安装 (1)先准备虚拟机安装包。 (2)更改安装路径: “D: VMwareVMware Workstationvmware.exe” (3)输入序列号:ctrl+v,在安装过程中不能进行复制剪切操作。 (4)不能重新启动,才能继续安装汉化版D: vmwarevmware workstation 2.新建一个虚拟机并进行配置 (1)单击新建虚拟机虚拟机的类型选择:典型安装 选择客户端操作系统 :linux虚拟机的名字及位置根据需要网络类型选择:,桥接。指定的磁盘容量删除软驱:双击 floppy—remove虚拟内存设置:双击memory—1024MB设置linux的安装文件:选择安装镜像文件—指定第一个安装文件—就可以啦!之后会提示安装第二个安装文件 就进行选择第二个 中间鼠标切换用CTRL+ALT。 3.安装LINUX操作系统 (1)要确定鼠标是否在虚拟机的激活状态下:敲回车不需要检测安装文件选择 skip进入linux的安装前的配置选项:选择安装的语言—中文简体键盘:--默认鼠标:--默认安装类型:--workstation磁盘分区:--自动分区引导程序:默认网络配置:默认防火墙:无防火墙支持的语言:中文时区:亚洲-上海密码:root123456安装的软件包:全部。 二 .在已有虚拟机软件的基础上安装LINUX的技巧。 (1)新建虚拟机—典型安装—linux ,red hat linux---给虚拟机命名,并且指定安装位置d:red hat linux---桥接---10G。 (2)在刚才建立的虚拟机上安装linux系统.(3)配置要安装的linux系统的安装文件iso镜像文件 (4)选择配置好linux镜像文件刚才建立的虚拟机,启动虚拟机,开始安装。 三 .实验总结 充分了解linux系统的安装,学会新建虚拟机,在虚拟机上安装linux系统.和一些简单的技巧并对此门课程有了一定的兴趣。第二篇:操作系统实验报告
第三篇:操作系统实验报告
第四篇:操作系统实验报告一
第五篇:linux操作系统实验报告