操作系统实习报告
日期:
实习题目:
读者写者问题
完
成
人
实习
内容
简要
描述
主 要
代 码
结构
( 附
注
释)
姓名:陈明明
组号:
学号 0843041112
创建一个控制台进程。此进程包含 n 个线程。用这 n 个线
程来表示 n 个读者或写者。每个线程按相应测试数据文件
(后面有介绍)的要求进行读写操作。用信号量机制分别实
现读者优先和写者优先的读者-写者问题
#include "stdafx.h"
#include"windows.h"
#include
#include
#include
#include
#include
#include
#define READER 'R'
#define WRITER 'W'
#define INTE_PER_SEC 1000
#define MAX_THREAD_NUM 64
//#define MAX_FILE_NUM 32
//#define MAX_STR_LEN 32
readcount=0;
int
int writecount=0;
//int
r_i = 1;
//int w_j = 1;
//读者
//写者
//每秒时钟中断数目
//最大线程数目
//最大数据文件数目
//字符串长度
//读者数目
//写者数目
CRITICAL_SECTION RP_Write;
CRITICAL_SECTION CS_Write;
CRITICAL_SECTION CS_Read;
struct ThreadInfo//------------------------------定义线程的结构
//临界区
//--临界区写
//--临界区读
{
serial;
int
char
entity;
double delay;
double persist;
//线程序号
//线程类别(判断是读者线程还是写者线程)
//线程延迟
//线程读写操作持续时间
};
void RP_ReaderThread(void * p) //---------------------------读者优先--读者线程
{
HANDLE h_Mutex;
//互斥变量
m_persist
=
//延迟等待,然
//等待互斥变量所有权
//OpenMutex 函数功能:为现有的一个已命名互斥体对象创建一个新句柄
h_Mutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");
DWORD wait_for_mutex;
DWORD m_delay;
DWORD m_persist;
int m_serial;
//从参数中获得信息
m_serial = ((ThreadInfo *)(p)) -> serial;
m_delay = (DWORD)(((ThreadInfo *)(p)) -> delay * INTE_PER_SEC);
//读文件持续时间
//线程序号
//延迟时间
(DWORD)(((ThreadInfo *)(p)) -> persist * INTE_PER_SEC);
后发出对共享资源的读(写)申请。
Sleep(m_delay);
printf("Reader thread %d sents the reading require.\n",m_serial);
wait_for_mutex = WaitForSingleObject(h_Mutex,-1);
readcount++;
if(readcount == 1){
//读者数目增加
EnterCriticalSection(& RP_Write);
//第一个读者,等待资源
}
ReleaseMutex(h_Mutex);
//释放互斥信号
printf("Reader thread %d begins to read file.\n",m_serial); //读文件
Sleep(m_persist);
printf("Reader thread %d finished reading file.\n",m_serial);
wait_for_mutex = WaitForSingleObject(h_Mutex,-1);
readcount--;//读者数目减少
if(readcount == 0){
//退出线程
LeaveCriticalSection(& RP_Write);
}
ReleaseMutex(h_Mutex);
//释放互斥信号
}
void RP_WriterThread(void * p) //--------------------------读者优先--写者线程
{
//线程序号
//延迟等待
//延迟时间
//写文件持续时间
DWORD m_delay;
DWORD m_persist;
int m_serial;
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);
printf("Writer thread %d sents the writing require.\n",m_serial);
EnterCriticalSection(& RP_Write);
printf("Writer thread %d begins to write to the file.\n",m_serial);
Sleep(m_persist);
printf("Writer thread %d finishing writing to the file.\n",m_serial);
LeaveCriticalSection(& RP_Write);
//释放资源
//等待资源
//写文件
//退出线程
}
void ReaderPriority(char * file) //-------------------------读者优先处理函数-
{
//线程数目
//线程 ID
//等待所有线程结束
DWORD n_thread = 0;
DWORD thread_ID;
DWORD wait_for_all;
HANDLE h_Mutex;
h_Mutex = CreateMutex(NULL,FALSE,"mutex_for_readcount");
HANDLE h_Thread[MAX_THREAD_NUM]; //线程对象的数组
ThreadInfo thread_info[MAX_THREAD_NUM];
readcount = 0;
InitializeCriticalSection(& RP_Write);
ifstream inFile;
inFile.open(file);
if(! inFile){
//初始化临界区
//初始化 readcount
//互斥对象
//打开文件
printf("error in open input file\n");
}
printf("Reader Priority:\n\n");
while(inFile){//读入每一个读者、写者的信息
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(int i = 0; i < (int)(n_thread); i++){
if(thread_info[i].entity == READER || thread_info[i].entity == 'R'){
h_Thread[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_ReaderThread),&
thread_info[i],0,& thread_ID);
}else{//创建写者线程
h_Thread[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),&
thread_info[i],0,& thread_ID);
}
}
wait_for_all = WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);
printf("All reader and writer have finished operating\n");
}
void WP_ReaderThread(void * p) //----------------------------写者优先--读者线程
{
//互斥变量
HANDLE h_Mutex1;
h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutexl");
HANDLE h_Mutex2;
h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex2");
DWORD wait_for_mutex1;
DWORD wait_for_mutex2;
//等待互斥变量所有权
//延迟时间
//读文件持续时间
DWORD m_delay;
DWORD m_persist;
int m_serial;
//线程序号
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);
printf("Reader thread %d sents the reading require.\n",m_serial);
wait_for_mutex1 = WaitForSingleObject(h_Mutex1,-1);
EnterCriticalSection(& CS_Read); //进入读者临界区
wait_for_mutex2 = WaitForSingleObject(h_Mutex2,-1);
readcount++;
if(readcount == 1){
//修改读者数目
//如果是第一个读者,等待写者写完
//延迟等待
EnterCriticalSection(& CS_Write);
//释放互斥信号 mutex2
}
ReleaseMutex(h_Mutex2);
LeaveCriticalSection(& CS_Read); //让其他读者进人临界区
ReleaseMutex(h_Mutex1);
printf("Reader thread %d begins to read file.\n",m_serial);
Sleep(m_persist); //退出线程
printf("Reader thread %d finished reading file.\n",m_serial);
wait_for_mutex2 = WaitForSingleObject(h_Mutex2,-1);
readcount--;
if(readcount == 0){//最后一个读者,唤醒写者
LeaveCriticalSection(& CS_Write);
}
ReleaseMutex(h_Mutex2);
//释放互斥信号
//读文件
}
void WP_WriterThread(void * p) //---------------------------写者优先--写者线程
{
//线程序号
//延迟等待
//延迟时间
//写文件持续时问
DWORD m_delay;
DWORD m_persist;
int m_serial;
DWORD wait_for_mutex3;
HANDLE h_Mutex3; //互斥对象
h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex3");
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);
printf("Writer thread %d Sents the writing require.\n",m_serial);
wait_for_mutex3 = WaitForSingleObject(h_Mutex3,-1);
writecount++;
if(writecount == 1){
//修改写者数目
EnterCriticalSection(& CS_Read); //第一个写者,等待读者读完
}
ReleaseMutex(h_Mutex3);
EnterCriticalSection(& CS_Write); //进入写者临界区
printf("Writer thread %d begins to write to the file.\n",m_serial); //写文件
Sleep(m_persist);
printf("Writer thread %d finishing writing to the file.\n",m_serial); //退出线程
LeaveCriticalSection(& CS_Write); //离开临界区
wait_for_mutex3 = WaitForSingleObject(h_Mutex3,-1);
writecount--;
if(writecount == 0){
LeaveCriticalSection(& CS_Read);
}
ReleaseMutex(h_Mutex3);
}
void WriterPriority(char * file) //-----------------------------写者优先处理函
{
//线程数目
//线程 ID
//等待所有线程结束
DWORD n_thread = 0;
DWORD thread_ID;
DWORD wait_for_all;
HANDLE h_Mutex1; //互斥对象
h_Mutex1 = CreateMutex(NULL,FALSE,"mutexl");
HANDLE h_Mutex2;
h_Mutex2 = CreateMutex(NULL,FALSE,"mutex2");
HANDLE h_Mutex3;
h_Mutex3 = CreateMutex(NULL,FALSE,"mutex3");
HANDLE h_Thread[MAX_THREAD_NUM]; //线程对象
ThreadInfo thread_info[MAX_THREAD_NUM];
readcount = 0;
writecount = 0;
InitializeCriticalSection(& CS_Write);
InitializeCriticalSection(& CS_Read);
ifstream inFile;
inFile.open(file);
printf("writer Priority:\n\n");
while(inFile){//读入每一个读者、写者的信息
//打开文件
//初始化 readcount
//初始化 writecount
//初始化临界区
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(int i = 0;i < (int)(n_thread);i++){
if(thread_info[i].entity == READER || thread_info[i].entity == 'R'){//创建读者线程
h_Thread[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_ReaderThread),&
thread_info[i],0,& thread_ID);
}else{//创建写者线程
h_Thread[i] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_WriterThread),&
thread_info[i],0,& thread_ID);
}
}//等待所有线程结束
wait_for_all = WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);
printf("All reader and writer have finished operating.\n");
}
int main(int argc,char * argv[])
{
char ch;
while(true){
//打印提示信息
printf("\t\t\t**************选项菜单************\n");
printf("\t\t\t*
printf("\t\t\t*
printf("\t\t\t*
printf("\t\t\t**********************************\n");
printf("Enter your choice(1,2 or 3):");
do//如果输入信息不正确,继续输入{//getch()功 能: 从控制台无回显地取一个字符
1:Reader Priority
2:Writer Priority
3:Exit to Windows
*\n");
*\n");
*\n");
ch = (char)getch();
}while(ch != '1' && ch != '2' && ch != '3');
system("cls");
if(ch == '3') //选择 3,返回
return 0;
else if(ch == '1') //选择 l,读者优先
ReaderPriority("thread.dat");//选择 2,写者优先
else
WriterPriority("thread.dat");
printf("\nPress Any Key To Continue:");
getch();
system("cls");
}
return 0;
}
结 果
分 析
( 或
错 误
原 因
分
析)
注释:如果上述表格空间不够,可以另附表格进行说明