电子信息学院计算机科学与技术课程设计报告(2011-2012第1学期)题目:操作系统组成原理学号:姓名:专业:计算机科学与技术指导教师:课程设计日期:目录(一)验环境、相关背景知识介绍;.................................................3(二)实验内容..........................................................................................32.1操作系统的进程调度(处理机调度-时间片轮转).........................................32.1.1基本原理分析...................................................................................................32.1.2程序流程图.......................................................................................................42.1.3数据结构...........................................................................................................42.1.4测试与结论......................................................................................................52.1.5思考与感悟.......................................................................................................72.2操作系统的进程通信(管道通信)..................................................................82.2.1基本原理分析...................................................................................................82.2.2程序流程图.......................................................................................................82.2.3实现步骤...........................................................................................................92.2.4测试结果.........................................................................................................102.2.5思考与感悟.....................................................................................................11(三)小结..............................................................................................11(四)参考文献......................................................................................11(一)验环境、相关背景知识介绍;计算机基本配置要求:操作系统:win98/2000/xp/2003等windows平台内存:256MB及以上主存64KB开发语言:visualc++(二)实验内容2.1操作系统的进程调度(处理机调度-时间片轮转)2.1.1基本原理分析当系统按时间片轮转算法调度进程时,将所有的就绪进程按照一定的原则(如先来先服务原则)排列,形成一个就绪队列。每次调度为队首进程分配CPU资源,令其执行一个时间片,该时间片的大小从几ms到几百ms。当时间片用完时,由计时器发出中断信号,通知系统剥夺当前运行进程的CPU使用权,并将此进程送入就绪队列的末尾,等待下一次执行;然后,把处理机分配给就绪队列中断的队首进程,执行重复操作。在进程运行过程中,如果时间片未用完而等待事件发生,则该进程进入等待队列,系统将CPU重新分配给就绪队列的队首进程,一旦事件发生后,等待队列的队首进程进入就绪队列末尾。这样就可以保证就绪队列中的所有进程,在可接受的时间内,均能获得处理机并调度执行。2.1.2程序流程图开开开开开开开开AlgoAlgo=priority/roundrobin?开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开1开开开开开3开开开开开开开0开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开1开开开CPU开开开1开开开开开开开0开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开开priority开开开开开开roundrobin开开开开开2.1.3数据结构Typedefstructjcb{charname[N];intprio;intround;intcputime;intneedtime;intcount;charstate;structnode*next;}2.1.4测试与结论2.1.5思考与感悟实验感想本实验的难点是每执行一个时间片就让它排到队尾,也即重新排序,并从头开始调度执行!时间片的工作流程是:时间片轮转的原则是系统将所有的就绪进程按照先来先服务的原则排成一个队列,每次调度时,把CPU分配对手进程,并令其执行一个时间片,当执行完时,有一个计时器发出时钟中断请求,该进程停止,并被送到就绪队列的末尾,然后再把处理机分配就绪队列的队列进程,同时也让它执行一个时间片!通过亲手实验,对上述写的时间片的工作流程和原理有了更贴切的认识!本次实验遇到了很大的麻烦,及时大部分代码是借鉴网上的,但自己通过修改,来获取自己想要的,在自己的努力和同学的帮助下终于调试正确!很是高兴!2.2、操作系统的进程通信(管道通信)2.2.1基本原理分析管道分为无名管道和有名管道两种。无名管道可用于具有亲缘关系进程间的通信,如父子进程、兄弟进程。有名管道克服了管道没有名字的限制,允许无亲缘关系进程间的通信。本文应用的是管道通信无名机制。管道具有以下特点:(1)管道是半双工的,数据只能单向流动;需要相互通信时,就要建立两个管道。(2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程,有名管道则突破了这一限制)。(3)单独构成一种独立的文件系统,并且只存在于内存中。(4)数据的读出和写入都是单向的:一个进程向管道中写的数据被管道另一端的进程读出。写入的数据每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。管道的创建:#includeunistd.hintpipe(intfd[2])该函数是Linux的一个系统调用,其创建的管道两端处于一个进程中间。要用其实现父子进程之间的通信则需要在由pipe()创建管道后,再由系统调用fork创建一个新的子进程,然后通过管道在这两个进程间传送数据,实现进程间的通信(同样,不是父子关系和两个进程,只要两个进程中存在亲缘关系——具有共同的祖先,都可以采用管道方式来进行通信)。管道的读写:Pipe函数有一个参数fd[2],是用于管道两端的描述字。管道一端只能用于读,由描述字fd[0]表示,即管道读端;另一端则只能用于写,由描述字fd[1]表示,即管道写端。既不能从管道写端读取数据,也不能向管道读端写入数据。I/O函数close、read、write等都可以用于对管道进行操作。从管道中读取数据时,如果管道的写端不存在,则认为已经读到了数据末尾,读函数返回的读出字节数为0;若管道写端存在,如果请求的字节数目大于管道中现有的数据字节数,则返回管道中现有数据字节数;否则返回请求的字节数。向管道中写入数据时,只要管道缓冲区有空闲区域,写进程就会试图向管道中写入数据。如果读数据的进程不读走管道缓冲区中的数据,那么将导致写操作的阻塞。这是管道通信的一个弊端。2.2.2程序流程图2.2.3实现步骤管道的创建管道是一种最基本的IPC机制,由pipe函数创建:#includeunistd.hintpipe(intfiledes[2]);调用pipe函数时在内核中开辟一块缓冲区(称为管道)用于通信,它有一个读端一个写端,然后通过filedes参数传出给用户程序两个文件描述符,filedes[0]指向管道的读端,filedes[1]指向管道的写端(很好记,就像0是标准输入1是标准输出一样)。所以管道在用户程序看起来就像一个打开的文件,通过read(filedes[0]);或者write(filedes[1]);向这个文件读写数据其实是在读写内核缓冲区。pipe函数调用成功返回0,调用失败返回-1。开辟了管道之后如何实现两个进程间的通信呢?比如可以按下面的步骤通信。1.父进程调用pipe开辟管道,得到两个文件描述符指向管道的两端。2.父进程调用fork创建子进程,那么子进程也有两个文件描述符指向同一管道。开始是否为P2执行结束NYP2从pipe1中读取数据P1往pipe1中写入数据P1创建子进程P2读取数据字符数为否为偶数P2创建子进程P3是否为P3执行P3从pipe2中读取数据P2往pipe2写入数据是否为P4执行P4从pipe3中读取数据P2创建子进程P4YNNNP2往pipe3写入数据YY3.父进程关闭管道读端,子进程关闭管道写端。父进程可以往管道里写,子进程可以从管道里读,管道是用环形队列实现的,数据从写端流入从读端流出,这样就实现了进程间通信。2.2.4测试结果2.2.5思考与感悟:父进程在读取子进程向管道里面入写数据时,子进程1原内容输出,但是当子进程2写过后有覆盖现象。而且由于子进程父进程每执行一次相关操作后,就会休眠,使得运行结果不唯一。覆盖现象是因为子进程创建后,虽然是共享父进程中管道的空间,但并不是说有指针等指向那里,而是将该地址空间的内容,复制到自己的那部分空间中,而程序总子进程每次是从头开始填写,所以有覆盖现象。如果设置全局变量,指向读写后的当前位置为下一次读写的其实位置,可以调试出不同的结果。总结:通过本次试验,我掌握了Linux系统中管道通信的原理,了解了管道通信的特点,掌握了Linux管道的相关函数的功能及使用方法,并了解了Linux管道的建立与使用,学会了如何利用管道实现进程间的通信,对进程间的通信有了更深刻的理解与掌握。(三)小结由于理论知识的不足,再加上平时没有什么设计经验,一开始的时候有些手忙脚乱,不知从何入手。在老师和同学的帮助下,使我找到了信心。虽然种种困难都以克服,但还是会有疏忽和遗漏的地方。完美总是可遇不可求,抱着这个心态我一步步做下来。通过这次课设,我发现自己原来的知识还是比较欠缺,我现在明白学习是个长期的过程。知识必须通过应用才能实现其价值。有些东西我以为学会了,可是真的用的时候我发现时两回事,所以我认为会用才是真的学会了。在设计过程中,我查阅了很多资料,经历了不少艰辛,