--
数学与计算机学院
课程设计说明书
课程名称: 操作系统原理-课程设计课程代码:
题目:读者写者问题
年级/专业/班:
学生姓名:
学号:
开始时间:2011 年12月05日完成时间:2011 年12月25 日课程设计成绩:
学习态度及平时成绩(30) 技术水平与实际
能力(20)
创新(5)说明书撰写质量(45)
总分
(100)
指导教师签名:年月日
目录
1 引言?错误!未定义书签。
1.1问题的提出?错误!未定义书签。
1.2任务于分析?错误!未定义书签。
2程序的主要功能?错误!未定义书签。
2.1测试文本录入功能.................................... 错误!未定义书签。
2.2读者优先判断功能.................................... 错误!未定义书签。2.3写者优先判断功能.................................. 错误!未定义书签。
3 程序运行平台........................................... 错误!未定义书签。
4 总体设计............................................... 错误!未定义书签。5模块分析 ............................................... 错误!未定义书签。
5.1测试文本录入模块.................................... 错误!未定义书签。
5.2读者优先判断模块.................................... 错误!未定义书签。
5.3写者优先判断模块.................................... 错误!未定义书签。6系统测试............................................. 错误!未定义书签。
7 结论................................................................. 8致谢.................................................. 错误!未定义书签。参考文献 (10)
摘要
在现代操作系统中,几乎毫无例外的都是通过文件系统来组织和管理在计算机中所存储的大量程序和数据;或者说,文件系统的管理功能,使通过把它所管理的程序和数据组织成一系列文件来实现的。文件系统负责管理在外存上的文件,并把对文件的存取、共享和保护等功能调用提供给用户。不仅方便了用户,保证了文件的安全性,还可有效的提高系统资源的利用率操作系统是一门实践性很强的课程,不仅要学习书本上的理论,而且必须动手实践才能对操作系统基本原理真正理解。本课程设计中的题目能加深学生对教学内容的理解,培养学生初步掌握操作系统基本功能的设计方法及其实现过程。
计算机操作系统是计算机中的关键性技术,它的设计与实现体现了程序设计与软件工程的精髓。计算机操作系统原理课程那个是计算机科学与技术及相关专业的核心课程,历来为计算机及信息学科所重视。操作系统原理课程设计正是该课程时间环节的集中表现,它不仅可使学生巩固理论学习的概念、原理、设计及算法,同时也可培养软件开发所应有的系统结构设计和软件工程素养。
关键词:操作系统文件系统功能调用
1 引言
1.1 问题的提出
在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求进行读写操作。用信号量机制分别实现读者优先和写者优先问题。
1.2任务与分析
具体要求:
读者-写者问题的读写操作限制(包括读者优先和写者优先)
写-写互斥:不能有两个写者同时进行写操作
读-写互斥:不能同时有一个线程在读,而另一个线程在写。
读-读允许:可以有一个或多个读者在读。
读者优先的附加限制:如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一个写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
课程设计目的:
通过实现经典的读者写者问题,巩固对线程及其同步机制的学习效果,加深对相关基本概念的理解,并学习如何将基本原理和实际设计有机的结合。
?2程序的主要功能
2.1测试文本录入功能
从指定的文件中录入程序所需要的数据信息。
2.2读者优先判断功能
按thread_info中信息创建线程并执行,当线程类型为R时创建读者线程。2.3写着优先判断功能
按thread_info中信息创建线程并执行,当线程类型为R时创建读者线程。
?3 程序运行平台
Windows98/2000/XP操作系统,以VC++ 6.0集成开发环境为主要开发工具。?4总
体设计
图4.1 系统总体框架5 模块分析
5.1测试文本录入模块
打开测试数据文本“thread.txt”,并将其中数据读入thread_info数组中
int nu;//线程号,nu、ki、de、ru用来临时保存线程信息
char ki;//线程类型
double de;//延迟时间
double ru;//运行时间
file=fopen("thread.txt","r");
?if(file)
?{ while(!feof(file))
?{ fscanf(file,"%d %c %lf %lf\n",&nu,&ki,&de,&ru);
??thread_info[n_thread].num=nu;
?thread_info[n_thread].kind=ki;
??thread_info[n_thread].delay=de;
?thread_info[n_thread++].runtime=ru;
}
?}
fclose(file);
5.2 读者优先判断模块
1.首先调readfirst()函数,按thread_info中信息创建线程并执行,当线程类型为R时创建读者线程,反之创建写者线程。主要代码如下:
? for(int i=0;i<n_thread;i++)
?{ if(thread_info[i].kind=='R')
?thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(rf_read),&thread_info[i],0,&threadID);//创建读者线程
??else if(thread_info[i].kind=='W')
thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(r f_write),&thread_info[i],0,&threadID);// 创建写者线程
? }
2.创建及调度读者线程的函数rf_read():首先申请读;然后用一互斥变量rmutex保
证修改readcount时无其他读者线程影响,当为第一个申请的读者时应判断当前是否有写者等待或写,等待写操作完毕方才继续执行,释放互斥变量rmutex,完成读者读的过程;最后用互斥变量rmutex保证修改readcount时无其他读者线程影响,之后释放rmutex。
HANDLE rmutex=OpenMutex(MUTEX_ALL_ACCESS,false,"rmutex");
DWORD de=(DWORD)(((threadinfo*)p)->delay *1000);//延迟时间
DWORD ru=(DWORD)(((threadinfo*)p)->runtime *1000);//执行时间
int nu=((threadinfo*)p)->num;
Sleep(de); //等待
printf("reader %d apply\n",nu);
WaitForSingleObject(rmutex,-1);//阻塞rmutex,以便修改readcount
if(++readcount==1) //申请的读者数加1
EnterCriticalSection(&cs_write);//如为第一个读者,等待写者写完
ReleaseMutex(rmutex);//释放互斥变量rmutex
printf("reader %d begin to read\n",nu);
Sleep(ru); //执行
printf("reader %d finished\n",nu);
WaitForSingleObject(rmutex,-1);//阻塞rmutex,以便修改readcount
if(--readcount==0)
?LeaveCriticalSection(&cs_write);
ReleaseMutex(rmutex);//释放rmutex
3.写者线程rf_write():首先申请写操作;然后等待进入临界区cs_write,执行写操作;最后释放临界资源cs_write,完成写操作。
DWORD de=(DWORD)(((threadinfo*)(p))->delay*1000);//延迟时间
DWORD ru=(DWORD)(((threadinfo*)(p))->runtime*1000);//执行时间
int nu=((threadinfo*)p)->num;
Sleep(de); //等待
printf("writer %d apply\n",nu);
EnterCriticalSection(&cs_write);
printf("writer %d begin to write\n",nu);
Sleep(ru);
printf("writer %d finished\n",nu);
LeaveCriticalSection(&cs_write);
5.3读者优先判断模块
1.首先调writefirst()函数,按thread_info中信息创建线程并执行,当线程类
型为R时创建读者线程,反之创建写者线程。主要代码如下:
for(int i=0;i ? { if(thread_info[i].kind=='R') ?thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(wf_rea d),&thread_info[i],0,&threadID);// 创建读者线程 ?else if(thread_info[i].kind=='W') ?thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(wf_write),&thread_info[i],0,&threadID);// 创建写者线程 ? } 2.创建及调度读者线程的函数wf_read():首先申请读;然后用一互斥变量mutex保证当前只有一个读者进入cs_read临界区,然后用一互斥变量rmutex保证修改re adcount时无其他读者线程影响,当为第一个申请的读者时应判断当前是否有写者等待或写,等待写操作完毕方才继续执行,完成进入临界区的过程,释放临界区并释放互斥变量mutex及rmutex以便其他读者访问临界区cs_read,完成读者读的过程;最后用互斥变量rmutex保证修改readcount时无其他读者线程影响,之后释放rmutex。 HANDLE mutex=OpenMutex(MUTEX_ALL_ACCESS,false,"mutex"); HANDLE rmutex=OpenMutex(MUTEX_ALL_ACCESS,false,"rmutex"); DWORD de=(DWORD)(((threadinfo*)p)->delay *1000); //延迟时间 DWORD ru=(DWORD)(((threadinfo*)p)->runtime *1000);//执行时间int nu=((threadinfo*)p)->num; Sleep(de); //等待 printf("reader %d apply\n",nu); WaitForSingleObject(mutex,-1);//阻塞互斥变量mutex EnterCriticalSection(&cs_read); WaitForSingleObject(rmutex,-1);//阻塞rmutex,以便修改readcountreadcount++;//申请的读者数加1 if(readcount==1) ?EnterCriticalSection(&cs_write);//如为第一个读者,等待写者写完 ReleaseMutex(rmutex);//释放互斥变量rmutex LeaveCriticalSection(&cs_read);//让其他读者进去临界区 ReleaseMutex(mutex);//释放互斥变量mutex printf("reader %d begin to read\n",nu); Sleep(ru); //执行 printf("reader %d finished\n",nu); WaitForSingleObject(rmutex,-1);//阻塞rmutex,以便修改readcount readcount--; if(readcount==0) LeaveCriticalSection(&cs_write); ReleaseMutex(rmutex);//释放rmutex 3.写者线程wf_write()与读者线程有些类似,但也有不同:首先也是申请写操作;然 后用互斥变量wmutex完成修改writecount及进入临界区cs_write的过程,若为第一个申请的写者应等待当前进行的读者读完,之后释放互斥变量wmutex,执行读 操作(注意:此时并未释放临界资源cs_write,即一次仅允许一个写者写);最后释放临界资源cs_write,完成写操作,然后用互斥变量wmutex完成修改writec ount,如为当前最后一个写者则释放临界区变量cs_read,释放互斥变量wmutex。 HANDLE wmutex=OpenMutex(MUTEX_ALL_ACCESS,false,"wmutex"); DWORD de=(DWORD)(((threadinfo*)(p))->delay*1000);//延迟时间 DWORDru=(DWORD)(((threadinfo*)(p))->runtime*1000);//执行时间 int nu=((threadinfo*)p)->num; Sleep(de); //等待 printf("writer %d apply\n",nu); WaitForSingleObject(wmutex,-1);//阻塞wmutex,以便修改writecount writecount++; //当前申请的写者数加1 if(writecount==1) EnterCriticalSection(&cs_read);//如有读者在读,等待ReleaseMutex(wmutex); //释放互斥变量wmutex EnterCriticalSection(&cs_write); printf("writer %d begin to write\n",nu); Sleep(ru); printf("writer %d finished\n",nu); LeaveCriticalSection(&cs_write); WaitForSingleObject(wmutex,-1); writecount--;//当前申请的写者数减1 if(writecount==0) LeaveCriticalSection(&cs_read); ReleaseMutex(wmutex);//释放互斥变量wmutex 流程图: ?6 系统 测试 6.1读者优先结果 结束 将数据读入threadinfo 数组 输入选择0、1、或2 读完,读者数 -1,如读者数 为0,允许写者如有读者在读 直接进入,否则 等写者写完,将 读者数+1 调函数rf_write 写操作 等读者读,写者写 调函数 rf_read 线程R 线程W 最后线程 否 是 开始 2 1 0 调函数readerfirst 调函数writerfirst 最后线程 是 否 读完,读者数-1,如读者数为0,允许写 有读者读无写者等时进入读,读者数+1,反之等待 线程R 调函数rf_write 线程W 写操作 调函数rf_read 等读者读,写者写 图6-1选择读者优先 图6-2读者优先运行过程及结果6.2 写者优先结果 图6-3 选择写者优先 7结论 图6-4 写者优先运行结果和过程? 本次操作系统课程设计完成的是读者-写者问题,通过学习对线程及其同步机制有了很的学习和掌握. 并认识到同步可以保证在一个时间内只有一个线程对某个资源有控制权。共享资源包括全局变量、公共数据成员或者句柄等。同步还可以使得有关联交互作用的代码按一定的顺序执行。