读写者问题.docx
- 文档编号:29831951
- 上传时间:2023-07-27
- 格式:DOCX
- 页数:49
- 大小:154.56KB
读写者问题.docx
《读写者问题.docx》由会员分享,可在线阅读,更多相关《读写者问题.docx(49页珍藏版)》请在冰豆网上搜索。
读写者问题
设计一读者写者问题
实习环境:
系统为WindowsXP+VC6.0
一、实验目的:
1、加深对进程概念的理解,明确进程和程序的区别,进一步认识并发执行的实质;
2、理解和运用信号量、PV原语、进程间的同步互斥关系等基本知识。
二、设计要求
在Windows XP下创建一个控制台进程,该进程应包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的操作限制(包括读者优先和写者优先):
1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3)读-读互斥,即可以有一个或多个读者在读。
读者优先的附加限制:
如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:
如果一个读者申请进行读操作时已有另一个写者在等待访问共享资源,则该读者必须等到没有写者出于等待状态后才能开始读操作。
测试文件格式说明,下面是一个测试数据文件的例子:
1R35
2W45
3R52
4R65
5W5.13
6R154
7R154
三、设计说明
1、读者优先
指除非有写者在写文件,否则读者不需要等待。
所以可以用一个整形变量readnum记录当前的读者数目,用于确定是否需要唤醒正在等待的写者进程(当readnum==读者人数时,表明所有的读者读完,需要唤醒写者等待队列中的第一个写者)。
每一个读者开始读文件时,必须修改readnum变量。
因此需要一个互斥对象rnum[]来实现对全局变量readnum修改时的互斥。
另外,为了实现写写互斥,需要增加一个临界区对象wstate。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读写互斥,当readnum=2时(即第一个读者到来时),读者进程也必须申请临界区对象的所有权。
当读者拥有临界区的所有权时,写者阻塞在临界区对象wstate上。
当写者拥有临界区的所有权时,第一个读者判断完“readnum=2”后阻塞在write上,其余的读者由于等待对readnum的判断,阻塞在rnum[]上。
也可以将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
2、写者优先
写者优先和读者优先相似,可以根据读者优先来改写。
四、 运行结果:
(1)读者优先
(2)写者优先
五、结果分析:
Writerthread2sentsthewriterequire.
当写者2发出申请时,有读者1在读文件,所以写者2阻塞。
Readerthread3sentsthereadingrequire.
Readerthread3beginstoreadfile.
读者3发出申请后,立刻得到满足。
读者6和读者7发送请求时已没有读者线程,所以他们被安排在写者线程完成写操作后读文件。
六、心得与体会:
本次实验是关于操作系统中运用信号量实现进程间的互斥以及同步的,不让共享资源同时修改,用信号量来判断一个进程是否阻塞及何时唤醒。
它与以前的课程设计明显的区别是只要求程序结果及实现什么样的功能,同样的课题,能实现的功能越多,应该能够说明程序员在编程的灵活性。
当然源代码要少,这是编程人员应该具备的素养。
设计二内存管理
一、设计目的
1、内存管理时计算机操作的一大功能,任何作业的运行都需要内存。
通过实验的练习,理解内存的分配及回收。
2、熟悉VC的使用,培养和提高学生的分析问题的能力。
二、设计要求
1、可利用先来先服务、短作业优先、响应比高者优先、多级反馈队列模型间片轮转法等来实现处理机的调度。
2、根据单处理机,多任务的特性做好软件实现的分析要求。
3、要求在系统安全的前提下,兼顾各个进程的公平。
4、可根据问题的实际要求,可选择进程的数量。
三、设计说明
Windows进程的虚拟地址空间中也有三种状态的页面:
空闲页面、保留页面和提交页面。
空闲(Free)页面:
空闲页面是指那些可以保留或提交的可用页面。
保留(Reserved)页面:
保留页面是逻辑页面已分配但没有分配物理存储的页面。
设置这种状态的效果是可以保留一部分虚拟地址,这样,如果不预先释放这些地址,就不能被其他应用程序(如Malloc,LocalAlloc等)的操作所使用。
试图读或写空闲页面或保
留页面将导致页面出错异常。
保留页面可被释放或提交。
提交(Committed)页面:
提交页面是物理存储(在内存中或磁盘上)
已被分配的页面。
可对它加以保护,不许访问或允许只读访问,或允许读写访问。
提交也可以被回收以释放存储空间,从而变成保留页面。
在本实验中,首先创建工程makefile生成随机输入文件,其中包含对内存要求作的各种操作;然后创建工程MemoryAllocation,实现输入文件所要求的各项内存管理操作。
2.主要数据结构
实现内存在管理的主要API函数有:
GetSystemInfo
函数功能:
返回当前系统信息,存放入lpSystemInfo中。
GlobalMemoryStatus
函数功能:
获得计算机系统中当前使用的物理内存和虚拟内存的信息。
使用
GlobalMemoryStatus
函数可以判断应用程序能够分配多少与其它应用程序不冲突的内存空间。
但
GlobalMemoryStatus
函数返回的
信息是不稳定的,我们不能保证两次调用该函数都能返回到相同的信息。
VirtualQuery
函数功能:
提供有关调用进程虚拟窨中的页面信息.
VirtualAlloc
函数功能:
在调用进程的虚拟地址中保留或提交页面。
除非设置了MEM_RESET
标志,否则被这个函数分配的内存单元被自动初始化为0。
VirtualAllocEX
函数功能:
使用该函数可以保留、提交或者保留和提交进程虚拟空间的页面的基址,否则返回NULL。
VirtualFree
函数功能:
可以释放或注销调用进程虚拟空间中的页面。
成功则返回一个非零值,否则返回零值。
VirtualFreeEx
函数功能:
该函数可以释放或注销指定进程虚拟空间中的页面。
VirtualFreeEx函数和VirtualFree函数区别是:
VirtualFree函数释放调用进程的地址空间,而VirtualFreeEx函数可以释放任意指定的进程的地址空间。
如果函数调用成功则返回非零值,否则返回零值。
VirtualLock
功能:
该函数可以将进程虚拟空间中的内存加锁。
以确保后面的对该区域的存取操作不会失败。
成功则返回一个非零值,否则返回一个零值。
VirtualUnlock
功能:
该函数可以将进程虚拟空间指定范围内的页面解锁,从以系统在必要时可以将这些页面换出到页面文件中。
函数调用成功则返回一个非零值,否则返回零值。
3.主要代码段
首先,定义两个结构体
structoperation和structtrace,分别记录对内存的操作信息和跟踪每一次分配活动,并为之分别定义信号量allo和rac,以实现对内存操作的互斥。
具体实现用函数WaitForSingleObject(trac,INFINITE)和ReleaseSemaphore(allo,1,NULL)来实现。
函数DWORDTracker(LPDWORDlpdwparm)用以跟踪allocator线程的内存行为,并输出必要信息。
函数voidAllocator()用以模拟内存分配活动的线程。
四、实验结果
五、总结
1)保留一块区域的操作减少了虚拟空间中未保留与未提交的存储空间。
2)提交一块区域的操作减少了页面文件可用字节数。
3)锁一块区域的操作只减少了物理存储空间的字节数。
4)解锁一开空间的操作只增加物理存储空间的字节数。
5)回收一块的操作只增加页面文件可用字节数和物理存储空间的字节数。
6)释放一块区域的操作只增加虚拟空间中未保留与未提交的存储空间。
分析:
1.内存的提交是由物理存储器支持的页面,他可在页面中,也可在页面文件中
2.保留页面相反,他完全不由物理页面支持。
3.VirtualLock可用在物理内存中锁定一块内存。
设计三快速文件系统
一、设计目的
众所周知,CPU是整个计算机系统中运算速度最快的部分,而外部设备是最慢的部分,它们之间存在着很大的差别。
然而,CPU却时时刻刻可能要求访问外设。
如果CPU的每次操作都必须等待外设完成,那么CPU宝贵的运行时间就会大大浪费。
随着现代计算机技术的发展,大多数现代操作系统都对这个问题进行了处理。
下面就介绍Windows2000中解决这个不匹配问题的方法:
高速缓存和异步传输。
二、设计要求
设计一个函数intfilter(charsource,char*sink,intf),其中:
source:
源文件,即从哪个文件读。
sink:
目标文件,即写到哪个文件。
f:
一个对文件的操作(可以指定任何操作)
分别用3种方法实现一个对文件的操作:
1)无缓冲方式:
表示用的标志位是FILE_FLAG_NO_BUFFERING。
2)缓冲方式:
表示用的标志位是FILE_FLAG_SEQUENTIAL_SCAN。
3)异步方式:
表示用的标志位是FILE_FLAG_OVERLAPPED。
三、设计说明
1.文件高速缓存
文件高速缓存是CPU访问外设的一个“中间设备”。
说是设备,其实它不是真正的物理设备,而是一种核心级内存映像机制。
由于它被设置在内存中,因此速度非常快,可以部分解决CPU与硬盘速度差异的问题。
文件系统的驱动程序通过调用“高速缓存管理程序” 来使用文件高速缓存,然后高速缓存管理程序执行高速缓存的处理工作。
文件高速缓存的原理是:
假设一个进程读了文件的第一个字节,它常常会按照顺序读第二个第三个字节,一直到读出所有的字节。
利用这个原理可以进行“预取”,也就是说,在进程没请求读磁盘之前就先把文件读出来并放到高速缓存中。
这样,当进程请求访问磁盘时,高速缓存可以快速地把已经取到内存中的文件内容直接送给进程使用,从而大大加速了访问磁盘的速度。
另外,由于一个文件可能会被多次读入,因此可以在第一次读入后,将文件数据保存在高速缓存中。
这样,下次再读时,就不必从硬盘而可以从缓存中读取。
利用LRU(LeastRecentlyUsed)的原则,可以将不常使用的文件从缓存中删除以节省高速缓存空间。
2.异步传输
与文件高速缓存不同,文件的异步传输是一种改变指令执行顺序的机制。
在以往的操作系统中,指令都是顺序执行的,下一条指令必须在上一条指令执行完毕后才能执行。
因此,如果CPU遇到一条放盘指令,那么它就必须等待缓慢的磁盘访问结束以后才能进行后续工作。
如果它后面遇到的指令并不依赖于访盘操作时,这个等待就很没有必要。
Windows2000中使用了一种异步文件传输机制来解决这个问题。
它通过设置打开文件时的一个标志位来使进程不等待读些文件操作而继续执行。
当后续指令必须用到磁盘访问的结果数据时,它在通过一条Wait指令进行等待。
这样,在访盘指令和等待指令之间的指令就可以与磁盘访问同时进行了,从而大大加快了系统的整体速度。
实际测试当中,采用一个37KB的文本文件,输出结果如下:
当然,这些数据还需要更多的测试才准确,但是整体看来还是使用高速缓存时速度最快啊。
不过我们还是应该根据情况采用不同的文件操作模式。
附件
一、读者写者源程序
#include"windows.h"
#include
#include
#include
#include
#defineREADER'R' //reader
#defineWRITER'W' //writer
#defineINTE_PER_SEC1000 //interruptnumberpersecond
#defineMAX_THREAD_NUM64 //maxthreadnumber
intreadcount=0;
intwritecount=0;
CRITICAL_SECTIONRP_Write; //CriticalSection
CRITICAL_SECTIONcs_Write;
CRITICAL_SECTIONcs_Read;
structThreadInfo
{
intserial; //theserialnumberofthethread.
charentity; //typeofthread(readerorwriter).
doubledelay; //delayofthread.
doublepersist; //timefothread'sreadandwriteoperation.
};
voidRP_ReaderThread(void*p);
voidRP_WriterThread(void*p);
voidReaderPriority(char*file);
voidWP_ReaderThread(void*p);
voidWP_WriterThread(void*p);
voidWriterPriority(char*file);
//themainfunction
intmain(intargc,char*argv[])
{
charch;
while(true)
{
printf("************************************************/n");
printf(" 1:
ReaderPriority/n");
printf(" 2:
WriterPriority/n");
printf(" 3:
ExittoWindows/n");
printf("************************************************/n");
printf("Enteryourchoice(1,2or3):
");
//inputisincorrect.
do{
ch=(char)_getch();
}while(ch!
='1'&&ch!
='2'&&ch!
='3');
//clearthescreen.
system("cls");
//choose3,return.
if(ch=='3')
return0;
//choose1,readerfirst.
elseif(ch=='1')
ReaderPriority("thread.dat");
//choose2,writerfirst.
else
WriterPriority("thread.dat");
//end.
printf("/nPressAnyKeyToContinue:
");
_getch();
system("cls");
}
return0;
}
voidRP_ReaderThread(void*p)
{
//execlusiveobject
HANDLEh_Mutex;
h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");
DWORDwait_for_mutex; //waitfortheexeclusiveobject
DWORDm_delay; //delaytime
DWORDm_persist; //thetimeofreadfileoperation
intm_serial; //serialnumberofthethread
//gettheinformationfromtheparameter.
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay); //waitforalittlewhile.
printf("Readerthread%dsentsthereadingrequire./n",m_serial);
//waitforexeclusivesignal,
wait_for_mutex=WaitForSingleObject(h_Mutex,-1);
//addthereader'snumber
readcount++;
if(readcount==1)
{
//thefirstreader,waitforresource.
EnterCriticalSection(&RP_Write);
}
ReleaseMutex(h_Mutex); //releaseexeclusivesignal
//readthefile.
printf("Readerthread%dbeginstoreadfile./n",m_serial);
Sleep(m_persist);
//exitthethread
printf("Readerthread%dfinishedreadingfile./n",m_serial);
wait_for_mutex=WaitForSingleObject(h_Mutex,-1);
//decrementthereader'snumber
readcount--;
if(readcount==0)
{
//ifallreadersfinishedtheiroperation,wakeupthewriter
LeaveCriticalSection(&RP_Write);
printf("Readerthread%dleavethecriticalsection./n",m_serial);
}
ReleaseMutex(h_Mutex); //releasetheexeclusivesignal
}
voidRP_WriterThread(void*p)
{
DWORDm_delay;
DWORDm_persist;
intm_serial;
//getinfomationfromtheparameter.
m_serial=((ThreadInfo*)(p))->serial;
m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC);
m_persist=(DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);
Sleep(m_delay); //wait
printf("Writerthread%dsentsthewritingrequire./n",m_serial);
//waitfortheresource
EnterCriticalSection(&RP_Write);
//writethefile
printf("Writerthread%dbeginstowritetothefile./n",m_serial);
Sleep(m_persist);
//exitthethread
printf("Writerthread%dfinishingwritingtothefile./n",m_serial);
//releasetheresource
LeaveCriticalSection(&RP_Write);
}
voidReaderPriority(char*file)
{
DWORDn_thread=0; //numberofthreads
DWORDthread_ID; //threadID
DWORDwait_for_all; //waitforallthreads
//execlusiveobject
HANDLEh_Mutex;
h_Mutex=CreateMutex(NULL,FALSE,"mutex_for_readcount");
//thearrayofthethreadobject
HANDLEh_Thread[MAX_THREAD_NUM];
ThreadInfothread_info[MAX_THREAD_NUM];
readcount=0; //Initializereadcount
InitializeCriticalSection(&RP_Write);
ifstreaminFile;
inFile.open(file);
printf("ReaderPriority:
/n/n");
while(inFile)
{
//readeverywriter,reader'sinformation
inFile>>thread_info[n_thread].serial;
inFile>>thread_info[n_thread].entity;
inFile>>thread_info[n_thread].delay;
inFile>>thread_info[n_thread++].persist;
inFile.get();
}
for(inti=0;i<(int)(n_thread);i++)
{
if(thread_info[i].entity==READER||thread_info[i].entity=='r')
{
//createreaderthread
h_Thread[i]=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)(RP_Reader
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 读写 问题