操作系统原理
实验报告
实验名称: :
操作系统
姓
名: :
XXX
学
号:
xx x x xxxx x xx
班
级:
xxx
指导老师:
xxx
一、实验内容
在Windows2000 环境下,创建一个控制台进程,此进程包含 n 个线程。用这 n个线程来表示 n 个读者或写者。每个线程按相应测试数据文件(后面有介绍)得要求进行读写操作。用信号量机制分别实现读者优先与写者优先得读者—写者问题。):)先优者写与先优者读括包(制限作操写读得题问者写—者读ﻫ1互写—写ﻫ斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写.,)3允读-读ﻫ许,即可以有一个或多个读者在读. 读者优先得附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。请申者读个一果如:制限加附得先优者写ﻫ进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作与结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应得读写操作限制. 二、实验目得
在 Windows2000 环境下,创建一个控制台进程,此进程包含n个线程。用这 n 个线程来表示 n 个读者或写者.每个线程按相应测试数据文件(后面有介绍)得要求进行读写操作。用信号量机制分别实现读者优先与写者优先得读者-写者问题。
三、实验原理
1) 、读者优先 读者优先指得就是除非有写者在写文件,否则读者不需要等待.所以可以用一个
整型变量read_count 记录当前得读者数目,用于确定就是否需要释放正在等待得写者线程(当 read_count=O时,表明所有得读者读完,需要释放写者等待队列中得一个写者)。每一个读者开始读文件时,必须修改 read_count 变量.因此需要一个互斥对象mutex来实现对全局变量read_count 修改时得互斥。ﻫ另外,为了实现写—写互斥,需要增加一个临界区对象 write。当写者发出写请求时,必须申请临界区对象得所有权。通过这种方法,也可以实现读-写互斥,当read_count=l 时(即第一个读者到来时),读者线程也必须申请临界区对象得所有权。
当读者拥有临界区得所有权时,写者阻塞在临界区对象 write 上.当写者拥有临界区得所有权时, 第一个读者判断完 "read_count==1"后阻塞在 write 上,其余得读者由于等待对read_count得判断,阻塞在 mutex 上。
)2ﻫ 2)先 、写者优先它,来到者写个一旦一于在处之同不;似类先优者读与先优者写ﻫ应该尽快对文件进行写操作,如果有一个写者在等待,则新到来得读者不允许进行读操作。为此应当添加一个整型变量write_count,用于记录正在等待得写者得数目,当write_count=O 时,才可以释放等待得读者线程队列.全对了为ﻫ局变量 write_count 实现互斥,必须增加一个互斥对象mutex3.现实了为ﻫ写者优先,应当添加一个临界区对象 read,当有写者在写文件或等 待时,读者必须阻塞在read 上。
· 读者线程除了要对全局变量 read_count 实现操作上得互斥外,还必须有一个互斥对象对阻塞,read 这一过程实现互斥。这两个互斥对象分别命名为mutex1与 mutex2。
四、实验过程
在 Windows2000 环境下,创建一个控制台进程。
用 VC++实现。
读者优先指得就是除非有写者在写文件,否则读者不需要等待。所以可以用一个整型变量 read_count 记录当前得读者数目,用于确定就是否需要释放正在等待得写者线程(当read_count=O 时,表明所有得读者读完,需要释放写者等待队列中得一个写者)。每一个读者开始读文件时,必须修改 read_count变量.因此需要一个互斥对象 mutex 来实现对全局变量read_count 修改时得互斥。
另外,为了实现写—写互斥,需要增加一个临界区对象 write。当写者发出写请求时,必须申请临界区对象得所有权。通过这种方法,也可以实现读-写互斥,当read_count=l 时(即第一个读者到来时),读者线程也必须申请临界区对象得所有权. 当读者拥有临界区得所有权时,写者阻塞在临界区对象 write 上。当写者拥有临界区得所有权时, 第一个读者判断完 "read_count==1”后阻塞在 write上,其余得读者由于等待对read_count 得判断,阻塞在 mutex 上。
写者优先与读者优先类似;不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来得读者不允许进行读操作。为此应当添加一个整型变量write_count,用于记录正在等待得写者得数目,当 write_count=O 时,才可以释放等待得读者线程队列.量变局全对了为ﻫwrite_count 实现互斥,必须增加一个互斥对象mutex3.,先优者写现实了为ﻫ应当添加一个临界区对象 read,当有写者在写文件或等在塞阻须必者读,时待ﻫread 上。
· 读者线程除了要对全局变量 read_count实现操作上得互斥外,还必须有一个
互斥对象对阻塞,read 这一过程实现互斥。这两个互斥对象分别命名为mutex1与 mutex2。
结构:
头文件 定义全局变量 RP_ReaderThread()读者优先—--读者线程 RP_WriterThread()读者优先--—写者线程 ReaderPriority ()读者优先处理函数 WP_ReaderThrea ()写者优先-——读者线程 WP_WriterThread()写者优先-——写者线程 WriterPriority ()写者优先处理函数 主函数:包含对 dat 文件得读取以及函数得调用. 代码:附录 五、实验结果
界面:
测试数据:
2 W 4 5 3 R 5 2 4 R 6 5 5 W 5、1 3
结果 读者优先
写者优先
六、实验心得体会
通过对读者写者问题得编程,对线程有了更深得了解,希望在后面得学习中懂得更多。
七、参考文献
老师提供得资料,以及互联网查阅。
八、附录
#include ”windows、h" #include <conio、h> #include 〈stdlib、h〉 #include 〈fstream、h〉 #include <io、h> #include <string、h〉 #include <stdio、h〉 #include "winbase、h” #define READER
"R"
// 读者 #define WRITER
’W"
// 写者 #define INTE_PER_SEC
1000
// 每秒时钟中断得数目 #define MAX_THREAD_NUM
64
// 最大线程数 int nReaderCnt = 0;
// 读者计数 int nWriterCnt = 0;
// 写者计数 HANDLE hWrite
= ::CreateSemaphore( NULL, 1, 1, NULL );
// 写开始信号 HANDLE hRead
= ::CreateSemaphore( NULL, 1, 1, NULL );
// 读开始信号
HANDLE hRCMutex
= ::CreateMutex( NULL, FALSE, NULL );
HANDLE hWCMutex
= ::CreateMutex( NULL, FALSE, NULL ); HANDLE hReadMutex
= ::CreateMutex( NULL, FALSE, NULL ); // 从测试数据文件中获取得线程信息 struct ThreadInfo {
ThreadInfo()
{
nSerialNo
= 0;
cType
= ’^’;
dDelayTime
= 0、0;
dOpeTime
= 0、0;
}
int
nSerialNo;
// 线程序号
char
cType;
// 线程类别
double
dDelayTime;
// 线程延迟时间
double
dOpeTime;
// 线程读写操作时间 }; // 读者优先—-—读者线程
// P:读者线程信息 void RP_ReaderThread(void *p)
{
int nSerialNo = ((ThreadInfo*)(p))-〉nSerialNo ; //从文件中读取 线程序号
DWORD dwReadTime = (DWORD)(((ThreadInfo*)(p))—>dOpeTime * INTE_PER_SEC );
DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))->dDelayTime * INTE_PER_SEC );
Sleep( dwDelay );
printf(”Reader thread %d sents the reading require、\n",nSerialNo);
WaitForSingleObject( hRCMutex, INFINITE );
nReaderCnt++;
if( nReaderCnt == 1 )
{
WaitForSingleObject( hWrite, INFINITE );
}
ReleaseMutex(hRCMutex);
printf( "Reader thread %d begins to read file、\n", nSerialNo );
Sleep( dwReadTime );
printf( ”Reader thread %d finished reading file、\n", nSerialNo );
WaitForSingleObject( hRCMutex, INFINITE );
nReaderCnt——;
if( nReaderCnt == 0 )
{
ReleaseSemaphore( hWrite, 1, NULL );
}
ReleaseMutex(hRCMutex); } // 读者优先—--写者线程 // P:写者线程信息 void RP_WriterThread(void *p) {
int nSerialNo = ((ThreadInfo*)(p))->nSerialNo ; //
从参数中获得信息
DWORD dwWriteTime = (DWORD)(((ThreadInfo*)(p))-〉dOpeTime * INTE_PER_SEC );
DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))—>dDelayTime * INTE_PER_SEC );
Sleep( dwDelay );
printf("Write thread %d sents the writing require、
\n”,nSerialNo);
WaitForSingleObject( hWrite, INFINITE );
printf( ”Writer thread %d begins to write to the file、\n”, nSerialNo );
Sleep( dwWriteTime );
printf( ”Write thread %d finished writing to the file、\n", nSerialNo );
ReleaseSemaphore( hWrite, 1, NULL ); } // 读者优先处理函数 // file:文件名 void ReaderPriority( char *file )
{
int nThreadCnt = 0;
DWORD dwThreadID = 0;
nReaderCnt = 0;
// 初始化读写者计数
HANDLE hThreads[MAX_THREAD_NUM];
ThreadInfo oThreadInfo[MAX_THREAD_NUM];
ifstream inFile;
in ( file );
printf( "Reader Priority:\n\n” );
while( inFile )
{
// 读入每一个读者,写者得信息
inFile>>oThreadInfo[nThreadCnt]、nSerialNo;
inFile〉〉oThreadInfo[nThreadCnt]、cType;
inFile〉〉oThreadInfo[nThreadCnt]、dDelayTime;
inFile>〉oThreadInfo[nThreadCnt]、dOpeTime;
if ( ’^’ != oThreadInfo[nThreadCnt]、cType )
{
nThreadCnt++;
}
in();
}
// 创建线程
for( int i = 0; i< nThreadCnt; i++ )
{
if(( oThreadInfo[i]、cType==READER )
|| ( oThreadInfo[i]、cType == ’r" ))
{
hThreads[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(RP_ReaderThread),
// 创建读者进程
&oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID );
}
else
{
hThreads[i] = CreateThread( NULL, 0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),// 创建写线程
&oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID );
}
}
for( i = 0; i〈 nThreadCnt; i++ )
{
ResumeThread( hThreads[i] );
}
WaitForMultipleObjects( nThreadCnt, hThreads, TRUE, INFINITE );
printf( "All reader and writer have finished operating、\n" ); } // 写者优先—-—读者线程 // P:读者线程信息 void WP_ReaderThread( void *p ) {
int nSerialNo = ((ThreadInfo*)(p))—〉nSerialNo ; // 从参数中得到信息
DWORD dwReadTime = (DWORD)(((ThreadInfo*)(p))—〉dOpeTime * INTE_PER_SEC );
DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))—>dDelayTime * INTE_PER_SEC );
Sleep( dwDelay );
printf("Reader thread %d sents the reading require、\n",nSerialNo);
WaitForSingleObject( hReadMutex, INFINITE );
WaitForSingleObject( hRead, INFINITE );
WaitForSingleObject( hRCMutex, INFINITE );
nReaderCnt++;
if(nReaderCnt==1)
{
WaitForSingleObject( hWrite, INFINITE );
}
ReleaseMutex( hRCMutex );
ReleaseSemaphore( hRead, 1, NULL );
ReleaseMutex( hReadMutex );
printf( ”Reader thread %d begins to read file、\n", nSerialNo );
Sleep( dwReadTime );
printf( "Reader thread %d finished reading
file、\n", nSerialNo );
WaitForSingleObject( hRCMutex, INFINITE );
nReaderCnt—-;
if( nReaderCnt == 0 )
{
ReleaseSemaphore( hWrite, 1, NULL );
}
ReleaseMutex( hRCMutex ); } // 写者优先---写者线程 // P:写者线程信息 void WP_WriterThread( void *p ) {
int nSerialNo = ((ThreadInfo*)(p))—>nSerialNo;
DWORD dwWriteTime = (DWORD)
(((ThreadInfo*)(p))->dOpeTime * INTE_PER_SEC );
DWORD dwDelay = (DWORD)(((ThreadInfo*)(p))->dDelayTime * INTE_PER_SEC );
Sleep( dwDelay );
printf("Writer thread %d sents the writing r
equire、\n”,nSerialNo);
WaitForSingleObject( hWCMutex, INFINITE );
nWriterCnt++;
if( nWriterCnt == 1 )
{
WaitForSingleObject( hRead, INFINITE );
}
ReleaseMutex(hWCMutex);
WaitForSingleObject( hWrite, INFINITE );
printf( "Writer thread %d begins to write to the file、\n”, nSerialNo );
Sleep( dwWriteTime );
printf( "Writer thread %d finished writing to the file、\n", nSerialNo );
ReleaseSemaphore( hWrite, 1, NULL );
WaitForSingleObject( hWCMutex, INFINITE );
nWriterCnt--;
if( nWriterCnt == 0 )
{
ReleaseSemaphore( hRead, 1, NULL );
}
ReleaseMutex(hWCMutex);
} // 写者优先处理函数 // file:文件名 void WriterPriority( char * file )
{
int nThreadCnt = 0;
DWORD dwThreadID;
HANDLE hThreads[MAX_THREAD_NUM];
ThreadInfo oThreadInfo[MAX_THREAD_NUM];
nReaderCnt=0;
nWriterCnt=0;
ifstream inFile;
in (file);
printf(”Writer priority:\n\n”);
while(inFile)
{
inFile〉>oThreadInfo[nThreadCnt]、nSerialNo;
inFile>>oThreadInfo[nThreadCnt]、cType;
inFile>>oThreadInfo[nThreadCnt]、dDelayTime;
inFile>>oThreadInfo[nThreadCnt]、dOpeTime;
if ( ’^' != oThreadInfo[nThreadCnt]、cType )
{
nThreadCnt++;
}
in();
}
for( int i = 0 ;i 〈 nThreadCnt; i++ ) // 创建线程
{
if(( oThreadInfo[i]、cType == READER ) || ( oThreadInfo[i]、cType == ’r’ ))
{
hThreads[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(WP_ReaderThread),
//创建读者进程
&oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID );
}
else
{
hThreads[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)(WP_WriterThread),
&oThreadInfo[i],CREATE_SUSPENDED,&dwThreadID);
}
}
for( i = 0; i< nThreadCnt; i++ )
{
ResumeThread( hThreads[i] );
}
WaitForMultipleObjects( nThreadCnt, hThreads, TRUE, INFINITE );
printf("All reader and writer have finished operating、\n"); } int main(int argc,char *argv[]) {
char ch;
while(true)
{
printf(”*************************************\n");
printf("
1、Reader Priority\n");
printf("
2、Writer Priority\n");
printf(”
3、Exit to Windows\n");
printf(”*************************************\n");
printf("Enter your choice1,2,3: ");
do{
ch=(char)_getch();
}while(ch!='1’&&ch!="2"&&ch!=’3’);
system(”cls”);
if(ch==’3")
return 0;
else if(ch=="1’)
ReaderPriority(”thread、dat");
else
WriterPriority(”thread、dat”);
printf(”\nPress Any Key to Coutinue:”);
_getch();
system(”cls");
}
return 0; }