版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
目录27544_WPSOffice_Level1一、实验一Windows进程管理 113505_WPSOffice_Level1·实验目的、实验内容 15203_WPSOffice_Level1·实验结果与分析 35438_WPSOffice_Level1·小结与心得体会 41845_WPSOffice_Level1二、实验二Linux进程管理 512661_WPSOffice_Level1·实验目的、实验内容 528700_WPSOffice_Level1·实验结果与分析 715196_WPSOffice_Level1·小结与心得体会 817839_WPSOffice_Level1三、实验三Linux进程间通信 97535_WPSOffice_Level1·实验目的、实验内容 126452_WPSOffice_Level1·实验结果与分析 1118781_WPSOffice_Level1·小结与心得体会 1119424_WPSOffice_Level1四、实验四Windows的互斥与同步 126319_WPSOffice_Level1·实验目的、实验内容 1227420_WPSOffice_Level1·实验结果与分析 1410113_WPSOffice_Level1·小结与心得体会 155754_WPSOffice_Level1五、实验六银行家算法的模拟与实现 1625993_WPSOffice_Level1·实验目的 1619230_WPSOffice_Level1·总体设计 1628167_WPSOffice_Level1·详细设计 1726240_WPSOffice_Level1·实验结果与分析 181257_WPSOffice_Level1·小结与心得体会 1920449_WPSOffice_Level1六、实验八磁盘调度算法的模拟与实现 20843_WPSOffice_Level1·实验目的 2022348_WPSOffice_Level1·总体设计 2020226_WPSOffice_Level1·详细设计 214450_WPSOffice_Level1·实验结果与分析 2232680_WPSOffice_Level1·小结与心得体会 2316088_WPSOffice_Level1七、实验九*基于信号量机制的并发程序设计 249396_WPSOffice_Level1·实验目的 241166_WPSOffice_Level1·总体设计 2432164_WPSOffice_Level1·详细设计 248610_WPSOffice_Level1·实验结果与分析 2715442_WPSOffice_Level1·小结与心得体会 2731481_WPSOffice_Level1八、实验十*简单shell命令行解释器的设计与实现 2827347_WPSOffice_Level1·实验目的 2820483_WPSOffice_Level1·总体设计 286567_WPSOffice_Level1·详细设计 2819154_WPSOffice_Level1·实验结果与分析 3024569_WPSOffice_Level1·小结与心得体会 31九、课程设计报告日志 32实验题目实验一、Windows进程管理实验目的学会使用VC编写基本的Win32ConsolApplication控制台应用程序)。通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解Windows进程的“一生”。通过阅读和分析实验程序,学习创建进程、观察进程、终止进程以及父子进程同步的基本程序设计方法。实验内容1.背景知识:Windows所创建的每个进程都从调用CreateProcess()API函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。每一进程都以调用ExitProcess()或TerminateProcess()API函数终止。通常应用程序的框架负责调用ExitProcess()函数。对于C++运行库来说,这一调用发生在应用程序的main()函数返回之后。模块介绍:主函数模块、创建子进程、startClone()模块、互斥信号量的创建与释放实验步骤:编写基本的Win32ConsolApplication创建进程进行父子进程的简单通信及终止进程数据结构数组以及函数的调用父子进程参数的传递父子进程利用互斥信号进行同步互斥体的创建、获得、检测与释放、API接口子进程的创建与关闭程序流程图:关键代码//清单1-2创建子进程//创建传递过来的进程的克隆过程并赋于其ID值voidStartClone(intnCloneID){//提取用于当前可执行文件的文件名TCHARszFilename[MAX_PATH];GetModuleFileName(NULL,szFilename,MAX_PATH);//格式化用于子进程的命令行并通知其EXE文件名和克隆IDTCHARszCmdLine[MAX_PATH]; sprintf(szCmdLine,"\"%s\"%d",szFilename,nCloneID); //用于子进程的STARTUPINFO结构STARTUPINFOsi;ZeroMemory(&si,sizeof(si));si.cb=sizeof(si); //必须是本结构的大小//返回的用于子进程的进程信息PROCESS_INFORMATIONpi;//利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质BOOLbCreateOK=::CreateProcess(szFilename, //产生这个EXE的应用程序的名称szCmdLine, //告诉其行为像一个子进程的标志NULL, //缺省的进程安全性NULL, //缺省的线程安全性FALSE, //不继承句柄CREATE_NEW_CONSOLE, //使用新的控制台NULL, //新的环境NULL, //当前目录&si, //启动信息&pi); //返回的进程信息//对子进程释放引用if(bCreateOK){CloseHandle(pi.hProcess);CloseHandle(pi.hThread);}}实验结果与分析实验1-1结果分析:其中出现的问题就是要将void改成int,然后加上return0,从main()函数开始,程序将会运行输出Hello,Win32ConsolApplication。问题:如果运行不成功,则可能的原因是什么?答:原因可能是编译器的不同导致兼容性不同,编译出错;还有就是创建项目出错,不对应无法运行。实验1-2结果分析:从main()函数开始,首先判断argc的值(argc初始值默认为1)因为argc不满足大于1,所以不能将argv[1]赋值给nClone;然后nClone<c_nCloneMax,则调用StartClone(++nClone)函数,创建子进程;创建子进程后,argc的值变为2,然后将自增的nClone赋值argv[1],然后将继续执行main()函数,直到(nClone>c_nCloneMax),跳出,结束创建新进程。最初结果与第一次修改结果相同:(出现六个进程)第二次修改结果:(无限产生进程)问题:从中你可以得出什么结论?说明nClone的作用。变量的定义和初始化方法(位置)对程序的执行结果有影响吗?为什么?答:在控制程序执行过程,当nClone>5时跳出循环,创建子进程结束;但是当变量赋值的位置不同的时候对于执行结果有影响,在第二次更改中,由于nClone每次都初始化为0,会陷入死循环,不断创建子进程。实验1-3结果分析:从main()函数开始,首先判断argc的值(argc初始值默认为1),决定进行父进程还是子进程,因为argc不满足大于1,所以调用parent()函数,在执行parent()函数过程中调用StartClone();然后通过sprintf(szCmdLine,"\"%s\"child",szFilename)将argv[1]赋值child后面满足条件后调用child()函数;由于设置了互斥信号,则只允许一个进程进行,所以只有当父进程释放互斥信号hMutexSuicide时,子进程检测获得才结束进程。最初结果和修改之后的结果:问题:参考MSDN中的帮助文件CreateMutex()、OpenMutex()、ReleaseMutex()和WaitForSingleObject()的使用方法,理解父子进程如何利用互斥体进行同步的。给出父子进程同步过程的一个大概描述。答:CreateMutex()创建互斥体hMutexSuicide信号、OpenMutex()打开互斥体、ReleaseMutex()释放互斥体、WaitForSingleObject()检测Hhandle信号状态,通过这些只允许有一个状态被创建或者使用也就是信号量唯一,实现进程的同步。小结与心得体会通过这个实验让我更加深入了解了熟悉操作系统的进程这方面的概念,也更加清楚了操作系统进程在各种时期的相关操作与设计,也让我更加对于操作系统这一学科产生了更加浓厚的兴趣。所有进程都是以调用CreateProcess()API函数开始的是ExitProcess()函数结束的,在获得互斥体时,首先,想要访问调用的线程可使用OpenMutex()API来获得指向对象的句柄;然后,线程将这个句柄提供给一个等待函数。当内核将互斥体对象发送给等待线程时,就表明该线程获得了互斥体的拥有权。当线程获得拥有权时,线程控制了对共享资源的访问——必须设法尽快地放弃互斥体。放弃共享资源时需要在该对象上调用ReleaseMute()API。然后系统负责将互斥体拥有权传递给下一个等待着的线程(由到达时间决定顺序)。还有就是,Windows提供的常用对象可分成三类:核心应用服务、线程同步和线程间通讯。其中,开发人员要可以使用线程同步对象来协调线程和进程的工作,以使其共享信息并执行任务。实验题目实验二、Linux进程管理实验目的通过进程的创建、撤销和运行加深对进程概念和进程并发执行的理解,明确进程和程序之间的区别。实验内容背景知识fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:在父进程中,fork返回新创建子进程的进程ID;在子进程中,fork返回0;如果出现错误,fork返回一个负值;在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。模块介绍2-1:一个父进程,一个子进程2-2:一个父进程,一个子进程实验步骤创建进程创建子进程执行新任务数据结构数据结构为链表结构,C++语言编写,运用了C++库函数。个进程会派生多个子进程时,子进程与子进程具有兄弟关系。程序流程图关键代码//清单2-2子进程执行新任务intmain(){pid_tpid;/*forkachildprocess*/pid=fork(); if(pid<0) {/*erroroccurred*/ fprintf(stderr,"ForkFailed");return1;}elseif(pid==0){/*子进程*/ execlp("/bin/ls","ls",NULL);}else{/*父进程将一直等待,直到子进程运行完毕*/wait(NULL);printf("ChildComplete");}return0;}实验结果与分析实验2-1结果分析:从main()函数开始,运行父进程,接着通过判断是否创建成功,while((x=fork())==-1)进行判断,如果x>0,则继续创建子进程,若成功,则此时有一个子进程和一个父进程,先创建的子进程会输出a,接下来是父进程执行完毕,输出b,后面是进程执行完毕输出c;fork出来的进程不能确定子进程和父进程谁先执行,是随机的,所以每次执行的结果可能会不一样的,父进程与子进程争夺CPU资源。所以最终的输出结果是acbc或者是bcac。问题:观察屏幕上的显示结果,并分析多次运行为什么会出现不同的结果。答:fork出来的进程不能确定子进程和父进程谁先执行,是随机的,所以每次执行的结果可能会不一样的,父进程与子进程争夺CPU资源。实验2-2结果分析:从main()函数开始,父进程创建子进程,首先判断子进程是否创建成功,如果pid<0则创建进程失败,当pid=0时,运行子进程,输出系统当前目录。父进程将会一直等待子进程信号,只有当子进程释放信号,父进程输出“ChildComplete”。问题:观察该程序在屏幕上的显示结果,并分析实验结果。答:分析:屏幕上出现的是当前目录的列表,以及子进程结束打印输出的子进程complete,首先该程序创建一个子进程然后,但是fork()是一次调用返回两个参数,在父进程中返回的是创建子进程的ID,在子进程中返回的是0,故会同时出现一起存在的结果小结与心得体会本实验在实验一的基础上将创建进程实验到了Linux系统上,实验是有两个块组成,创建进程和子进程执行新任务构成,本实验最重要的一个函数就是fork()函数,就是在fork的时候调用一次,返回两个参数,这也是对于这个实验的基本理解,在Linux中利用fork建立一个子进程,父进程继续运行,子进程在同样的位置执行同样的程序。对于子进程,fork()返回0,出错时返回-1,对于父进程,fork()返回子进程的pid,while((x=fork())==-1)这句话是用来判断子进程是否能创建成功,而且当x=0时运行子进程,当x>0时父进程执行,而x<0时,则进程创建不成功,通过代码输出相应的字符去确定父子进程的先后执行顺序,也同时可以发现子父进程会争夺cpu资源形成两中不同的结果,说明进程的执行是随机的关键看是否获得资源。通过本实验初步认识了Linux系统下如何创建进程以及进程是如何执行的,以及对于fork函数的深刻理解,也让我感受到了Linux系统的简约,原始点但也能说是有趣,发现这个开源的系统比想象的要更加有趣,以及在现在主流的操作系统中我也认为它能很好的完成各种功能的实现,只不过相对比较麻烦一点罢了,但是对于程序员来说这样才能更加深入的了解底层的原理才能更好的提升自己的能力。实验题目实验三、Linux进程间通信实验目的Linux系统的进程通信机构(IPC)允许在任意进程间大批量地交换数据,通过本实验,理解熟悉Linux支持的消息通信机制。实验内容背景知识UINX/Linux系统把信号量、消息队列和共享资源统称为进程间通信资源(IPCresource)。提供给用户的IPC资源是通过一组系统调用实现的。这组系统调用为用户态进程提供了以下三种服务:用信号量对进程要访问的临界资源进行保护。用消息队列在进程间以异步方式发送消息。用一块预留出的内存区域供进程之间交换数据。在Linux中创建子进程要使用fork()函数,执行新的命令要使用exec()系列函数,等待子进程结束使用wait()函数,结束终止进程使用exit()函数。fork()原型如下:pid_tfork(void);fork建立一个子进程,父进程继续运行,子进程在同样的位置执行同样的程序。对于父进程,fork()返回子进程的pid,对于子进程,fork()返回0。出错时返回-1。模块介绍主函数、SERVER函数、CLIENT函数实验步骤用一个程序作为“引子”,先后fork()两个子进程SERVER和CLIENT,进行通信。SERVER端建立一个key为75的消息队列,等待其他进程发来的消息。当遇到类型为1的消息,则作为结束信号,取消该队列,并退出SERVER。SERVER每接收到一个消息后显示一句“(server)received”。CLIENT端使用key为75的消息队列,先后发送类型从10到1的消息,然后退出。最后的一个消息,即是SERVER端需要的结束信号。CLIENT每发送一条消息后显示一句“(client)sent”。父进程在SERVER和CLIENT均退出后结束。数据结构#defineMSGKEY75structmsgform{longmtype; charmtext[1030];}msg;intmsgqid,i;程序流程图关键代码voidCLIENT(){inti;msgqid=msgget(MSGKEY,0777);for(i=10;i>=1;i--){msg.mtype=i; printf("(client)sent\n"); msgsnd(msgqid,&msg,1024,0);}exit(0);}voidSERVER(){msgqid=msgget(MSGKEY,0777|IPC_CREAT);do{msgrcv(msgqid,&msg,1030,0,0); printf("(Server)recieved\n");}while(msg.mtype!=1);msgctl(msgqid,IPC_RMID,0);exit(0);}voidmain(){while((i=fork())==-1);if(!i)SERVER();while((i=fork())==-1);if(!i)CLIENT();wait(0);wait(0);}实验结果与分析实验3-1结果分析:这个程序从主函数开始,然后通过fork()函数创建两个子进程SERVER和CLIENT,用来进行通信。在client函数中创建75序列,打开0777序列标识符然后后续传递给server函数进行匹配,然后设定msg.mtype=i就是让后面server函数唯一接收client传过来的信息,for循环10次,传递10次信息,通过msgsnd(msgqid,&msg,1024,0)来传递信息。问题:从理论上说,上述程序应当是每当client发送一条消息后,server接收该消息,client再发送下一条,也即是应该交替出现(client)sent和(server)received,但实际结果大多不是这样,会出现几个(client)sent连续后再几个(server)received,请分析原因。答:message的传送和控制并不保证完全同步,当一个程序不再激活状态的时候,它完全可能继续睡眠,造成上面现象,在多次sendmessage后才receivemessage.这一点有助于理解消息转送的实现机理.小结与心得体会本实验是对于熟悉Linux支持的消息通信机制,在Linux系统的进程通信机构(IPC)允许在任意进程间大批量地交换数据,通过本实验让我熟悉了解了通信的传送与接收的机制,在message传送与接收的过程中,其实在传送与接收的过程中并不是完全同步的,在多次多次sendmessage后才receivemessage,通过实验,体会到了Linux系统在这方面的功能,也很好的了解了本实验所要我们学习的本质!这也可以看看现在生活中的通信机制,当然不是进程之间,但十分相似与相近,在我们使用qq或者微信的时候,我们也等同于一个发送机制和一个接收机制,所以想象一下我们现在如此发达的通信的时代,研究人员是如何去减少这个延时,当我们网络信号不好时,延时就会很大,也很难同步。在本实验中我们所使用的是操作系统中的消息队列这一进程通信方法,我不仅深入了解本实验所用的消息队列的方式,还了解到还有管道、信号量、信号、共享内存、套接字等这些方式的特点,了解过后也对linux进程通信方式有了全面的了解,让我感受到通信的多样化与奇特!实验题目实验四、Windows的互斥与同步二、实验目的回顾操作系统进程、线程的有关概念,加深对Windows线程的理解。了解互斥体对象,利用互斥与同步操作编写生产者-消费者问题的并发程序,加深对P(即semWait)、V(即semSignal)原语以及利用P、V原语进行进程间同步与互斥操作的理解。实验内容背景知识信号量:信号量是一个与队列有关的整型变量。可以初始化成非负数;semWait操作使信号量减1。若值为负数,则执行semWait的进程阻塞,否则继续执行;semSignal操作使信号量加1。若值小于或等于0,则被semWait操作阻塞的进程被解除阻塞。模块介绍生产者:Produce()、Append()和消费者:Take()、Consume()实验步骤生产者消费者问题创建一个工程,用清单4-1中的程序,编译成可执行文件。在命令窗口运行步骤1中生成的可执行文件,列出运行结果。仔细阅读源程序,找出创建线程的WINDOWSAPI函数修改清单4-1中的程序,调整生产者线程和消费者线程的个数,使得消费者数目大与生产者,观察察运行结果。修改信号量EmptySemaphore的初始化方法,观察结果有何不同。根据步骤4的结果,并查看MSDN。数据结构constunsignedshortSIZE_OF_BUFFER=2;//缓冲区长度unsignedshortProductID=0;//产品号unsignedshortConsumeID=0;//将被消耗的产品号unsignedshortin=0;//产品进缓冲区时的缓冲区下标unsignedshortout=0;//产品出缓冲区时的缓冲区下标intbuffer[SIZE_OF_BUFFER];//缓冲区是个循环队列boolp_ccontinue=true;//控制程序结束HANDLEMutex;//用于线程间的互斥HANDLEFullSemaphore;//当缓冲区满时迫使生产者等待HANDLEEmptySemaphore;//当缓冲区空时迫使消费者等待DWORDWINAPIProducer(LPVOID);//生产者线程DWORDWINAPIConsumer(LPVOID);//消费者线程程序流程图关键代码DWORDWINAPIProducer(LPVOIDlpPara)//生产者{while(p_ccontinue){WaitForSingleObject(EmptySemaphore,INFINITE);//p(empty);WaitForSingleObject(Mutex,INFINITE); //p(mutex);Produce();Append();Sleep(1500);ReleaseMutex(Mutex); //V(mutex);ReleaseSemaphore(FullSemaphore,1,NULL); //V(full); }return0;}DWORDWINAPIConsumer(LPVOIDlpPara)//消费者{ while(p_ccontinue){WaitForSingleObject(FullSemaphore,INFINITE);//P(full);WaitForSingleObject(Mutex,INFINITE); //P(mutex);Take();Consume();Sleep(1500);ReleaseMutex(Mutex); //V(mutex);ReleaseSemaphore(EmptySemaphore,1,NULL); //V(empty); }return0;}实验结果与分析实验4-1结果分析:修改后代码清单4-1后,从main()函数开始,首先创建了生产者-消费者问题中应用到的互斥信号和同步信号以及其他基础定义,创建消费者生产者线程;最初生产者满足条件生产产品,所以先执行生产者,然后当资源有产品时,会执行消费者,生产者和消费者在代码运行过程中出现是随机的,当生产者多于消费者时,生产速度快,生产者经常等待消费者;反之,消费者经常等待;若缓冲区为空,则必定是生产者运行,缓冲区为满,则消费者运行,生产者等待,而对于结果的表示,则是调用Append()和Consume()中的循环输出。问题:线程的第一个执行函数是什么(从哪里开始执行)?它位于创建线程的API函数的第几个参数中?答:生产者第一个执行的函数是Producer(),消费者第一个执行的函数是Consumer(),位于创建线程API的第3个函数。实验4-2结果分析:当生产者多余消费者时候,生产者生产多个的时候消费者才会去消费。当生产者少于消费者时,生产者基本每生产一个,消费者就消费一个。问题:观察结果有何不同,从中你可以得出什么结论?答:当生产者个数多于消费者个数时生产速度快,生产者经常等待消费者对产品进行消费;反之,消费者经常等待生产者生产。实验4-3结果分析:将资源EmptySemaphore的初始值设置为0,也就是一开始两个资源都不能获取,导致无论是生产者还是消费者的P操作都不无法取到资源,只能一直等待,所以窗口不输出任何东西,表示的含义就是生产者和消费者都在等待EmptySemphore资源的释放。小结与心得体会通过本实验深入了解互斥体对象,利用互斥与同步操作编写生产者-消费者问题的并发程序,加深对P(即semWait)、V(即semSignal)原语以及利用P、V原语进行进程间同步与互斥操作的理解,还回顾了顾操作系统进程、线程的有关概念,加深对Windows线程的理解,在本实验中,有意思的就是可以通过改变生产者和消费者的数量大小来观察在进程运行的时候,生产者和消费者的状态,当消费者大于个数多于消费者个数时生产速度快,生产者经常等待消费者对产品进行消费;反之,消费者经常等待生产者生产。这也和老师上课讲的理论知识遥相呼应,也让我更加加深了对于生产者消费者的问题的理解,接着通过设置资源EmptySemaphore的初始值设置为0,使其两个资源不能进行获取,导致无论消费者还是生产者都是在不停的等待,导致界面的不显示,所以在进行实验的时候通过改变一个小小的值就可以改变实验结果,也让我体会到底层语言的艰辛,也感觉到了写代码时候要及其注意参数的传递,因为可能由于参数的传递,或者对于资源的赋值就可以改变实验结果,达不到想要的效果,所以我们再检查错误时候要仔细检查这方面的错误,通过本实验收获很多,感触颇深!实验题目实验六、银行家算法的模拟与实现实验目的进一步理解进程的并发执行。加强对进程死锁的理解,理解安全状态与不安全状态的概念。掌握使用银行家算法避免死锁问题。总体设计背景知识 死锁:多个进程在执行过程中,因为竞争资源会造成相互等待的局面。如果没有外力作用,这些进程将永远无法向前推进。此时称系统处于死锁状态或者系统产生了死锁。 安全序列:系统按某种顺序并发进程,并使它们都能达到获得最大资源而顺序完成的序列为安全序列。 安全状态:能找到安全序列的状态称为安全状态,安全状态不会导致死锁。 不安全状态:在当前状态下不存在安全序列,则系统处于不安全状态。 银行家算法:银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要满足多个客户的借贷周转,为了防止银行家资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。当一进程提出资源申请时,银行家算法执行下列步骤以决定是否向其分配资源:检查该进程所需要的资源是否已超过它所宣布的最大值。检查系统当前是否有足够资源满足该进程的请求。系统试探着将资源分配给该进程,得到一个新状态。执行安全性算法,若该新状态是安全的,则分配完成;若新状态是不安全的,则恢复原状态,阻塞该进程。模块介绍主函数运行模块银行家算法模块检查资源分配安全模块输出资源分配模块设计步骤初始化时让系统拥有一定的资源;用键盘输入的方式允许进程动态申请资源;如果试探分配后系统处于安全状态,则修改系统的资源分配情况,正式分配资源;如果试探分配后系统处于不安全状态,则提示不能满足请求,恢复原状态并阻塞该进程。详细设计数据结构资源总量向量Resource,m维,表示m种资源的总量。可用资源向量Available,m维,表示未分配的各种可用资源数量。需求矩阵Claim,n*m矩阵,表示n个进程对m类资源的最大需求。分配矩阵Allocation,n*m矩阵,表示n个进程已分配的各种资源数。程序流程图关键代码intchkerr(ints)//函数chkerr,检查是否安全{while(1){inti; intflag1=0; for(i=0;i<M;){ intsum=0;intk; for(k=0;k<M;k++){sum+=FINISH[k];}if(sum==M){ intij;printf("存在安全序列:["); for(ij=0;ij<M;ij++){ printf("p%d",array[ij]);} printf("]\n"); printf("【经安全性检查,系统安全,本次分配成功。】\n\n"); return1; }if(FINISH[i]!=1){ flag1=0; for(intj=0;j<N;j++){//资源检查 if(NEED[i][j]>WORK[j]){//进程i所需要的资源j能否被满足 flag1=1;break;}}}//有不满足的,就退出 if(flag1==0&&FINISH[i]!=1){//表示i进程没执行,且可以执行 intj; FINISH[i]=1;//i号进程,可以执行 printf("进程p%d执行\n",i);printf("系统当前可用资源:"); for(j=0;j<N;j++) {WORK[j]+=ALLOCATION[i][j];//各分配的资源回收 printf("%d",WORK[j]); } printf("\n"); array[cnt++]=i; i=0;}else{i++;}}//不能执行判断下一个进程实验结果与分析实验结果:首先刚进去的界面进行资源展示的界面当输入不合理时:分配失败时:分配成功时:实验分析:本实验由几个模块组成,先是对于进程所需资源量和剩余资源量的计算,然后调用显示函数,将所有的资源数量以及进程的各种数量显示出来,接着就是银行家算法的主体,通过用户输入的进程分配第一个资源,接着由程序自行判断,用银行家算法变成资源预分配状态,接着运用安全检测函数检测与分配的安全性,如果安全责则输出安全序列,分配成功,否则资源请求不合理再重新调配资源。小结与心得体会通过本实验加深了我对死锁避免银行家算法的理解,死锁避免其关键首先在于对于请求资源不能大于剩余资源的数量,也就是用户刚开始输入判断的那步,还有就是要时刻检查资源是否足够还有系统尝试着分配资源给进程然后得到新的安全序列,不安全则恢复,这也是银行家算法的核心。在本实验中还加深了我对于进程死锁的理解,理解安全状态与不安全状态的概念,进程死锁的条件是互斥、占有且等待、不可抢占、循环等待,这也是在避免死锁时的关键,可以通过对于任一条件的不满足破坏死锁,但是银行家算法相比与其他,代价较小,当进程分配的为死锁序列时,程序将会进行回滚,恢复原来的状态,使系统不会出现死锁状态。在做本实验之前,在学习银行家算法时,原本是有一些些不明白,在通过本实验之后,茅塞顿开,感觉十分奇妙,是死锁避免安全性检查的奇特,也让我对操作系统的兴趣又加深了一步,也希望将来能够学习到更多更深的知识去丰富自己,加强自己。实验题目实验七、磁盘调度算法的模拟与实现实验目的了解磁盘结构以及磁盘上数据的组织方式。掌握磁盘访问时间的计算方式。掌握常用磁盘调度算法及其相关特性。总体设计背景知识磁盘调度算法:磁盘调度的目的是要尽可能降低磁盘的寻道时间,以提高磁盘I/O系的性能。先进先出算法FIFO:按访问请求到达的先后次序进行调度。最短服务时间优先算法SSTF:优先选择使磁头臂从当前位置开始移动最少的磁盘I/O请求进行调度。SCAN(电梯算法):要求磁头臂先沿一个方向移动,并在途中满足所有未完成的 请求,直到它到达这个方向上的最后一个磁道,或者在这个方向上没有别的请求为止,后一种改进有时候称作LOOK策略。然后倒转服务方向,沿相反方向扫描,同样按顺序完成所有请求。C-SCAN(循环扫描)算法:在磁盘调度时,把扫描限定在一个方向,当沿某个方 向访问到最后一个磁道时,磁头臂返回到磁盘的另一端,并再次开始扫描。磁盘数据的组织:磁盘上每一条物理记录都有唯一的地址,该地址包括三个部分:磁头号(盘面号)、柱面号(磁道号)和扇区号。给定这三个量就可以唯一地确定一个地址。磁盘访问时间的计算方式:磁盘在工作时以恒定的速率旋转。为保证读或写,磁头必须移动到所要求的磁道上,当所要求的扇区的开始位置旋转到磁头下时,开始读或写数据。对磁盘的访问时间包括:寻道时间、旋转延迟时间和传输时间。模块介绍主函数模块先进先出算法FIFO模块最短服务时间优先算法SSTF模块SCAN(循环扫描)算法模块C-SCAN(循环扫描)算法模块设计步骤首先对于main函数的总体设计,采用用户输入磁道号数组与算法编号,然后调用相应算法函数先进先出算法FIFO模块的设计最短服务时间优先算法SSTF模块的设计SCAN(循环扫描)算法模块的设计C-SCAN(循环扫描)算法模块的设计详细设计数据结构#definemaxsize1000//定义最大数组域voidsort(int*a,intleft,intright)//二分法排序voidFIFO(intarray[],intm)//先进先出调度算法voidSSTF(intarray[],intm)//最短服务时间优先算法voidSCAN(intarray[],intm)//扫描算法,采用look策略voidCSCAN(intarray[],intm)//循环扫描算法,采用look策略程序流程图3.关键代码voidsort(int*a,intleft,intright)//二分法排序{if(left>=right)/*如果左边索引大于或者等于右边的索引就代表已经整理完成一个组了*/{return;}inti=left;intj=right;intkey=a[left];while(i<j)/*控制在当组内寻找一遍*/{while(i<j&&key<=a[j])//找到从右边开始第一个大于key的值 /*而寻找结束的条件就是找到一个小于或者大于key的数(大于或小于取决于你想升序还是降序)2、没有符合条件1的,并且i与j的大小没有反转*/{ j--;}/*向前寻找*/a[i]=a[j];/*找到一个这样的数后就把它赋给前面的被拿走的i的值(如果第一次循环且key是a[left],那么就是给key)*/while(i<j&&key>=a[i])/*这是i在当组内向前寻找,同上,不过注意与key的大小关系停止循环和上面相反,因为排序思想是把数往两边扔,所以左右两边的数大小与key的关系相反*/{ i++; }a[j]=a[i];} a[i]=key; /*当在当组内找完一遍以后就把中间数key回归*/ sort(a,left,i-1);/*最后用同样的方式对分出来的左边的小组进行同上的做法*/ sort(a,i+1,right);/*用同样的方式对分出来的右边的小组进行同上的做法*/ /*当然最后可能会出现很多分左右,直到每一组的i=j为止*/}实验结果与分析实验结果:先进先出算法(FIFO)最短服务时间优先算法(SSTF)扫描算法(SCAN)(LOOK策略)循环扫描算法(C-SCAN)(LOOK策略)实验分析:先来先服务的优点为简单与公平,缺点就是平均寻道时间距离大,效率不高,磁壁粘着,适用于磁盘I/O较少的场合;最短寻道时间优先算法性能比"先来先服务"好,能保证平均寻道时间最短,但是可能出现"饥饿"现象,
磁壁粘着;扫描算法寻道性能较好,可避免"饥饿"现象;既考虑了距离,同时又考虑了方向,但是却不利于远离磁头一端的访问请求,
磁壁粘着;循环扫描算法则消除了对两端磁道请求的不公平。小结与心得体会通过本次实验让我充分了解了掌握常用磁盘调度算法及其相关特性,在本实验我们模拟的是磁盘调度的模拟和实现,充分了解其各种调度算法的原理以及对于寻道数量以及平均寻道长度的理解,在设计算法时候,要注意的就是要掌握各算法特性以及它调度的规律,我们在设计算法时,还要注意代码代码的重复利用性,就是可以单独提出一个重复利用到的函数,比如扫描算法都是运用了look策略,我们就使用了一个sort二分查找的函数供他们调用,减少了代码的耦合性,还是代码不显得冗余、易懂。然后在设计算法时遇到的困难就是在设计时要运用许多的for循环去累加数,比如累加寻道数量的累加,容易搞混淆,要及其注意,然后还有对于其他来说就是sort函数的编写,通过各种学习与请教,让我搞懂以及不断测试后,终于将程序功能变得十分完善,十分完美。通过这次的学习,让我感受到了计算机磁盘调度的奇妙之处,在不同场合结果其实并不相同,分为不同的场合,各种磁盘调度算法都不一样,也让我感受到,人类真正实现智能化,还需要我们这一代的努力与奋斗,不断突破自我,深入学习,才能使操作系统的未来更上一层楼,我也愿意在这方面贡献我的绵薄之力!实验题目实验九、基于信号量机制的并发程序设计实验目的回顾操作系统进程、线程的有关概念,针对经典的同步、互斥、死锁与饥饿问题进行并发程序设计与实现。理解Linux支持的信息量机制,利用IPC的信号量系统调用编程实现哲学家进餐问题。总体设计背景知识哲学家进餐问题描述有五个哲学家,他们的生活方式是交替地进行思考和进餐,哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,该哲学家进餐完毕后,放下左右两只筷子又继续思考。约束条件:只有拿到两只筷子时,哲学家才能吃饭。如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。任一哲学家在自己未拿到两只筷子吃完饭前,不会放下手中已经拿到的筷子模块介绍wait_for_2fork()模块(对两个筷子进行p操作)free_2fork()模块(对筷子进行V操作)philosephere()模块(哲学家模块)Main()主函数模块设计步骤分析实验要求,找到实验解决办法,确定数据结构分析然后编写主函数模块,定义5个信号量都为1,创建五个进程编写philosephere()模块(哲学家模块),对于进程进行PV操作编写P操作函数模块编写V操作函数模块运行测试、分析结果详细设计数据结构#defineERR_EXIT(m)do{perror(m);exit(EXIT_FAILURE);}while(0)#defineDELAY(rand()%5+1)intsemid;//信号量IDunionsemun{ intval; /*ValueforSETVAL*/ structsemid_ds*buf; /*BufferforIPC_STAT,IPC_SET*/ unsignedshort*array; /*ArrayforGETALL,SETALL*/ structseminfo*__buf; /*BufferforIPC_INFO(Linux-specific)*/};程序流程图关键代码voidwait_for_2fork(intno)//P操作{ intleft=no;intright=(no+1)%5;//拿右边的筷子structsembufbuf[2]={{left,-1,0},{right,-1,0}};//拿起筷子,因此第left,right信号量减一semop(semid,buf,2);//P操作,若果能同时拿起两个筷子,就不用等待}voidfree_2fork(intno)//V操作{ intleft=no;intright=(no+1)%5;structsembufbuf[2]={{left,1,0},{right,1,0}};//放下筷子,因此第left,right信号量加一semop(semid,buf,2);//V操作,同时放下两只筷子}intphilosephere(intno)//哲学家算法{srand(getpid());for(;;){printf("%disthinking\n",no);sleep(DELAY);printf("%dishungry\n",no);wait_for_2fork(no);printf("%diseating\n",no);sleep(DELAY);free_2fork(no);}}intmain(intargc,char*argv[]){unionsemunsu;su.val=1;semid=semget(IPC_PRIVATE,5,IPC_CREAT|0666);//因为是父子进程通信,可以设置为IPC_PRIVATE,五个人,因此管理五个信号量if(semid==-1)ERR_EXIT("semget");for(inti=0;i<5;i++)semctl(semid,i,SETVAL,su);//将5个信号量分别初始化为1intno=0;inti=0;pid_tpid;for(i=1;i<5;i++){pid=fork(); //产生5个进程if(pid==-1)ERR_EXIT("fork");if(pid==0){no=i;break;//必须break,否则子进程会创建出新的进程}}//printf("no=%d\n",no);philosephere(no);return0;}实验结果与分析实验结果:........分析:实验未出现死锁现象,进程一直在重复的思考、就餐。然后程序没有运行卡着,即没有发生死锁现象,从中也可以发现同时最多只能有两个哲学家一起用餐,也不会出现相邻哲学家一起用餐的情况。小结与心得体会通过本次实验首先是对于哲学家就餐问题有了更深的了解,按照实验要求通过PV操作来解决哲学家就餐问题,这也使我回顾了操作系统进程、线程的有关概念,针对经典的同步、互斥、死锁与饥饿问题进行并发程序设计与实现,在运用PV操作解决哲学家问题的同时,我也发现了另外几种可以很好解决哲学家就餐问题的方法,比如允许最多4个哲学家同时坐在桌子上或者只有一个哲学家的两根筷子都可用时,他才能拿起它们(他必须在临界区内拿起两根筷子)。或者使用非对称解决方案。即单号的哲学家先拿起左边的筷子,接着右边的筷子;而双号的哲学家先拿起右边的筷子,接着左边的筷子。在设计本实验时,主要就是PV操作的运用,在运用PV操作时就是对于semop函数的操作,先是对于信号量的加一或者减一,然后调用semop函数进行PV操作,因此本实验的关键就是对于信号量系统调用编程实现哲学家进餐问题,也让我深刻理解了Linux支持的信息量机制,我也从中体会到操作系统的奇妙之处,加深了我对于操作系统的学习以及理解,我从中也受益匪浅。实验题目实验十、简单shell命令行解释器的设计与实现实验目的本实验主要目的在于进一步学会如何在Linux系统下使用进程相关的系统调用,了解shell工作的基本原理,自己动手为Linux操作系统设计一个简单的命令接口。总体设计背景知识常见的shell内部命令如下:cd<目录>更改当前的工作目录到另一个<目录>。如果<目录>未指定,输出当前工作目录如果<目录>不存在,应当有适当的错误信息提示。这个命令应该也能改变PWD的环境变量environ列出所有环境变量字符串的设置(类似于Linux系统下的env命令)echo<内容>显示echo后的内容且换行help简短概要的输出你的shell的使用方法和基本功能。jobs输出shell当前的一系列子进程,必须提供子进程的命名和PID号。quit,exit,bye退出shell。提示:shell的主体就是反复下面的循环过程while(1){接收用户输入的命令行;解析命令行;if(用户命令为内部命令)直接处理;elseif(用户命令为外部命令)创建子进程执行命令;else提示错误的命令;}模块介绍一个main函数模块包含了判断与响应的操作设计步骤分析实验要求,确定好所要实现的shell内部命令,确定数据结构将所确定的shell命令行进行分类,按照首字母来分类在细分shell命令,编写shell命令详细操作测试程序,分析结果 详细设计数据结构charcmd[2100]; //用来存放用户的输入命令intlen=strlen(cmd)//用来获取用户命令行长度charcata[100]; //用来将cmd值传递赋值程序流程图关键代码intmain(){charcmd[2100];while(1){printf("\n--------------------------------------------------\n"); printf("shell命令行解释器"); printf("\n--------------------------------------------------\n\n");printf("请输入你的操作:");scanf("%s",cmd);Intlen=strlen(cmd),i;if(cmd[0]=='e'&&cmd[1]=='c')//echo{intflag=0;for(i=5;i<len-1;i++){if(cmd[i]!='')flag=1;//hif(flag){putchar(cmd[i]);}} if(flag){putchar('\n');}elseif(cmd[0]=='q'||cmd[1]=='x'||cmd[0]=='b')//quit,exit,bye {printf("Bye\n"); return0;}elseif(cmd[0]=='h'){ //helpprintf("echo<content>\tprintalinecontent\n");printf("quit,exit,bye\tendproduce\n");printf("cd<catalog>\techocatalog\n");printf("jobs\techoprocessnameandpid...\n");printf("environ\techoenvironmentvariable\n");}els
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024至2030年中国平行百叶窗数据监测研究报告
- 2024年超深井用高抗挤毁石油管钢项目评估分析报告
- 2024至2030年中国铲运机大臂数据监测研究报告
- 2023年无机械动力飞机项目评估分析报告
- 2023年澳代巴豆酸乙酯项目成效分析报告
- 2024至2030年中国自行车前叉立管行业投资前景及策略咨询研究报告
- 2024至2030年中国碳素结构冷轧钢带数据监测研究报告
- 2024至2030年中国棉绒数据监测研究报告
- 2024至2030年中国数字可变衰减器数据监测研究报告
- 2024至2030年中国头盔式隔热面罩数据监测研究报告
- 生物技术为精准医疗注入新动力
- 2024年高级经济师之工商管理题库(历年真题)
- 《linux操作系统应用》课程标准
- 《公务员回避制度》课件
- 全市体育中考成绩分析报告
- 四川省凉山州西昌市2023-2024学年四年级上学期期末数学试卷
- 康复护理的历史发展
- 初中物理教学经验分享
- 烟花爆竹从业人员安全培训试题
- Part1-2 Unit3 Internship教案-【中职专用】高一英语精研课堂(高教版2021·基础模块2)
- 一例下肢静脉溃疡患者的个案护理论文
评论
0/150
提交评论