1.1实验目的 1.2实验要求 1.3课程设计题目 2.1题目剖析 2.1.1问题的描述 2.1.2问题的解决方式 2.2算法剖析 2.2.1读者优先算法剖析 2.2.2写者优先算法剖析 2.2.3无优先算法剖析 112.3 函数设计 153.1 程序功能及界面设计 153.2 实现程序流程 153.2.1 读者优先算法实现 153.2.2 写者优先算法实现 163.2.3 无优先算法实现 173.3 程序流程图 183.3.1 读者优先算法流程图 183.3.2 写者优先算法流程图 183.3.3 无优先算法流程图 19心得感受 21参考文献 22附表1 源代码 实验目的和实验要求1.1 实验目的 理解临界区和进程互斥的概念,掌握用信号量和PV 操作实现进程互斥的方 1.2实验要求 在windows 或者linux 环境下编撰一个控制台应用程序,该程序运行时能创 个线程,其中既有读者线程又有写者线程,它们根据事先设计好的测试数据进行读写操作。请用信号量和PV 操作实现读者/写者问题。 1.3 课程设计题目 本课程设计共包括 个题目,内容覆盖了操作系统原理的关键知识点,包括进程调度、内存管理、进程同步、死锁、进程通信、文件系统及嵌入式操作 系统。
题目1:进程调度算法。模拟在单处理器情况下的进程调度,目的是加深对 进程调度工作的理解,掌握不同调度算法的优缺点 题目2:动态异长分区的储存分配与回收算法。编写一个程序,模拟操作系 统对动态异长分区的储存分配与回收算法。 题目 3:读者/写者问题与进程同步。理解临界区和进程互斥的概念,掌握 用信号量和PV 操作实现进程互斥的技巧。要求中学生用信号量和PV 操作实现读 者/写者问题的读者优先算法、写者优先算法和无优先算法。 我们小组选择题目 3,即读者/写者问题与进程同步。以下是该题目的实验 报告。 实验内容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 由于只要有一个读者在读文件,便不容许写者写文件,所以,仅当read_count=0 时,即尚无读者在读文件时,读者才须要执行 P(r_w_w)操作。
若 P(r_w_w)操作成功,读者便可去读文件,相应地,read_count+1。同理,仅当在 执行了read_count 时,才须要执行V(r_w_w)操作,以便让写者写文件。又由于 read_count 是一个可被多个读者访问的临界资源,所以应 该为它设置一个互斥信号量 h_mutex_read_count。每个读者在访问 read_count 之前执行P(h_mutex_read_count),之后执行V(h_mutex_read_count)。 通过上述剖析得到图 2-1 所示的算法描述,其中的数字表示句子对应的行 01semaphore 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); 16 writer(){ 17 P(r_w_w); 18 写文件; 19 V(r_w_w); 20 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 15图2-1 读者优先算法 下面对该算法的调度疗效进行剖析。
假设最初没有进程在访问文件。过了一会,就会有很多读者和写者抵达。 对它们可能有两种调度情形。 情形1最先调度写者 写者执行P(r_w_w)操作成功,将r_w_w 的值变为0,获得文件的访问权; 其它的写者执行 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 后一直为正数因而阻塞在信号量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 后弄成0,w1 获得文件使用权,执行句子18,开始写文件,参见图2-3; 在w1 尚未写完时,w2 提出写恳求,所以执行句子17,将信号量r_w_w 后弄成负1,w2被阻塞在信号量r_w_w 上,参见图2-4; 同时 r1 提出读恳求,所以执行句子 5,将信号量 h_mutex_read_count 后弄成0,接着执行句子6,判断read_count的值是0,所以执行P(r_w_w), 后弄成-2,r1被阻塞在信号量r_w_w 上,参见图2-5; 同时w3 提出写恳求,所以执行句子17,将信号量r_w_w 成-3,w3被阻塞在信号量r_w_w 上,参见图2-6; 同时 r2 提出读恳求,所以执行句子 5,将信号量 h_mutex_read_count 后弄成-1,r2被阻塞在信号量h_mutex_read_count 上,参见图2-7; 同时 r3 提出读恳求,所以执行句子 5,将信号量 h_mutex_read_count 后弄成-2,r3被阻塞在信号量h_mutex_read_count 上,参见图2-8; w1 写完文件,执行句子19,将信号量r_w_w 后弄成-2,并唤起w2,w2 接着执行句子18,开始写文件,参见图2-9; w2 写完文件,执行句子19,将信号量r_w_w 后弄成-1,并唤起r1,r1 接着执行句子7,将read_count 后弄成1,执行句子8,将讯号w1 请求 read_count=0 h_mutex_read_cou nt NULLr_w_w NULL访问文件者:w1 图2-3 初始状态 read_count=0 h_mutex_read_cou nt NULLr_w_w NULL访问文件者: 图2-2w2 请求 read_count=0 h_mutex_read_cou nt NULLr_w_w -1 w2 访问文件者:w1 图2-4 r1 请求 read_count=0 h_mutex_read_cou nt NULLr_w_w -2 w2,r1 访问文件者:w1 图2-5 后弄成-1,并唤起r2,r1执行句子9,开始读 文件;被唤起的r2 执行句子6,判断read_count 的值不是0,所以执行句子 7,将read_count 后弄成0,并唤起r3,r2执行句子9,开始读文件;被唤起的r3 执行 语句6,判断read_count 的值不是0,所以执行句子7,将read_count 行句子9,开始读文件。
这样三个读者同时读文件,参见图2-10;当r1、r2 和r3 读完文件时,都执行句子10~14,并由最后一个执行句子 10~14 的读者执行V(r_w_w),将信号量r_w_w 后弄成0,并唤起w3,w3 接着执行句子18,开始写文件,参见图2-11; w3写完文件时,执行句子 19,将信号量 r_w_w 到初始状态。可见,对于恳求序列 w1,w2,r1,w3,r2,r3 ,实际访问文件的次序是 w1,w2,r1,r2,r3,w3。虽然w3 比r2、r3 先提出恳求,但是因为在此之前早已有r1 在读文件,所以优先响应读者r2、r3,阻塞写者w3。如果在w3 之后不断有新 的读者抵达,则w3 将仍然被阻塞,直至被冻死。 w3 请求 read_count=0 h_mutex_read_cou nt NULLr_w_w -3 w2,r1,w3 访问文件者: w1 图2-6 r2 请求 read_count=0 h_mutex_read_cou nt -1 r2 r_w_w -3 w2,r1,w3 访问文件者: w1 图2-7 情形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),之后开始读文件。
可见多个读者可以 w1 结束,唤醒w2 read_count=0 h_mutex_read_co unt -2 r2,r3 r_w_w -2 r1,w3 访问文件者:w2 图2-9 r1,r2,r3 结束,唤醒 w3 read_count=0 h_mutex_read_cou nt NULLr_w_w NULL访问文件者: w3 图2-11 r3 请求 read_count=0 h_mutex_read_cou nt -2 r2,r3 r_w_w -3 w2,r1,w3 访问文件者: w1 图2-8 w2 结束,唤醒r1, r1 唤醒r2,r2 唤醒r3 read_count=3 h_mutex_read_co unt NULLr_w_w -1 w3 访问文件者: r1,r2,r3 图2-10 同时读文件,并在读文件时阻塞写者。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)去竞争写文件权力。其它写者不需要再 权利。同理仅当写者在执行writ_count 时,才须要执行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 变为 ,执行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的值变为负 ,阻塞在信号量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 不是 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; 实验内容10 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 23writer(){ 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最先调度读者 实验内容11 第一个读者执行 P(reader_wait) reader_wait的值变为 ,执行P(first_reader_wait),将first_reader_wait 的值变为0,向写者申明有读者要读文 件,接着执行P(h_mutex_read_count),并判定read_count 所以执行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 从而执行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); 18 writer(){ 19 P(wait); 20 P(r_w_w); 实验内容12 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 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 的值变为 ,再执行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 P(r_w_w)操作将r_w_w 的值变为正数,从而阻塞在 r_w_w 上。
这促使在它 之后抵达的读者和写者陆续阻塞在wait 实验内容13 当第一批读者读完文件后,由最后一个退出的读者执行执行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 是临界区变量,用来保护文件,实现对文件的读—写互斥和写— 实验内容14 写互斥(相当于算法描述中的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 程序实现15 程序实现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 由于只要有一个读者在读文件,便不容许写者写文件,所以,仅当read_count=0 时,即尚无读者在读文件时,读者才须要执行 P(r_w_w)操作。若 P(r_w_w)操作成功,读者便可去读文件,相应地,read_count+1。同理,仅当在 执行了read_count 时,才须要执行V(r_w_w)操作,以便让写者写文件。又由于 read_count 是一个可被多个读者访问的临界资源,所以应 该为它设置一个互斥信号量 h_mutex_read_count。
每个读者在访问 read_count 程序实现16 之前执行 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)去竞争写文件 程序实现17 权利。同理仅当写者在执行 writ_count 时,才须要执行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 无优先操作截图 程序实现18 3.3 程序流程图 3.3.1 读者优先算法流程图 根据定义的函数名称和功能画读者优先算法的函数流程图如下图3-4 所示: 图3-4 读者优先算法函数流程图 3.3.2 写者优先算法流程图 根据定义的函数名称和功能画写者优先算法的函数流程图如下图3-5 所示: 程序实现19 图3-5 写者优先算法函数流程图 3.3.3 无优先算法流程图 根据定义的函数名称和功能画无优先算法的函数流程图如下图3-6 所示: 程序实现20 图3-6 无优先算法函数流程图 心得感受 21 心得感受 这一次课程设计,我们组完成了题目3 即“读者-写者问题与进程同步”问 题,更加系统地理解和把握了临界区和进程互斥的概念把握用信号量和 PV 作实现进程互斥的方式。
要求中学生用信号量和PV操作实现读者/写者问题的读 者优先算法、写者优先算法和无优先算法。经过读者写者问题的编撰,我对同 步机构应用有了深入的了解,懂得了运用信号量实现进程间的互斥,实现了不 让共享资源同时更改。用信号量上的谓词操作使临界段问题的解决比较简单明 了了。读者写者问题的编撰,花的时间好多,也学到好多东西。了解在支持多 道程序的并发操作系统设计中,如何解决资源共享时进程间的同步与互斥的信 号量机制。 课程设计提升了我们对所学知识的综合应用能力,全面检测并把握所学的 内容,培养独立思索、刻苦钻研的精神,在剖析问题、解决问题的过程中,更 是获得一种成功的喜悦,进而降低学习和应用的兴趣。同时也要督促自己在学 习的过程中不断的建立自我,加强自己的动手操作能力,培养我的独立思考的 那种思维方法。 总之,这一次课程设计我们深刻的理解操作系统,而且锻练了实际编程能 力和思维方法,虽然有难度过程中遇见好多问题,经过深刻细致的理解问题、 剖析问题、解决问题使我们深刻的认识理解了读者/写者问题与进程同步。 参考文献 22 参考文献 百度百科 左嘉庆等著.计算机操作系统教程(第三版). 北京:高等教育出版社,2010.7 附录1 源代码 23 附录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}, 表示读者线程{"r2",1, 15}, 表示写者线程{"w1",3,3}, {"r3",4, {"w2",5,6},{"w3",6,10}, {"r4",7,8}, {"r5",9,2}, {"w4",10,18}, {"w5",12,2} intread_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"); //写者计数器互斥体