写优先”策略的“读者-写者”问题
操作系统——读者-写者问题的解决方法

操作系统——读者-写者问题的解决⽅法问题描述不允许Write进程和Read进程或其他Write进程同时访问⽂件,Read进程可以和其他Read进程同时访问。
分为三种类型。
读者优先要求:1.多个读者可以同时访问⽂件2.同⼀时间只允许⼀个写者访问⽂件3.读者和写者进程互斥解决⽅法:⽤⼀个readcounter记录是第⼏个读者在读,如果是第⼀个读者,则不能让写者写,需要⼀个锁。
因为readcounter是临界资源,也需要⼀个互斥量。
semaphore rc_mutex = 1, wmutex = 1;readcounter = 0;void writer{do{wait(wmutex);//writesignal(wmutex);}while(TRUE);}void reader{do{wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);// readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}写者优先要求:1.读者写者互斥2.写者读者同时等待时,所有等待的写者优先,等所有写者结束后,读者才能读3.没有写者时,读者能同时读4.写者到来时,不会终⽌已经进⾏的读者操作解决⽅法:semaphore wc_mutex = 1, prior = 1; //写者计数器,优先信号量readcounter = 0, writercounter = 0;void writer{do{wait(wc_mutex); //申请更改wc的权限if(writercounter == 0) //如果是第⼀个写者,就申请优先权限wait(prior);writercounter ++;signal(wc_mutex);wait(wmutex);//writesignal(wmutex);wait(wc_mutex);writercounter --;if(!writercounter)signal(prior); //当最后⼀个写者操作完成后,释放优先级权限 signal(wc_mutex);}while(TRUE);}void reader{do{wait(prior); //先申请优先级权限,如果前⾯还有写者就等待wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);signal(prior); //释放优先级权限// readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}读写均等semaphore prior = 1; //读者和写者都等待在⼀个队列上,实现读写均等readcounter = 0, writercounter = 0;void writer{do{wait(prior);wait(wmutex);//writesignal(wmutex);signal(prior);}while(TRUE);}void reader{do{wait(prior);wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);signal(prior);//readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}有错误请指出!。
实验五 读者-写者问题

实验题目:实验五读者-写者问题完成人:报告日期:一、实验内容简要描述1)创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
2)读者-写者问题的读写操作限制(包括读者优先和写者优先):写-写互斥,即不能有两个写者同时进行写操作。
读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
●读-读允许,即可以有一个或多个读者在读。
3)读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
4)写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
5)运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、程序设计1、设计思路将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
2、主要数据结构1)读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=0时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读-写互斥,当read_count=l时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。
读者写者问题

读者-写者问题一个著名的同步问题是读者-写者问题(Courtois 等人,1971),它为数据库访问建立了一个模型。
例如,设想一个飞机订票系统,其中有许多竞争的进程试图读写其中的数据。
多个进程同时读数据库是可以接受的,但如果一个进程正在更新(写)数据库,则所有的其他进程都不能访问该数据库,即使读操作也不行。
这里的问题是如何对读者和写者进行编程?图2-47给出了一种解法。
在该解法中,第一个读者对信号量db 执行down操作。
随后的读者只是递增一个计数器rc。
当读者离开时,它们递减这个计数器,而最后一个读者则对信号量执行up,这样就允许一个被阻塞的写者(如果存在的话)可以访问该数据库。
在该解法中,隐含着一个需要注解的条件。
假设一个读者正使用数据库,另一个读者来了。
同时有两个读者并不存在问题,第二个读者被允许进入。
如果有第三个和更多的读者来了也同样允许。
现在,假设一个写者到来。
由于写者的访问是排他的,不能允许写者进入数据库,只能被挂起。
只要还有一个读者在活动,就允许后续的读者进来。
这种策略的结果是,如果有一个稳定的读者流存在,那么这些读者将在到达后被允许进入。
而写者就始终被挂起,直到没有读者为止。
如果来了新的读者,比如,每2秒钟一个,而每个读者花费5秒钟完成其工作,那么写者就永远没有机会了。
为了避免这种情形,可以稍微改变一下程序的写法:在一个读者到达,且一个写者在等待时,读者在写者之后被挂起,而不是立即允许进入。
用这种方式,在一个写者到达时如果有正在工作的读者,那么该写者只要等待这个读者完成,而不必等候其后面到来的读者。
该解决方案的缺点是,并发度和效率较低。
Courtois等人给出了一个写者优先的解法。
如下:一个写者优先的一个案例。
北理工操作系统实验二读者写者问题

