学号:0121410880532课程设计2012——2013学年第2学期课程名称操作系统学院计算机科学与技术学院专业软件工程专业班级软工ZY1402姓名李婧琪指导教师刘军目录设计题目与要求…………………………………………………………31.总的设计思想及系统平台,语言,工具…………………………….31.1设计思想………………………………………………………….31.2系统调用平台及语言…………………………………………….31.3SCI……………………………………………………………….41.4系统调用的一般步骤…………………………………………….41.4.1.对用户内存进行读写………………………………………41.4.2.使用系统调用…………………………………………….52.数据结构与模块说明(功能与流程图)……………………………52.1数据结构………………………………………………………….52.1.1运行结果…………………………………………………….72.2系统流程图……………………………………………………….83.源程序………………………………………………………………..84.调试记录……………………………………………………………..95.自我评价与总结……………………………………………………..96.参考文献…………………………………………………………….10评分表………………………………………………………………….111、设计题目与要求设计题目:实现读者写者(Reader-WriterProblem)问题要求:通过研究Linux的线程机制和信号量实现读者写者(Reader-Writer)问题并发控制。读者写者问题(read—writeproblem)是一个经典的并发程序设计问题。有两组并发进程:读者和写者,共享一个问题F,要求:(1)允许多个读者可同时对之执行读操作;(2)只允许一个写者往文件中写信息;(3)任一写者在完成写操作之前不允许其他读者或者写者工作;(4)写者执行写操作前,应让已有的写者和读者全部退出。实验条件要求:每人一台与Linux主机联网的Windows主机,普通用户权限。2、总的设计思想及系统平台,语言,工具2.1设计思想:根据题目所述,读者写者问题会分为以下三种情况:1、读者优先权比写者高2、写者优先权比读者高3、读者和写者的优先权高相同1、读者优先权比写者高对于读者优先,应满足下列条件:如果新读者到:①无读者、写者,新读者可以读;②有写者等待,但有其它读者正在读,则新读者也可以读;③有写者写,新读者等待。如果新写者到:①无读者,新写者可以写;②有读者,新写者等待;③有其它写者,新写者等待。为了实现以上功能,我们需要设定一个信号量mutex来控制两个进程不能再同一时间访问相同的数据,另外我们需要设定另一个信号量resource来表示资额使用,以及readcount来表示当前有多少个读者。以下是一些简单的代码及思想:Writer(){resource.p();//分配资源给写者dowritingresource.v();//回收资源}Reader(){mutex.p();//用信号量确定当一个读者进入时,别人不能使用.readcount++;//读者数量加一if(readcount==1)resource.p();//分配资源给reader,使writer阻塞mutex.v();//解除占用doreadingmutex.p();readcount--;if(readcount==0)resource.v();//唤醒写者进程mutex.v();解除占用}在这种解决办法中,第一个读者必须锁定资源,一旦这些资源对写者是锁定的,后来的读者将会拥有这些资源,并同样的进行锁定。同一时间可能会尝试进入很多读者,但是一次只有一个读者可以进入,因此我们在尝试进入之前要用mutex来声明,直到完成活动之后解除声明。这种情况对于读者尝试退出的情况同样适用。这时候我们并没有占用写者的资源。在第一个读者都命令的时候,它会锁定资源,这样做会阻止写者进入操作,同样的,后来的读者也可以锁定资源。因此,最后一个读者必须将资源解锁,从而提供给作家。总而言之,读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。该算法只要还有一个读者在活动,就允许后续的读者进来,该策略的结果是,如果有一个稳定的读者流存在,那么这些读者将在到达后被允许进入。而写者就始终被挂起,直到没有读者为止。。2、写者优先权比读者高写者优先1的设计思想是在一个写者到达时如果有正在工作的读者,那么该写者只要等待正在工作的读者完成,而不必等候其后面到来的读者就可以进行写操作。该算法当一个写者在等待时,后到达的读者是在写者之后被挂起,而不是立即允许进入。为了实现这个想法,我们需要增设一个writecount来记录写者的数目,当writecount==0时才可以释放读者进行操作。为了实现对writecount的互斥访问,设置了一个互斥对象wmutex。为了实现写者优先,设置一个临界区对象readTry,当有写者等待时,读者必须阻塞在readTry上,读者除了要一个全局变量readcount实现操作上的互斥外,还需要一个互斥对象对阻塞在readTry这一个过程实现互斥,这两个互斥对象分别为rmutex和resource。以下是一些简单的代码及思想:intreadcount,writecount;semaphorermutex,wmutex,readTry,resourcereader(){readTry.p();rmutex.p();readcount++;if(readcount==1)resource.p();rmutex.v();readTry.v();doreadingrmutex.p();readcount--;if(readcount==0)resource.v();rmutex.v();}Writer(){Wmutex.p();Writecount++;if(writecount==1)readTry.p();wmutex.v();resource.p()dowritringresource.v()wmutex.p();writecount--;if(writecout==0)readTry.v();wmutex.v();}在这种解决方法里,rmutex和wmutex的使用和第一种方法是一样的,都是为了避免当他们进入或退出的时候有读者或写者竞争的情况。这种办法通过让每个读者都锁定和接入readTry来解决饿死问题,第一个写者锁定readTry然后后面的读者仍然可以占用resource,但是最后一个读者必须释放readTry,只有这样,读者才能占用资源并进入。2.2系统调用平台及语言:本课程设计在Linux操作系统下,使用c语言完成2.3开发工具的选择用到的工具有GCC编译器和vi编译器.3.数据结构与模块说明(功能与流程图)3.1模块说明1、gen函数NY2、主函数信号量初值设置Rand()%2==0?创建读进程创建写进程结束Reader_idN_REDAR&&WRITER_IDN_WRITER信号量初值设置3、read函数3.1.1运行结果(1),输入gedittime.c命令,然后编写代码,如图:结束Gen();(2)用gcc编译器进行编译连接,然后输入“./RW”命令,运行编译连接之后的程序。结果我们可以看到。3.源程序#includestdio.h#includestdlib.h#includepthread.h#defineN_WRITER5//写者数目#defineN_READER5//读者数目#defineW_SLEEP1//控制写频率#defineR_SLEEP2//控制读频率pthread_twid[N_WRITER],rid[N_READER];constintMAX_RAND=1000;//产生的最大随机数intdata=0;intreaderCnt=0,writerCnt=0;pthread_mutex_taccessReaderCnt=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_taccessWriterCnt=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_twriteLock=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_treaderLock=PTHREAD_MUTEX_INITIALIZER;pthread_mutex_touterLock=PTHREAD_MUTEX_INITIALIZER;voidwrite(intmy_id){printf(%dthwriterisdoingwriting\n,my_id);sleep(2);printf(%dthwriterfinishwriting\n,my_id);}voidread(intmy_id){printf(%dthreaderisdoingreading\n,my_id);sleep(2);printf(%dthreaderfinishreading\n,my_id);}void*writer(void*in){intmy_id=*(int*)in;printf(%dthwriteriscome\n,my_id);pthread_mutex_lock(&accessWriterCnt);{//临界区,希望修改writerCnt,独占writerCntwriterCnt++;if(writerCnt==1){//阻止后续的读者加入待读队列pthread_mutex_lock(&readerLock);}}pthread_mutex_unlock(&accessWriterCnt);pthread_mutex_lock(&writeLock);{//临界区,限制只有一个写者修改数据printf(%dthwriterisdoingwriting\n,my_id);sleep(2);printf(%dthwriterfinishwriting\n,my_id);}pthread_mutex_unlock(&writeLock);pthread_mutex_lock(&accessWriterCnt);{//临界区,希望修改writerCnt,独占writerCntwriterCnt--;if(writerCnt==0){//阻止后续的读者加入待读队列pthread_mutex_unlock(&readerLock);}}pthread_mutex_unlock(&accessWriterCnt);sleep(W_SLEEP);pthread_exit((void*)0);}void*reader(void*in){intmy_id=*(int*)in;printf(%dthreaderiscome\n,my_id);//假如写者锁定了readerLock,那么成千上万的读者被锁在这里pthread_mutex_lock(&outerLock);{//临界区pthread_mutex_lock(&readerLock);//只被一个读者占有{//临界区pthread_mutex_lock(&accessReaderCnt);//代码段1{//临界区readerCnt++;if(readerCnt==1){pthread_mutex_lock(&writeLock);}}pthread_mutex_unlock(&accessReaderCnt);}pthread_mutex_unlock(&readerLock);//释放时,写者将优先获得readerLock}pthread_mutex_unlock(&outerLock);read(my_id);pthread_m