QQ泡沫乐园 · 免费提供游戏辅助,破解软件,活动资讯,喜欢记得收藏哦!
综合软件_线报活动_游戏辅助_最新电影_最优质的的辅助分享平台

2017年上海事业单位医疗招聘考试操作系统课程设计报告

网络 2023-02-11 15:05

操作系统课程设计报告目录 PAGE \* MERGEFORMAT 目录TOC \o "1-3" \t "" \h \z \u HYPERLINK \l "_Toc376250934" 第1章 实验目的和实验要求 PAGEREF _Toc376250934 \h 1 HYPERLINK \l "_Toc376250935" 1.1 实验目的 PAGEREF _Toc376250935 \h 1 HYPERLINK \l "_Toc376250936" 1.2 实验要求 PAGEREF _Toc376250936 \h 1 HYPERLINK \l "_Toc376250937" 1.3 课程设计题目 PAGEREF _Toc376250937 \h 1 HYPERLINK \l "_Toc376250938" 第2章 实验内容 PAGEREF _Toc376250938 \h 2 HYPERLINK \l "_Toc376250939" 2.1题目剖析 PAGEREF _Toc376250939 \h 2 HYPERLINK \l "_Toc376250940" 2.1.1 问题的描述 PAGEREF _Toc376250940 \h 2 HYPERLINK \l "_Toc376250941" 2.1.2 问题的解决方式 PAGEREF _Toc376250941 \h 2 HYPERLINK \l "_Toc376250942" 2.2 算法剖析 PAGEREF _Toc376250942 \h 3 HYPERLINK \l "_Toc376250943" 2.2.1 读者优先算法剖析 PAGEREF _Toc376250943 \h 3 HYPERLINK \l "_Toc376250944" 2.2.2 写者优先算法剖析 PAGEREF _Toc376250944 \h 8 HYPERLINK \l "_Toc376250945" 2.2.3 无优先算法剖析 PAGEREF _Toc376250945 \h 11 HYPERLINK \l "_Toc376250946" 2.3 函数设计 PAGEREF _Toc376250946 \h 13 HYPERLINK \l "_Toc376250947" 第3章 程序实现 PAGEREF _Toc376250947 \h 15 HYPERLINK \l "_Toc376250948" 3.1 程序功能及界面设计 PAGEREF _Toc376250948 \h 15 HYPERLINK \l "_Toc376250949" 3.2 实现程序流程 PAGEREF _Toc376250949 \h 15 HYPERLINK \l "_Toc376250950" 3.2.1 读者优先算法实现 PAGEREF _Toc376250950 \h 15 HYPERLINK \l "_Toc376250951" 3.2.2 写者优先算法实现 PAGEREF _Toc376250951 \h 16 HYPERLINK \l "_Toc376250952" 3.2.3 无优先算法实现 PAGEREF _Toc376250952 \h 17 HYPERLINK \l "_Toc376250953" 3.3 程序流程图 PAGEREF _Toc376250953 \h 18 HYPERLINK \l "_Toc376250954" 3.3.1 读者优先算法流程图 PAGEREF _Toc376250954 \h 18 HYPERLINK \l "_Toc376250955" 3.3.2 写者优先算法流程图 PAGEREF _Toc376250955 \h 18 HYPERLINK \l "_Toc376250956" 3.3.3 无优先算法流程图 PAGEREF _Toc376250956 \h 19 HYPERLINK \l "_Toc376250957" 心得感受 PAGEREF _Toc376250957 \h 21 HYPERLINK \l "_Toc376250958" 参考文献 PAGEREF _Toc376250958 \h 22 HYPERLINK \l "_Toc376250959" 附录1 源代码 PAGEREF _Toc376250959 \h 23第1章 实验目的和实验要求 PAGE \* MERGEFORMAT 28第1章 实验目的和实验要求1.1 实验目的理解临界区和进程互斥的概念,掌握用信号量和PV操作实现进程互斥的技巧。

1.2 实验要求在windows或则linux环境下编撰一个控制台应用程序,该程序运行时能创建N个线程,其中既有读者线程又有写者线程,它们根据事先设计好的测试数据进行读写操作。请用信号量和PV操作实现读者/写者问题。1.3 课程设计题目本课程设计共包括3个题目,内容覆盖了操作系统原理的关键知识点,包括进程调度、内存管理、进程同步、死锁、进程通信、文件系统及嵌入式操作系统。题目1:进程调度算法。模拟在单处理器情况下的进程调度,目的是加深对进程调度工作的理解,掌握不同调度算法的优缺点题目2:动态异长分区的储存分配与回收算法。编写一个程序,模拟操作系统对动态异长分区的储存分配与回收算法。题目3:读者/写者问题与进程同步。理解临界区和进程互斥的概念,掌握用信号量和PV操作实现进程互斥的技巧。要求中学生用信号量和PV操作实现读者/写者问题的读者优先算法、写者优先算法和无优先算法。我们小组选择题目3,即读者/写者问题与进程同步。以下是该题目的实验报告。第2章 实验内容第2章 实验内容2.1题目剖析2.1.1 问题的描述有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者寻址的一块空间,甚至可以是一组处理器寄存器。