本科实验报告实验名称:操作系统原理实验(读者写者问题)课程名称:操作系统原理实验时间:2015.10.30 任课教师:王耀威实验地点:10#102实验教师:苏京霞实验类型: 原理验证□综合设计□自主创新学生姓名:孙嘉明学号/班级:1120121474/05611202 组号:学院:信息与电子学院同组搭档:专业:信息对抗技术成绩:实验二:读者写者问题一、实验目的1.通过编写和调试程序以加深对进程、线程管理方案的理解;2.熟悉Windows多线程程序设计方法;二、实验要求在Windows环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先)1)写-写互斥:不能有两个写者同时进行写操作2)读-写互斥:不能同时有一个线程在读,而另一个线程在写。
3)读-读允许:可以有一个或多个读者在读。
读者优先的附加限制:如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
测试数据文件包括 n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,每个字段间用空格分隔。
第1个字段为正整数,表示线程的序号。
第2个字段表示线程的角色,R表示读者,W表示写者。
第3个字段为一个正数,表示读写开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。
第4个字段为一个正数,表示读写操作的延迟时间。
当线程读写申请成功后,开始对共享资源进行读写操作,该操作持续相应时间后结束,释放该资源。
下面是一个测试数据文件的例子(在记事本手工录入数据):1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3三、实验环境硬件设备:个人计算机。
读者写者问题实验报告

读者写者问题实验报告1. 引言读者写者问题是操作系统中的经典同步问题,用于研究多线程环境下对共享资源的访问和保护。
在该问题中,有多个读者和写者同时对一个共享资源进行操作,需要保证并发访问时的正确性和效率。
通过本实验,我们将探讨读者写者问题的解决方案,并比较不同算法的性能差异。
2. 实验目标本实验的主要目标是通过实现和比较不同的读者写者问题算法,深入了解并发访问的挑战和解决方案。
具体而言,我们将研究以下几个方面:•设计并实现读者写者问题的解决方案•比较不同算法的性能差异•分析可能的优化策略3. 实验方法我们将使用Python编程语言来实现读者写者问题的解决方案。
在实验过程中,我们将尝试以下几种常见的算法:3.1. 读者优先算法在读者优先算法中,当有读者在访问共享资源时,其他读者可以同时访问,但写者需要等待。
只有当所有读者完成访问后,写者才能获得访问权限。
3.2. 写者优先算法在写者优先算法中,当有写者在访问共享资源时,其他读者和写者都需要等待。
只有当写者完成访问后,其他读者或写者才能获得访问权限。
3.3. 公平算法在公平算法中,读者和写者的访问权限是公平的,先到先得。
无论读者还是写者,都需要按照到达的顺序依次获取访问权限。
4. 实验步骤下面是我们实施实验的具体步骤:4.1. 实现基本的读者写者问题解决方案我们首先实现基本的读者写者问题解决方案,包括读者和写者的线程逻辑和共享资源的访问控制。
我们将使用互斥锁和条件变量来保证并发访问的正确性。
4.2. 实现读者优先算法在已有的基本解决方案的基础上,我们实现读者优先算法。
我们将通过优化访问控制的逻辑来实现读者优先的特性。
4.3. 实现写者优先算法类似地,我们在基本解决方案的基础上实现写者优先算法。
我们将调整访问控制的逻辑,使得写者优先于其他读者和写者。
4.4. 实现公平算法最后,我们实现公平算法。
我们将结合队列和条件变量等技术来确保读者和写者的访问顺序是公平的。
读者-写者问题的实现

目录摘要 (1)1.设计思想 (2)2.各模块的伪码算法 (3)3. 函数关系调用图 (5)4.程序测试结果 (6)设计总结 (9)参考文献 (10)致谢 (11)摘要本设计的读者写者问题,是指一些进程共享一个数据区。
数据区可以使一个文件、一块内存空间或者一组寄存器。
Reader进程只能读数据区中的数据,而writer进程必须与其他进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述, 有一群写者和一群读者, 写者在写同一本书, 读者也在读这本书, 多个读者可以同时读这本书。
但是,只能有一个写者在写书, 并且,读者必写者优先,也就是说,读者和写者同时提出请求时,读者优先。
当读者提出请求时需要有一个互斥操作, 另外, 需要有一个信号量S来确定当前是否可操作。
本设计方案就是通过利用记录型信号量对读者写者问题的解决过程进行模拟演示,形象地阐述记录型信号量机制的工作原理。
关键词:共享对象,互斥,同步,信号量1.设计思想本设计借助C语言实现进程同步和互斥的经典问题--读者写者问题,用高级语言编写和调试一个进程同步程序,以加深对进程同步机制的理解。
通过用C 语言模拟进程同步实现,加深理解有关进程同步和互斥机制的概念及P、V操作的应用。
学生通过该题目的设计过程,掌握读者、写者问题的原理、软件开发方法并提高解决实际问题的能力。
在 Windows环境下,创建一个包含n个线程的控制台进程。
用这n个线每个线程按相应测试数据文件的要求,进行读写操作。
程来表示 n 个读者或写者。
请用信号量机制分别实现读者优先和写者优先的读者-写者问题。
将所有的读者和所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。
读者-写者的读写限制(包括读者优先和写者优先)1)写-写互斥,即不能有两个写者同时进行写操作;2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写;3)读读允许,即可以有 2 个以上的读者同时读;4)读者优先附加条件:如果一个读者申请进行读操作,同时又有一个读操作正在进行读操作,则该读者可以直接开始读操作;5)写者优先附加条件:如果一个读者申请进行读操作时已经有一个写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
4--采用“写优先”策略的“读者-写者”问题
4--采用“写优先”策略的“读者-写者”问题《操作系统课程设计》任务书设计题目:采用“写优先”策略的“读者-写者”问题指导老师:赵娟课程设计的目的:操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决实际问题的机会。
? 进一步巩固和复习操作系统的基础知识。
? 培养学生结构化程序、模块化程序设计的方法和能力。
? 提高学生调试程序的技巧和软件设计的能力。
? 提高学生分析问题、解决问题以及综合利用 C 语言进行程序设计的能力。
设计内容:用高级语言编写和调试一个采用“写优先”策略的“读者-写者”问题的模拟程序。
设计要求:1. 读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入 2. 读者与写者均有二个以上,可在程序运行期间动态增加读者与写者 3. 可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化4. 要求将运行过程用可视化界面动态显示,可随时暂停,查看阅览室中读者/写者数目、读者等待队列、写者等待队列、读写时间、等待时间5. 读写策略为:读写互斥、写写互斥、写优先(只要写者到达,就阻塞后续的所有读者,一旦阅览室无人,写者能最快进入阅览室;在写者未出阅读室之前,又有新的读者与写者到达,仍然是写者排在前面)设计结束需提交下列资料:1、课程设计报告。
报告中至少应包括:相关操作系统的知识介绍,程序总的功能说明、程序各模块的功能说明、程序设计的流程图、源程序清单。
2、源程序和编译连接后的可执行程序文件。
时间安排:分析设计贮备阶段(1天)编程调试阶段(7天)写课程设计报告、考核(2天)感谢您的阅读,祝您生活愉快。
读者-写者问题说明书
《操作系统原理》课程设计任务书题目:读者-写者问题的实现学生姓名:李志旭学号:13740113 班级:_13级软件工程_题目类型:软件工程(R)指导教师:陈文娟、马生菊一、设计目的学生通过该题目的设计过程,掌握读者、写者问题的原理、软件开发方法并提高解决实际问题的能力。
二、设计任务编写程序实现读者优先和写者优先问题:读者-写者问题的读写操作限制(包括读者优先和写者优先)写-写互斥:不能有两个写者同时进行写操作读-写互斥:不能同时有一个线程在读,而另一个线程在写。
读-读允许:可以有一个或多个读者在读。
三、设计要求1.分析设计要求,给出解决方案(要说明设计实现所用的原理、采用的数据结构)。
2.设计合适的测试用例,对得到的运行结果要有分析。
3.设计中遇到的问题,设计的心得体会。
4.文档:课程设计打印文档每个学生一份,并装在统一的资料袋中,资料袋前面要贴有学校统一的资料袋封面。
四、提交的成果1. 课程设计说明书内容包括(1) 封面(学院统一印制);(2) 课程设计任务书;(3) 中文摘要150字;关键词3-5个;(4) 目录;(5) 正文;(设计思想;各模块的伪码算法;函数的调用关系图;测试结果等)(6) 设计总结;(7) 参考文献;(8) 致谢等。
注:每一部分是单独的一章,要另起一页写。
2. 排版要求(1) 所有一级标题为宋体三号加粗(即上面写的2~8部分,单独一行,居中)(2) 所有二级标题为宋体四号加粗(左对齐)(3) 所有三级标题为宋体小四加粗(左对齐)(4) 除标题外所有正文为宋体小四,行间距为固定值22磅,每个段落首行缩进2字符(5) 目录只显示3级标题,目录的最后一项是无序号的“参考文献资料”。
3. 其他要求(班长负责,务必按照以下方式建文件夹)(1) 以班级为单位刻录光盘一张,光盘以班级命名,例如:“10级计算机科学与技术1班”;(2) 光盘内每人一个文件夹,以学号姓名命名——如“10730101 陈映霞”,内容包括任务书、设计文档。
读者写者问题
3)读读允许,即可以有2个以上的读者同时读
将所有的读者与所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。读者写者问题的定义如下:有一个许多进程共享的数据区,这个数据区可以就是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)与一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:1)任意多个读进程可以同时读这个文件;2)一次只有一个写进程可以往文件中写;3)如果一个写进程正在进行操作,禁止任何读进程度文件。我们需要分两种情况实现该问题:
一设计概述
所谓读者写者问题,就是指保证一个writer进程必须与其她进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述,有一群写者与一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但就是,只能有一个写者在写书,并且,读者必写者优先,也就就是说,读者与写者同时提出请求时,读者优先。当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前就是否可操作。
信号量机制就是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者问题则就是这一机制的一个经典范例。
与记录型信号量解决读者—写者问题不同,信号量机制它增加了一个限制,即最多允许RN个读者同时读。为此,又引入了一个信号量L,并赋予初值为RN,通过执行wait(L,1,1)操作,来控制读者的数目,每当有一个读者进入时,就要执行wait(L,1,1)操作,使L的值减1。当有RN个读者进入读后,L便减为0,第RN+1个读者要进入读时,必然会因wait(L,1,1)操作失败而堵塞。对利用信号量来解决读者—写者问题的描述如下:
读者-写者问题解答
2.读者—写者问题读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。
计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。
就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:(1)允许多个读者同时执行读操作;(2)不允许读者、写者同时操作;(3)不允许多个写者同时操作。
Reader和Writer的同步问题分为读者优先、弱写者优先(公平竞争)和强写者优先三种情况,它们的处理方式不同。
(1)读者优先。
对于读者优先,应满足下列条件:如果新读者到:①无读者、写者,新读者可以读;②有写者等待,但有其它读者正在读,则新读者也可以读;③有写者写,新读者等待。
如果新写者到:①无读者,新写者可以写;②有读者,新写者等待;③有其它写者,新写者等待。
单纯使用信号量不能解决读者与写者问题,必须引入计数器rc 对读进程计数;rc_mutex 是用于对计数器rc 操作的互斥信号量;write表示是否允许写的信号量;于是读者优先的程序设计如下:int rc=0; //用于记录当前的读者数量semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量semaphore write=1; //用于保证读者和写者互斥地访问的信号量void reader() /*读者进程*/do{P(rc_mutex); //开始对rc共享变量进行互斥访问rc ++; //来了一个读进程,读进程数加1if (rc==1) P(write);//如是第一个读进程,判断是否有写进程在临界区,//若有,读进程等待,若无,阻塞写进程V(rc_mutex); //结束对rc共享变量的互斥访问读文件;P(rc_mutex); //开始对rc共享变量的互斥访问r c--; //一个读进程读完,读进程数减1if (rc == 0) V(write);//最后一个离开临界区的读进程需要判断是否有写进程//需要进入临界区,若有,唤醒一个写进程进临界区V(rc_mutex); //结束对rc共享变量的互斥访问} while(1)void writer() /*写者进程*/do{P(write); //无读进程,进入写进程;若有读进程,写进程等待写文件;V(write); //写进程完成;判断是否有读进程需要进入临界区,//若有,唤醒一个读进程进临界区} while(1)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
采用“写优先”策略的“读者-写者”问题学院计算机科学与技术专业计算机科学与技术学号学生姓名指导教师姓名2014-3-11目录一、设计目的与内容 ................................................ 错误!未定义书签。
(1 )、课程设计的目的 (1)(2 ) 、课程设计的内容 (1)(3 ) 、课程设计的要求 (1)二、算法的基本思想 ................................................ 错误!未定义书签。
三、模块流程图......................................................... 错误!未定义书签。
四、测试结果............................................................. 错误!未定义书签。
五、结论..................................................................... 错误!未定义书签。
六、源程序................................................................. 错误!未定义书签。
一、设计目的与内容(1)课程设计的目的:操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决问题的机会。
●进一步巩固和复习操作系统的基础知识。
●培养学生结构化程序、模块化程序设计的方法和能力。
●提高学生调试程序的技巧和软件设计的能力。
●提高学生分析问题、解决问题以及综合利用C语言进行程序设计的能力。
(2) 课程设计的内容:用高级语言编写和调试一个采用“写优先”策略的“读者—写者”问题的模拟程序。
(3) 课程设计的要求:1.读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入。
2.读者与写者均有两个以上,可在程序运行期间进行动态增加读者与写者。
3.可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化。
4.要求将运行过程用可视化界面动态显示,可随时暂停,查看阅览室中读者/写者数目、读者等待队列、读写时间、等待时间。
5.读写策略:读写互斥、写写互斥、写优先(只要写者到达,就阻塞后续的所有读者,一旦阅览室无人,写者能最快进入阅览室;在写者未出阅读室之前,又有新的读者与写者到达,仍然是写者排在前面)二、算法的基本思想进程结构体:struct process{int name; //进程ID 号char type; //进程类别(判断是读者还是写者线程)int starttime; //进程开始时间int needtime; //进程读写需要的时间int runtime; //进程在内存中已运行的时间struct process *next;};创建三个链表,分别为process1 、process2 、process3 。
process1 存储各个进程的信息,process2 存储就绪队列的进程信息,process3 存储正在执行的进程的信息。
系统有两个功能,一个是手动输入进程,另一个是文件输入进程。
文件读入功能,是从文件“123.txt”中读入进程。
用整形数I 模拟时间片,每次时间片开始时先将需要进入就绪队列的进程用ready() 函数拉入就绪队列。
接着用sort() 函数进行排序,将写者排在读者前面。
然后判断就绪队列的开头是读者还是写者,然后调用相应的函数Reader()或Writer()。
时间片结束时,对各个进程的runtime++,并判断进程是否执行完毕,如果完毕就其离开process3 链表。
最后将时间片i++,反复循环,直到所有进程执行完毕。
三、模块流程图四、测试结果程序运行实例如下:1、进入主界面2、选择1,运行界面如下:3、选择2,运行界面如下:4.在执行过程中动态暂停。
5 、在进程暂停的情况下,按A 可以增加进程。
6 、退出五、结论这次课设成功采用了“写优先”策略通过输入、排序、就绪等函数实现“读者写者”问题,在这两周时间里我重新翻阅了《C 语言程序设计》、《操作系统》等书,也参考了很多网络资源,对“读者- 写者”问题有了更深的理解,对C 语言和数据结构也有了更好的掌握,使我体会到了理论与实践结合的效果。
这次课程设计对我有很大的帮助,在这过程中还掌握了很多编程的小技巧。
六、源程序#include <stdio.h>#include <stdlib.h>#include "windows.h"#include <conio.h>int mutex=1; //互斥读写的信号量int readcount=0; //用readcount变量来记录读者数struct process{int num; //进程序号char type; //进程类别(判断是读者还是写者)int starttime; //进程开始时间int needtime; //进程读写需要的时间int runtime; //进程在内存中已运行的时间struct process *next;};process *process1=NULL,*process2=NULL,*process3=NULL;void input(){process *p,*q;q=process1=(process *)malloc(sizeof(process)); //在内存中给q分配了一个动态的存储空间int a;FILE *fp; //是声明,声明fp是指针,用来指向FILE类型的对象printf("\t\t\t ****************\n");printf("\t\t\t *1.手动输入进程*\n");printf("\t\t\t *2.文件输入进程*\n");printf("\t\t\t *3.退出*\n");printf("\t\t\t ****************\n");printf("\n请选择序号:");QK:fflush(stdin); //清空输入缓冲区scanf("%d",&a);switch(a){case 1:CS:printf("输入进程数:");int i,j;scanf("%d",&i);if(i==0){printf("无进程,重新输入!\n");goto CS;}for(j=1;i>0;i--,j++){p=(process *)malloc(sizeof(process));q->next=p;printf("第%d个进程:\n",j);printf("进程序号:");scanf("%d",&p->num);printf("\n");printf("读\\写:");getchar();scanf("%c",&p->type);printf("\n");printf("开始时间:");scanf("%d",&p->starttime);printf("\n");printf("读写时间:");scanf("%d",&p->needtime);printf("\n");p->runtime=0;q=q->next;p->next=NULL;}p=process1;p->next=NULL;free(p);break;case 2:if((fp=fopen("d:\\123.txt","r"))==NULL){printf("文件打开失败!\n");exit(0);}while(!(feof(fp))){p=(process *)malloc(sizeof(process));q->next=p;fscanf(fp,"%d %c %d %d",&p->num,&p->type,&p->starttime,&p->needtime);p->runtime=0;q=q->next;p->next=NULL;}fclose(fp);p=process1;p->next=NULL;free(p);break;case 3:exit(0);default :printf("输入错误,重新输入:");goto QK;}}void ready(int i) //每次时间片开始时先将需要进入就绪队列的进程用ready()函数拉入就绪队列{process *p,*q,*j,*k;p=process1;q=process2;int t=0;if(process2==NULL){q=process2=(process *)malloc(sizeof(process));q->next=NULL;t=1;}j=(process *)malloc(sizeof(process));j->next=process1;while(p!=NULL){if(p->starttime==i){k=j;while(k->next!=p){k=k->next;}//比如i=1,这个作用就是寻找所有开始时间等于1的进程k->next=p->next;q->next=p;q=q->next;p=p->next;q->next=NULL;//找到之后插入链表}else{p=p->next;}}process1=j->next;j->next=NULL;free(j);if(t==1){p=process2;process2=process2->next;p->next=NULL;free(p);}}int wait(int &a){if(a<=0){return 0;}a--;return 1;}void signal(int &a){a++;}void Reader(){process *p;int t=0;p=process3;if(process3==NULL){p=process3=(process *)malloc(sizeof(process));p->next=NULL;t=1;}if(readcount>0){p->next=process2;process2=process2->next;p=p->next;p->next=NULL;readcount++;}//读者就开始读if((readcount==0)&&(wait(mutex)==1)) {p->next=process2;process2=process2->next;p=p->next;p->next=NULL;readcount++;}//写者开始写if(t==1){p=process3;process3=process3->next;p->next=NULL;free(p);}}void Writer(){if((wait(mutex)==1)&&(process3==NULL)) {process3=process2;process2=process2->next;process3->next=NULL;}}void sort(){process *p,*q,*j,*k;j=p=(process *)malloc(sizeof(process));p->next=NULL;k=q=(process *)malloc(sizeof(process));q->next=NULL;while(process2!=NULL){if((process2->type=='w')||(process2->type=='W')) {p->next=process2;process2=process2->next;p=p->next;p->next=NULL;}else{q->next=process2;process2=process2->next;q=q->next;q->next=NULL;}}process2=j->next;j->next=NULL;free(j);q=k->next;k->next=NULL;free(k);if(process2!=NULL){p->next=q;}//如果写者不为空,就让写者先进行elseprocess2=q;//不然读者进行}void add(int i){process *p,*q;int a;p=process1;q=(process *)malloc(sizeof(process));printf("进程序号:");scanf("%d",&q->num);printf("\n");printf("读\\写:");fflush(stdin);scanf("%c",&q->type);printf("\n");printf("开始时间:");scanf("%d",&a);q->starttime=a+i;printf("\n");printf("读写时间:");scanf("%d",&q->needtime);q->runtime=0;q->next=NULL;if(process1!=NULL){while(p->next!=NULL)p=p->next;p->next=q;//q是尾结点}elseprocess1=q;//把q中的信息赋值给process1 }void main(){system("color 1a");printf("\t\t---------------------------------------\n");printf("\t\t\t*写优先的读者-写者问题*\n");printf("\t\t---------------------------------------\n\n");int i=0;process *p,*q;//定义两个指向process的指针变量input();printf("\n以下输出各时间片进程状态\n");printf("<运行时如需暂停请输入P>\n");Sleep(1000);while((process1!=NULL)||(process2!=NULL)||(process3!=NULL)) {i++;if(process1!=NULL)ready(i);sort();if(process2!=NULL)while((process2->type=='r')||(process2->type=='R')){Reader();if(process3!=NULL)if((process3->type=='w')||(process3->type=='W'))break;if(process2==NULL)break;}if(process2!=NULL)if((process2->type=='w')||(process2->type=='W')) {Writer();}p=process3;while(p!=NULL){p->runtime++;p=p->next;}printf("\n时间%d :\n",i);printf("\t正执行进程: ");p=process3;if(p==NULL)printf("<空>");elsewhile(p!=NULL){printf("%d ",p->num);p=p->next;}printf("\n\t就绪队列: ");p=process2;if(p==NULL)printf("<空>");elsewhile(p!=NULL){printf("%d ",p->num);p=p->next;}printf("\n");p=q=(process *)malloc(sizeof(process)); p->next=NULL;while(process3!=NULL){if(process3->needtime!=process3->runtime){p->next=process3;p=p->next;}else{if((process3->type=='r')||(process3->type=='R')){readcount--;if(readcount==0)signal(mutex);}elsesignal(mutex);}process3=process3->next;p->next=NULL;}process3=q->next;q->next=NULL;free(q);Sleep(2000);if(kbhit()==1) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0{char ch;ch=getch();if((ch=='p')||(ch=='P')){printf("\n已暂停,继续请按P\n");printf("如需添加进程请按A\n");QK:fflush(stdin);ch=getchar();if((ch=='A')||(ch=='a')){add(i);printf("添加完成!\n");}fflush(stdin);{采用“写优先”策略的“读者-写者”问题while(1)if((ch=='P')||(ch=='p'))break;elsegoto QK;}}}}printf("\n\n所有进程执行完毕\n");system("pause");system("cls");main();}- 29 -。