有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。以下假定共享数据区是文件。这些读者和写者对数据区的操作必须满足以下条件:读—读容许;读—写互斥;写—写互斥。这些条件具体来说就是:(1)任意多的读进程可以同时读这个文件;(2)一次只容许一个写进程往文件中写;(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;(4)写进程执行写操作前,应让已有的写者或读者全部退出。这说明当有读者在读文件时不准许写者写文件。2.1.2 问题的解决方式(1)读者优先不仅上述四个规则外,还降低读者优先的规定,当有读者在读文件时,对随即抵达的读者和写者,要首先满足读者,阻塞写者。这说明只要有一个读者活跃,那么随即而至的读者都将被准许访问文件,从而造成写者长时间等待,甚至有可能出现写者被冻死的情况。(2)写者优先不仅上述四个规则外,还降低写者优先的规定,即当有读者和写者同时等待时,首先满足写者。当一个写者申明想写文件时,不容许新的读者再访问文件。(3)无优先不仅上述四个规则外,不再规定读写的优先权,谁先等待谁就先使用文件。2.2 算法剖析2.2.1 读者优先算法剖析对于陆续抵达的一批读者,并不是每位读者都须要执行P(r_w_w)和V(r_w_w)。

在这批读者中,只有最先抵达的读者才须要执行P(r_w_w),与写者竞争对文件的访问权,若执行P(r_w_w)成功则获得了文件的访问权,其他的读者可直接访问文件;同理,只有最后退出临界区的读者须要执行V(r_w_w)来归还文件访问权。为了记录正在读文件的一批读者的数目,需要设置一个整型变量read_count,每一个读者抵达时都要将read_count加1,退出时都要将read_count减1。由于只要有一个读者在读文件,便不容许写者写文件,所以,仅当read_count=0时,即尚无读者在读文件时,读者才须要执行P(r_w_w)操作。若P(r_w_w)操作成功,读者便可去读文件,相应地,read_count+1。同理,仅当在执行了read_count减1操作后其值为0时,才须要执行V(r_w_w)操作,以便让写者写文件。又由于read_count是一个可被多个读者访问的临界资源,所以应当为它设置一个互斥信号量h_mutex_read_count。每个读者在访问read_count之前执行P(h_mutex_read_count),之后执行V(h_mutex_read_count)。通过上述剖析得到图2-1所示的算法描述,其中的数字表示句子对应的行号。

读者写者问题流程图_写调查报告注意的问题_读者丛书编辑组《读者》·读者幽默^^^《读者》·隽永小品^^

01 semaphore r_w_w=1;02 semaphore h_mutex_read_count=1;03 int read_count=0; 04 reader(){05 P(h_mutex_read_count);06 if(read_count==0) P(r_w_w);07 read_count++;08 V(h_mutex_read_count);09 读文件;10 P(h_mutex_read_count);11 read_count--;12 if(read_count==0) V(r_w_w);13 V(h_mutex_read_count);14 }1516 writer(){17 P(r_w_w);18 写文件;19 V(r_w_w);20 }图2-1 读者优先算法下边对该算法的调度疗效进行剖析。假设最初没有进程在访问文件。过了一会,就会有很多读者和写者抵达。对它们可能有两种调度情形。情形1 最先调度写者写者执行P(r_w_w)操作成功,将r_w_w的值变为0,获得文件的访问权;其它的写者执行P(r_w_w)将r_w_w的值变为正数,从而阻塞在信号量r_w_w上;第一个读者执行P(h_mutex_read_count)成功,将信号量h_mutex_read_count的值变为0,然后判定read_count是0,所以执行P(r_w_w),将r_w_w的值减1后一直为正数因而阻塞在信号量r_w_w上,其它的读者执行P(h_mutex_read_count)将信号量h_mutex_read_count的值变为正数,从而阻塞在信号量h_mutex_read_count上。

例如,对于恳求序列w1,w2,r1,w3,r2,r3,我们用图表形象地描画进程的活动,图表中包括读者计数器的值、信号量h_mutex_read_count和r_w_w的值和队列以及访问文件的进程。①初始状态。没有进程使用文件,计数器read_count的值是0,信号量h_mutex_read_count和r_w_w的值都是1,队列都是空,参见图2-2;②w1恳求写文件,所以执行句子17,将信号量r_w_w的值减1后弄成0,w1获得文件使用权,执行句子18,开始写文件,参见图2-3;③在w1仍未写完时,w2提出写恳求,所以执行句子17,将信号量r_w_w的值减1后弄成负1,w2被阻塞在信号量r_w_w上,参见图2-4;④同时r1提出读恳求,所以执行句子5,将信号量h_mutex_read_count的值减1后弄成0,接着执行句子6,判断read_count的值是0,所以执行P(r_w_w),将信号量r_w_w的值减1后弄成-2,r1被阻塞在信号量r_w_w上,参见图2-5;①初始状态read_count=0h_mutex_read_count1NULLr_w_w1NULL访问文件者:无图2-2②w1恳求read_count=0h_mutex_read_count1NULLr_w_w0NULL访问文件者:w1图2-3⑤同时w3提出写恳求,所以执行句子17,将信号量r_w_w的值减1后弄成-3,w3被阻塞在信号量r_w_w上,参见图2-6;⑥同时r2提出读恳求,所以执行句子5,将信号量h_mutex_read_count的值减1后弄成-1,r2被阻塞在信号量h_mutex_read_count上,参见图2-7;③w2恳求read_count=0h_mutex_read_count1NULLr_w_w-1 w2访问文件者:w1图2-4④r1恳求read_count=0h_mutex_read_count0NULLr_w_w-2 w2,r1访问文件者:w1图2-5⑦同时r3提出读恳求,所以执行句子5,将信号量h_mutex_read_count的值减1后弄成-2,r3被阻塞在信号量h_mutex_read_count上,参见图2-8;⑧w1写完文件,执行句子19,将信号量r_w_w的值加1后弄成-2,并唤起w2,w2接着执行句子18,开始写文件,参见图2-9;⑨w2写完文件,执行句子19,将信号量r_w_w的值加1后弄成-1,并唤起r1,r1接着执行句子7,将read_count的值加1后弄成1,执行句子8,将信号量h_mutex_read_count的值加1后弄成-1,并唤起r2,r1执行句子9,开始读⑥r2恳求read_count=0h_mutex_read_count-1 r2r_w_w-3 w2,r1,w3访问文件者:w1图2-7⑤w3恳求read_count=0h_mutex_read_count0NULLr_w_w-3 w2,r1,w3访问文件者:w1图2-6文件;被唤起的r2执行句子6,判断read_count的值不是0,所以执行句子7,将read_count的值加1后弄成2,执行句子8,将信号量h_mutex_read_count的值加1后弄成0,并唤起r3,r2执行句子9,开始读文件;被唤起的r3执行句子6,判断read_count的值不是0,所以执行句子7,将read_count的值加1后弄成3,执行句子8,将信号量h_mutex_read_count的值加1后弄成1,r3执行句子9,开始读文件。

这样三个读者同时读文件,参见图2-10;⑩当r1、r2和r3读完文件时,都执行句子10~14,并由最后一个执行句子10~14的读者执行V(r_w_w),将信号量r_w_w的值加1后弄成0,并唤起w3,w3接着执行句子18,开始写文件,参见图2-11;当w3写完文件时,执行句子19,将信号量r_w_w的值加1后弄成1,回到初始状态。可见,对于恳求序列w1,w2,r1,w3,r2,r3,实际访问文件的次序是w1,w2,r1,r2,r3,w3。虽然w3比r2、r3先提出恳求,但是因为在此之前早已有r1在读文件,所以优先响应读者r2、r3,阻塞写者w3。如果在w3以后不断有新的读者抵达,则w3将仍然被阻塞,直至被冻死。⑦r3恳求read_count=0h_mutex_read_count-2 r2,r3r_w_w-3 w2,r1,w3访问文件者:w1图2-8⑧w1结束,唤醒w2read_count=0h_mutex_read_count-2 r2,r3r_w_w-2 r1,w3访问文件者:w2图2-9⑩r1,r2,r3结束,唤醒w3read_count=0h_mutex_read_count1NULL r_w_w0NULL 访问文件者: w3图2-11⑨w2结束,唤醒r1,r1唤起r2,r2唤起r3read_count=3h_mutex_read_count1NULL r_w_w-1 w3访问文件者:r1,r2,r3图2-10情形2 最先调度读者第一个读者执行P(h_mutex_read_count)成功,将信号量h_mutex_read_count的值变为0,接着该读者判定read_count是0,所以执行P(r_w_w)操作成功,获得文件的访问权,将r_w_w的值变为0,然后将read_count弄成1,执行V(h_mutex_read_count),之后开始读文件;随后的写者执行P(r_w_w)将r_w_w的值变为正数,从而阻塞在信号量r_w_w上;其它的读者执行P(h_mutex_read_count)成功,判断read_count不是0,所以直接将read_count的值再加1,执行V(h_mutex_read_count),之后开始读文件。

读者写者问题流程图_读者丛书编辑组《读者》·读者幽默^^^《读者》·隽永小品^^_写调查报告注意的问题

可见多个读者可以同时读文件,并在读文件时阻塞写者。2.2.2 写者优先算法剖析通过降低信号量并更改上述程序可以得到写者优先算法。为了实现写者优先算法,需要将写者和读者分开排队,并且第一个读者和其它读者也要分开排队。这样就须要三个队列,一个是写者排队的地方,另一个是第一个读者排队的地方,第三个是其它读者排队的地方。相应地须要设置三个信号量,r_w_w、first_reader_wait和reader_wait。当一个写者申明想写文件时,可以让新的读者中的第一个到first_reader_wait上排队等待;当有读者阻塞在first_reader_wait上时,让其它读者阻塞在reader_wait上;当有一个写者在写文件时,其它写者到r_w_w上排队。只要有活跃的写者或则写者队列不为空,则阻塞新抵达的读者。为了记录早已发出申明的写者数目,需要设置一个整数writ_count,以表示申明要写文件的写者数量。由于只要有一个写者抵达,就不容许读者去读,因此仅当writ_count=0,表示无写者申明写时,写者才须要执行P(first_reader_wait)操作,若操作成功,写者便可以执行P(r_w_w)去竞争写文件权力。

其它写者不需要再向读者申明,可以直接执行P(r_w_w)去竞争写文件权力。同理仅当写者在执行writ_count减1操作后其值为0时,才须要执行V(first_reader_wait)操作,以便唤起第一个被阻塞的读者去读文件。又由于writ_count是一个可被多个写??访问的临界资源,所以,应该为它设置一个互斥信号量writer_mutex。通过上述剖析得到图2-13的算法描述。下面对该算法的调度疗效进行剖析。假设最初没有进程在访问文件。过了一会,就会有很多读者和写者抵达。对它们可能有两种调度情形。情形1 最先调度写者写者执行P(writ_count_mutex),将writ_count_mutex的值变为0,并判定writ_count是0,从而执行P(first_reader_wait),将first_reader_wait的值变为0,成功地向读者申明了写访问意图,接着将writ_count变为1,执行V(writ_count_mutex),将writ_count_mutex的值变为1。然后写者执行P(r_w_w)操作,将r_w_w的值变为0,成功地获得了文件的写访问权力。第一个写者开始写文件;其它的写者执行P(writ_count_mutex),判断writ_count不是0,所以直接将writ_count加1,执行V(writ_count_mutex),然后执行P(r_w_w)操作,将r_w_w的值变为正数,写者依次被阻塞在信号量r_w_w上;第一个读者执行P(reader_wait),将reader_wait的值变为0,接着执行P(first_reader_wait),将first_reader_wait的值变为负1,阻塞在信号量first_reader_wait上;其它读者执行P(reader_wait),将reader_wait的值变为正数,依次阻塞在reader_wait上。

当第一个写者写完文件后,执行V(r_w_w),唤醒一个写者并将写者计数器writ_count减1,被唤起的写者可以写文件,写完后执行V(r_w_w),唤醒下一个写者并将写者计数器writ_count减1,直到最后一个写者将writ_count减为0,才执行V(first_reader_wait)唤醒第一个阻塞的读者。被唤起的读者执行P(h_mutex_read_count),然后判定read_count是0,从而执行 P(r_w_w),由于最后一个写者写完文件后,r_w_w的值早已还原为1,所以被唤起的读者执行P(r_w_w)成功,将r_w_w的值变为0,获得文件的读访问权。接着将read_count的值加到1,执行V(h_mutex_read_count),再执行V(reader_wait),唤醒第二个等待的读者,第一个读者执行V(first_reader_wait),将first_reader_wait的值还原到1。第一个读者可以读文件了。若没有新的写者抵达,则第二个读者执行P(first_reader_wait)成功,执行P(h_mutex_read_count)并判定read_count不是0,将read_count加到2,执行V(h_mutex_read_count),再执行V(reader_wait)唤醒第三个读者,再执行V(first_reader_wait),第二个读者也可以读文件了。

写调查报告注意的问题_读者写者问题流程图_读者丛书编辑组《读者》·读者幽默^^^《读者》·隽永小品^^

01 semaphore r_w_w=1;02 semaphore reader_wait=1;03 semaphore first_reader_wait=1;04 semaphore h_mutex_read_count=1;05 semaphore writ_count_mutex=1;06 int writ_count=0;07 int read_count=0; 08 reader(){09 P(reader_wait);10 P(first_reader_wait);11 P(h_mutex_read_count);12 if(read_count==0) P(r_w_w);13 read_count++;14 V(h_mutex_read_count);15 V(reader_wait);16 V(first_reader_wait);17 读文件;18 P(h_mutex_read_count);19 read_count--;20 if(read_count==0) V(r_w_w);21 V(h_mutex_read_count);22 }23 writer(){24 P(writ_count_mutex);25 if(writ_count==0) P(first_reader_wait);26 writ_count++;27 V(writ_count_mutex);28 P(r_w_w);29 写文件;30 V(r_w_w);31 P(writ_count_mutex);32 writ_count--;33 if(writ_count==0) V(first_reader_wait);34 V(writ_count_mutex);35 }图2-12 写者优先算法情形2 最先调度读者第一个读者执行P(reader_wait),将reader_wait的值变为0,执行P(first_reader_wait),将first_reader_wait的值变为0,向写者申明有读者要读文件,接着执行P(h_mutex_read_count),并判定read_count是0所以执行P(r_w_w),将r_w_w的值变为0,成功地获得了文件的读访问权,将读者计数器read_count加到1,执行V(h_mutex_read_count),V(reader_wait),V(first_reader_wait),将reader_wait和first_reader_wait的值依次还原为1。

之后,第一个读者开始读文件。若在第一个读者读文件的过程中没有写者抵达,则其它读者可以同时读文件;若在读者读文件时,有写者抵达,则第一个抵达的写者执行P(writ_count_mutex),将writ_count_mutex的值变为0,并判定writ_count是0,从而执行P(first_reader_wait),将first_reader_wait的值变为0,成功地向读者申明了写访问意图,接着将writ_count变为1,执行V(writ_count_mutex),将writ_count_mutex的值变为1。然后写者执行P(r_w_w)操作,(由于有读者在读文件,所以)将r_w_w的值变为负1,写者被阻塞在信号量r_w_w上;当在读文件的所有读者都读完文件后,由最后一个退出的读者执行V(r_w_w)唤醒写者。第一个写者开始写文件。2.2.3 无优先算法剖析不仅在读者优先时须要的信号量r_w_w和h_mutex_read_count之外,还须要设置一个信号量wait供读者和写者排队。读者和写者都排在wait队列上。若有读者在读文件,则第一个写者阻塞在r_w_w上,其它的写者和读者阻塞在wait上;若有一个写者在写文件,则其它写者和读者都阻塞在wait上。

无优先的算法描述如图2-13所示。01 semaphore r_w_w=1;02 semaphore wait=1;03 semaphore h_mutex_read_count=1;04 int read_count=0; 05 reader(){06 P(wait);07 P(h_mutex_read_count);08 if(read_count==0) P(r_w_w);09 read_count++;10 V(h_mutex_read_count);11 V(wait);12 读文件;13 P(h_mutex_read_count);14 read_count--;15 if(read_count==0) V(r_w_w);16 V(h_mutex_read_count);17 }18 writer(){19 P(wait);20 P(r_w_w);21 写文件;22 V(r_w_w);23 V(wait);24 }图2-13 无优先算法下边对该算法的调度疗效进行剖析。

读者丛书编辑组《读者》·读者幽默^^^《读者》·隽永小品^^_写调查报告注意的问题_读者写者问题流程图

最初没有进程在访问文件。过了一会,就会有很多读者和写者抵达。对它们可能有两种调度情形。情形1 最先调度写者写者执行P(wait)操作成功,将wait的值变为0,再执行P(r_w_w)操作成功,将r_w_w的值变为0,获得文件的访问权,写者可以写文件了。其它的写者或则读者执行P(wait)操作,将wait的值变为正数,从而依次阻塞在信号量wait上;第一个写者写完文件后,执行V(r_w_w),将r_w_w的值还原为1,再执行V(wait)唤醒排在wait队列最前面的一个进程,可能是读者,也可能是写者。情形2 最先调度读者第一个读者执行P(wait)操作成功,将wait的值变为0,再执行P(h_mutex_read_count)成功,将信号量h_mutex_read_count的值变为0,接着该读者判定read_count是0,所以执行P(r_w_w)操作成功,获得文件的访问权,将r_w_w的值变为0,然后将read_count弄成1,执行V(h_mutex_read_count),V(wait),将信号量h_mutex_read_count和wait的值还原为1,之后开始读文件;若随即抵达的一直是读者,则这种读者将read_count各加1以后也开始读文件;若随即抵达的是写者,则写者执行P(wait)操作成功,将wait的值变为0,再执行P(r_w_w)操作将r_w_w的值变为正数,从而阻塞在r_w_w上。

这促使在它以后抵达的读者和写者陆续阻塞在wait上。当第一批读者读完文件后,由最后一个退出的读者执行执行V(r_w_w),从而唤起第一个被阻塞的写者。 2.3 函数设计实现读者/写者问题的源程序名称是reader_and_writer.cpp。该程序共包括10个函数。这些函数可以分成4组。各组包含的函数及其功能如表2-1。表2-1 函数功能阐述组别包括函数函数功能一main()显示主菜单,接收用户的选择并执行相应的功能。二RF_reader_thread()RF_writer_thread()reader_first()读者优先算法的读者线程函数读者优先算法的写者线程函数读者优先算法的初始化函数:创建10个线程并等待它们结束三WF_reader_thread()WF_writer_thread()writer_first()写者优先算法的读者线程函数写者优先算法的写者线程函数写者优先算法的初始化函数:创建10个线程并等待它们结束四FIFO_reader_thread()FIFO_writer_thread()first_come_first_serverd()无优先算法的读者线程函数无者优先算法???写者线程函数无者优先算法的初始化函数:创建10个线程并等待它们结束程序开始部份定义了宏MAX_THREAD,表示程序中创建的线程数。

还定义了测试数据的结构体TEST_INFO,该结构体包含三个数据项:线程名称;提出恳求的时刻;操作持续时间。接着定义了全局变量,这些全局变量的作用如下:数组test_data保存了10个线程的测试数据;整数read_count记录一段时间内同时对文件进行读操作的线程数;整数write_count记录一段时间内提出写操作恳求的线程数,该整数只在写者优先算法中使用;CS_DATA是临界区变量,用来保护文件,实现对文件的读—写互斥和写—写互斥(相当于算法描述中的r_w_w);互斥体h_mutex_read_count拿来保护整数read_count,以保证多个读者对read_count的互斥访问;互斥体h_mutex_write_count拿来保护整数write_count,以保证多个写者对write_count的互斥访问,该互斥体只在写者优先算法中使用;互斥体h_mutex_first_reader_wait和h_mutex_reader_wait只在写者优先算法中使用,当有写者在写文件时,提出读恳求的第一个读者阻塞在h_mutex_first_reader_wait上,其余的读者阻塞在h_mutex_reader_wait上;互斥体h_mutex_wait只在无优先算法中使用,当文件被使用时,后继的读恳求和写恳求依次阻塞在h_mutex_wait上。

读者写者问题流程图_读者丛书编辑组《读者》·读者幽默^^^《读者》·隽永小品^^_写调查报告注意的问题

第3章 程序实现第3章 程序实现3.1 程序功能及界面设计该程序采用简单的控制台应用程序界面,在主界面上显示程序的功能。该程序的功能如下:演示读者优先算法;演示写者优先算法;演示无优先算法;退出。3.2 实现程序流程3.2.1 读者优先算法实现对于陆续抵达的一批读者,并不是每位读者都须要执行P(r_w_w)和V(r_w_w)。在这批读者中,只有最先抵达的读者才须要执行P(r_w_w),与写者竞争对文件的访问权,若执行P(r_w_w)成功则获得了文件的访问权,其他的读者可直接访问文件;同理,只有最后退出临界区的读者须要执行V(r_w_w)来归还文件访问权。为了记录正在读文件的一批读者的数目,需要设置一个整型变量read_count,每一个读者抵达时都要将read_count加1,退出时都要将read_count减1。由于只要有一个读者在读文件,便不容许写者写文件,所以,仅当read_count=0时,即尚无读者在读文件时,读者才须要执行P(r_w_w)操作。若P(r_w_w)操作成功,读者便可去读文件,相应地,read_count+1。同理,仅当在执行了read_count减1操作后其值为0时,才须要执行V(r_w_w)操作,以便让写者写文件。

又由于read_count是一个可被多个读者访问的临界资源,所以应当为它设置一个互斥信号量h_mutex_read_count。每个读者在访问read_count之前执行P(h_mutex_read_count),之后执行V(h_mutex_read_count)。读优先操作结果截图如下图3-1:图3-1 读优先操作截图3.2.2 写者优先算法实现为了实现写者优先算法,需要将写者和读者分开排队,并且第一个读者和其它读者也要分开排队。这样就须要三个队列,一个是写者排队的地方,另一个是第一个读者排队的地方,第三个是其它读者排队的地方。相应地须要设置三个信号量,r_w_w、first_reader_wait和reader_wait。当一个写者申明想写文件时,可以让新的读者中的第一个到first_reader_wait上排队等待;当有读者阻塞在first_reader_wait上时,让其它读者阻塞在reader_wait上;当有一个写者在写文件时,其它写者到r_w_w上排队。只要有活跃的写者或则写者队列不为空,则阻塞新抵达的读者。为了记录早已发出申明的写者数目,需要设置一个整数writ_count,以表示申明要写文件的写者数量。

由于只要有一个写者抵达,就不容许读者去读,因此仅当writ_count=0,表示无写者申明写时,写者才须要执行P(first_reader_wait)操作,若操作成功,写者便可以执行P(r_w_w)去竞争写文件权力。其它写者不需要再向读者申明,可以直接执行P(r_w_w)去竞争写文件权力。同理仅当写者在执行writ_count减1操作后其值为0时,才须要执行V(first_reader_wait)操作,以便唤起第一个被阻塞的读者去读文件。又由于writ_count是一个可被多个写者访问的临界资源,所以,应该为它设置一个互斥信号量writer_mutex。写优先操作结果截图如下图 3-2:图3-2 写优先操作截图3.2.3 无优先算法实现除了须要的信号量r_w_w和h_mutex_read_count之外,还须要设置一个信号量wait供读者和写者排队。读者和写者都排在wait队列上。若有读者在读文件,则第一个写者阻塞在r_w_w上,其它的写者和读者阻塞在wait上;若有一个写者在写文件,则其它写者和读者都阻塞在wait上。无优先操作结果截图如下图3-3:图3-3 无优先操作截图3.3 程序流程图3.3.1 读者优先算法流程图按照定义的函数名称和功能画读者优先算法的函数流程图如下图3-4所示:图3-4 读者优先算法函数流程图3.3.2 写者优先算法流程图按照定义的函数名称和功能画写者优先算法的函数流程图如下图3-5所示:图3-5 写者优先算法函数流程图3.3.3 无优先算法流程图按照定义的函数名称和功能画无优先算法的函数流程图如下图3-6所示:图3-6 无优先算法函数流程图心得感受心得感受这一次课程设计,我们组完成了题目3即“读者-写者问题与进程同步”问题,更加系统地理解和把握了临界区和进程互斥的概念把握用信号量和PV操作实现进程互斥的技巧。

要求中学生用信号量和PV操作实现读者/写者问题的读者优先算法、写者优先算法和无优先算法。经过读者写者问题的编撰,我对同步机构应用有了深入的了解,懂得了运用信号量实现进程间的互斥,实现了不让共享资源同时更改。用信号量上的谓词操作使临界段问题的解决比较简单明了了。读者写者问题的编撰,花的时间好多,也学到好多东西。了解在支持多道程序的并发操作系统设计中,如何解决资源共享时进程间的同步与互斥的信号量机制。课程设计提升了我们对所学知识的综合应用能力,全面检测并把握所学的内容,培养独立思索、刻苦钻研的精神,在剖析问题、解决问题的过程中,更是获得一种成功的喜悦,进而降低学习和应用的兴趣。同时也要督促自己在学习的过程中不断的建立自我,加强自己的动手操作能力,培养我的独立思考的那个思维方法。总之,这一次课程设计我们深刻的理解操作系统,而且锻练了实际编程能力和思维方法,虽然有难度过程中遇见好多问题,经过深刻细致的理解问题、剖析问题、解决问题使我们深刻的认识理解了读者/写者问题与进程同步。参考文献参考文献[1] 刘肄卓 著.操作系统实验教程113301-113302[2] 百度百科 /[3] 左嘉庆 等著.计算机操作系统教程(第三版). 北京:高等教育出版社,2010.7附表1 源代码附表1 源代码 #include #include #include #include #include #include #define MAX_THREAD 10//待测试的线程数typedef struct{//表示测试数据格式char thread_name[3];//线程名unsigned int require_moment; //恳求操作时刻unsigned int persist_time;//操作持续时间}TEST_INFO;TEST_INFO test_data[MAX_THREAD]={ //测试数据表{"r1",0,15},// r表示读者线程{"r2",1, 15},//w表示写者线程{"w1",3,3},{"r3",4, 2},{"w2",5,6},{"w3",6,10},{"r4",7,8},{"r5",9,2},{"w4",10,18},{"w5",12,2}};int read_count=0;//记录正在读文件的读者数int write_count=0;//在写者优先算法中记录申明要写文件的写者数CRITICAL_SECTION CS_DATA;//用于保护文件的临界区变量HANDLE h_mutex_read_count=CreateMutex(NULL,FALSE,"mutex_read_count");//读者计数器互斥体HANDLE h_mutex_write_count=CreateMutex(NULL,FALSE,"mutex_write_count");//写者计数器互斥体HANDLE h_mutex_reader_wait=CreateMutex(NULL,FALSE,"mutex_reader_wait");//在写者优先算法中用于阻塞读者的互斥体HANDLE h_mutex_first_reader_wait=CreateMutex(NULL,FALSE,"mutex_first_reader_wait");//在写者优先算法中用于阻塞第一个读者的互斥体HANDLE h_mutex_wait=CreateMutex(NULL,FALSE,"mutex_wait");//无优先时用于阻塞读者和写者的互斥体//读者优先时的读者线程void RF_reader_thread(void *data){char thread_name[3];//存放线程名称strcpy(thread_name,((TEST_INFO *)data)->thread_name);Sleep(((TEST_INFO *)data)->require_moment*1000);WaitForSingleObject(h_mutex_read_count,-1);//申请步入关于读者计数器的临界区相当于P操作read_count++;if(read_count==1)EnterCriticalSection(&CS_DATA);//申请步入关于文件的临界区相当于P操作ReleaseMutex(h_mutex_read_count);//离开关于读者计数器的临界区相当于V操作printf("%s ",thread_name);Sleep(((TEST_INFO *)data)->persist_time*1000); //用延后相应秒来模拟读文件操作WaitForSingleObject(h_mutex_read_count,-1);read_count--;if(read_count==0)LeaveCriticalSection(&CS_DATA); //离开关于文件的临界区相当于V操作ReleaseMutex(h_mutex_read_count);}//读者优先时的写者线程void RF_writer_thread(void *data){Sleep(((TEST_INFO *)data)->require_moment*1000);EnterCriticalSection(&CS_DATA);printf("%s ",((TEST_INFO *)data)->thread_name);Sleep(((TEST_INFO *)data)->persist_time*1000); //用延后相应秒来模拟写文件操作LeaveCriticalSection(&CS_DATA);}//读者优先时的初始化程序void reader_first(){int i=0;HANDLE h_thread[MAX_THREAD];printf("读优先申请顺序:");for(i=0;ithread_name);Sleep(((TEST_INFO *)data)->require_moment*1000);WaitForSingleObject(h_mutex_wait,-1);WaitForSingleObject(h_mutex_read_count,-1);read_count++;if(read_count==1)EnterCriticalSection(&CS_DATA);ReleaseMutex(h_mutex_read_count);ReleaseMutex(h_mutex_wait);printf("%s ",thread_name);Sleep(((TEST_INFO *)data)->persist_time*1000);WaitForSingleObject(h_mutex_read_count,-1);read_count--;if(read_count==0)LeaveCriticalSection(&CS_DATA);ReleaseMutex(h_mutex_read_count);}//无优先时的写者线程void FIFO_writer_thread(void *data){Sleep(((TEST_INFO *)data)->require_moment*1000);WaitForSingleObject(h_mutex_wait,-1);EnterCriticalSection(&CS_DATA);printf("%s ",((TEST_INFO *)data)->thread_name);Sleep(((TEST_INFO *)data)->persist_time*1000);LeaveCriticalSection(&CS_DATA);ReleaseMutex(h_mutex_wait);}//无优先时的初始化程序void first_come_first_served(){int i=0;HANDLE h_thread[MAX_THREAD];printf("无优先申请顺序:");for(i=0;ithread_name);Sleep(((TEST_INFO *)data)->require_moment*1000);WaitForSingleObject(h_mutex_reader_wait,-1);WaitForSingleObject(h_mutex_first_reader_wait,-1);WaitForSingleObject(h_mutex_read_count,-1);read_count++;if(read_count==1)EnterCriticalSection(&CS_DATA);ReleaseMutex(h_mutex_read_count);ReleaseMutex(h_mutex_first_reader_wait);ReleaseMutex(h_mutex_reader_wait);printf("%s ",thread_name);Sleep(((TEST_INFO *)data)->persist_time*1000);WaitForSingleObject(h_mutex_read_count,-1);read_count--;if(read_count==0)LeaveCriticalSection(&CS_DATA);ReleaseMutex(h_mutex_read_count);}//写者优先时的写者线程void WF_writer_thread(void *data){Sleep(((TEST_INFO *)data)->require_moment*1000);WaitForSingleObject(h_mutex_write_count,-1);if(write_count==0)WaitForSingleObject(h_mutex_first_reader_wait,-1);write_count++;ReleaseMutex(h_mutex_write_count);EnterCriticalSection(&CS_DATA);printf("%s ",((TEST_INFO *)data)->thread_name);Sleep(((TEST_INFO *)data)->persist_time*1000);LeaveCriticalSection(&CS_DATA);WaitForSingleObject(h_mutex_write_count,-1);write_count--;if(write_count==0)ReleaseMutex(h_mutex_first_reader_wait);ReleaseMutex(h_mutex_write_count);}//写者优先时的初始化程序void writer_first(){int i=0;HANDLE h_thread[MAX_THREAD];printf("写优先申请顺序:");for(i=0;i