操作系统原理实验报告——读者写者
一、实验目的
1.现代操作系统的核心是多道程序设计、多处理器和分布式处理器,这些方案和操作系统设计技术的基础都是并发。当多个进程并发执行时,不论是在多处理器系统的情况下,还是在单处理器多道程序系统中,都会出现冲突和合作的问题。
2.理解操作系统中用互斥和同步解决问题。
3.用信号量机制分别实现读者优先和写者优先的读者-写者问题从而掌握互斥与同步的基本理念。
二、实验内容
在Windows 环境下,创建一个控制台进程,此进程包含n个线程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):
1) 写-写互斥,即不能有两个写者同时进行写操作。
2) 读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3) 读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态才能开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结果读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
三、实验步骤和思路
总原理:
1.读者优先
读者优先指的是除非有写者在写文件,否则读者不需要等待。所以可以用一个整型变量read-count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read-count=0时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。每一个读者开始读文件时,必须修改read-count变量。因此需要一个互斥对象mutex来实现对全局变量read-count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。当写者发出写请求时,必须申请临界区对象的所有权。通过这种方法,也可以实现读-写互斥,当read-count=1时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。
当读者拥有临界区的所有权时,写者阻塞在临界区对象write上。当写者拥有临界区的所有权时,第一个读者判断完“read-count==1”后阻塞在write上,其余的读者由于等待对read-count的判断,阻塞在mutex上。
2.写者优先
写者优先与读者优先类似。不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。为此应当添加一个整型变量write-count,用于记录正在等待的写者数目,当write-count=0时,才可以释放等待的读者线程队列。
为了对全局变量write-count实现互斥,必须增加一个互斥对象mutex3。
为了实现写者优先,应当添加一个临界区对象read,当有写者在写文件或等待时,读者必须阻塞在read上。
读者线程除了要对全局变量read-count实现操作上的互斥外,还必须有一个互斥对象对阻塞read这一过程实现互斥。这两个互斥对象分别命名为mutex1和mutex2。
四、实验截图
五、实验总结
多进程和多线程是当今操作系统的一个很大的特色。本次实验就是通过一个读进程和一个写进程生成的多个读线程和多个写线程的并发执行来理解和体会Windows 的多线程处理机制。由于是初次接触涉及系统内部的程序设计,开始的时候,我感觉到有点茫然,因为我不知道从哪里下手开始做。我很认真地研读了老师提供的实验指导书,以期得到启发,但是还是觉得“万事开头难”,我虽然有些理解了,但是还不是很清晰,也就是说我的脑中还没有形成一个具体的程序架构。我看了材料中的那些函数,比如WaitForSingleObject、 WaitForMutipleObjects、CreatThread 等等。
通过此次实验,对线程及其同步机制有了较好的理解和掌握,并认识到同步可以保证在一个时间内只有一个线程对某个资源有控制权。同步还可以使得有关联交互作用的代码按一定的顺序执行。同时也掌握而来实现线程同步的对象有Criticai_setion(关键段),Event(事件),Mutex(互斥对象),Semaphores(信号量)。
#include "windows.h"
#include <conio.h>
#include <stdlib.h>
#include <fstream>
#include <io.h>
#include <string.h>
#include <stdio.h>
#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 //字符串的长度
int readcount=0; //读者数目
int writecount=0; //写者数目
CRITICAL_SECTION RP_Write; //临界资源
CRITICAL_SECTION cs_Write;
CRITICAL_SECTION cs_Read;
using namespace std;
struct ThreadInfo
{int serial; //线程序号char entity; //线程类别(判断是读者还是写者线程)double delay; //线程延迟时间double persist; //线程读写操作时间
};
///
// 读者优先---读者线程
//P:读者线程信息
void RP_ReaderThread(void *p)
{//互斥变量HANDLE h_Mutex;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);m_persist=(DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC);Sleep(m_delay); //延迟等待printf("读者线程 %d 发来读请求.\n",m_serial);//等待互斥信号,保证对ReadCount 的访问,修改互斥wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//读者数目增加readcount++;if(readcount==1){//第一个读者,等待资源EnterCriticalSection(&RP_Write);}ReleaseMutex(h_Mutex); //释放互斥信号//读文件printf("读者线程 %d 开始读文件.\n",m_serial);Sleep(m_persist);//线程挂起//退出线程printf("读者线程 %d 完成读文件.\n",m_serial);//等待互斥信号,保证对ReadCount的访问,修改互斥wait_for_mutex=WaitForSingleObject(h_Mutex,-1);//读者数目减少readcount--;if(readcount==0){//如果所有的读者读完,唤醒写者LeaveCriticalSection(&RP_Write);}ReleaseMutex(h_Mutex); //释放互斥信号
}
//
//P:写者线程信息
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("写者线程 %d 发来写请求.\n",m_serial);//等待资源EnterCriticalSection(&RP_Write);//写文件printf("写者线程 %d 开始写文件.\n",m_serial);Sleep(m_persist);//退出线程printf("写者线程 %d 完成写文件.\n",m_serial);//释放资源LeaveCriticalSection(&RP_Write);
}
//
//读者优先处理函数
//file:文件名
void ReaderPriority(char *file)
{DWORD n_thread=0; //线程数目DWORD thread_ID; //线程IDDWORD 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; //初始化readcountInitializeCriticalSection(&RP_Write); ifstream inFile;inFile.open (file);printf("读者优先:\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("所有的读者写者完成操作.\n");
}
//写者优先---读者线程
//P:读者线程信息
void WP_ReaderThread(void *p)
{//互斥变量HANDLE h_Mutex1;h_Mutex1=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex1");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("读者线程 %d 发来读请求.\n",m_serial);wait_for_mutex1=WaitForSingleObject(h_Mutex1,-1);//读者进去临界区EnterCriticalSection(&cs_Read);//阻塞互斥对象Mutex2,保证对readCount的访问和修改互斥wait_for_mutex2=WaitForSingleObject(h_Mutex2,-1);//修改读者的数目readcount++;if(readcount==1){// 如果是第1个读者,等待写者写完EnterCriticalSection(&cs_Write);}ReleaseMutex(h_Mutex2);// 释放互斥信号 Mutex2//让其他读者进去临界区LeaveCriticalSection(&cs_Read);ReleaseMutex(h_Mutex1);//读文件printf("读者线程 %d 开始读文件.\n",m_serial);Sleep(m_persist);//退出线程printf("读者线程 %d 完成读操作.\n",m_serial);//阻塞互斥对象Mutex2,保证对readcount的访问,修改互斥wait_for_mutex2=WaitForSingleObject(h_Mutex2,-1);readcount--;if(readcount==0){//最后一个读者,唤醒写者LeaveCriticalSection(&cs_Write);}ReleaseMutex(h_Mutex2); //释放互斥信号
}
///
//写者优先---写者线程
//P:写者线程信息
void WP_WriterThread(void *p)
{DWORD wait_for_mutex3; //互斥变量DWORD m_delay; //延迟时间DWORD m_persist; //读文件持续时间int m_serial; //线程序号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("写者线程 %d 发来写请求.\n",m_serial);wait_for_mutex3=WaitForSingleObject(h_Mutex3,-1);writecount++; //修改写者数目if(writecount==1){EnterCriticalSection(&cs_Read);}ReleaseMutex(h_Mutex3);EnterCriticalSection(&cs_Write);printf("写者线程 %d 开始写文件.\n",m_serial);Sleep(m_persist);printf("写者线程 %d 完成写文件.\n",m_serial);LeaveCriticalSection(&cs_Write);wait_for_mutex3=WaitForSingleObject(h_Mutex3,-1);writecount--;if(writecount==0){LeaveCriticalSection(&cs_Read);}ReleaseMutex(h_Mutex3);
}
/
//写者优先处理函数
// file:文件名
void WriterPriority(char * file)
{DWORD n_thread=0;DWORD thread_ID;DWORD wait_for_all;HANDLE h_Mutex1;h_Mutex1=CreateMutex(NULL,FALSE,"mutex1");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("写者优先:\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)(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("所有的读者写者完成操作.\n");
}
/
//主函数
int main(int argc,char *argv[])
{char ch;while(true){printf("*************************************\n");printf(" 1.读者优先\n");printf(" 2.写者优先\n");printf(" 3.退出\n");printf("*************************************\n");printf("Enter your choice(1,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");elseWriterPriority("thread.dat");printf("\n Press Any Key to Coutinue:");_getch();system("cls");}return 0;
}
操作系统原理实验报告——读者写者相关推荐
- 操作系统原理实验-进程同步
操作系统原理实验报告 实验题目 实验二进程同步 实验二.进程同步 1.1 实验目的 现代操作系统的核心是多道程序设计.多处理器和分布式处理器,这些方案和操作系统设计技术的基础都是并发.当多个进程并发执 ...
- ZUCC_操作系统原理实验_实验九 消息队列
操作系统原理实验报告 课程名称 操作系统原理实验 实验项目名称 实验九 消息队列 实验目的 了解 Linux 系统的进程间通信机构 (IPC): 理解Linux 关于消息队列的概念: 掌握 Linux ...
- 微型计算机原理实验报告总结,微机原理实验报告-两个多位十进制数相加的实验等.doc...
微机原理实验报告-两个多位十进制数相加的实验等.doc 微机原理实验报告班级学号姓名实验一两个多位十进制数相加的实验一.实验目的学习数据传送和算术运算指令的用法熟悉在PC机上建立.汇编.链接.调试和运 ...
- 《操作系统》实验报告——熟悉Linux基础命令及进程管理
理论知识 Linux--进程管理 Linux--Linux C语言编程基础知识 手把手教你安装Linux虚拟机 一.实验目的 (1)加深对进程概念的理解,明确进程和程序的区别. (2)进一步认识并发执 ...
- 进程同步算法实现实验报告Linux,操作系统进程同步实验报告.doc
操作系统进程同步实验报告 实验三:进程同步实验 一.实验任务: (1)掌握操作系统的进程同步原理: (2)熟悉linux的进程同步原语: (3)设计程序,实现经典进程同步问题. 二.实验原理: (1) ...
- 用汇编语言与C语言实验其他排序,微机原理实验报告冒泡排序
微机原理实验报告冒泡排序 五.运行结果 (1)对300,250,280,240,260五个数进行冒泡排序,运行结果如下: (2)对-1,2,54,-38,43五个数进行冒泡排序,运行结果如下 (1)当 ...
- 通信使用matlab三元码实验报告,Matlab仿真DSBSC信号与双极性不归零码通信原理实验报告二实验...
Matlab仿真DSBSC信号与双极性不归零码通信原理实验报告二实验 Matlab 仿真 DSB-SC 信号与双极性不归零码通信原理实验报告二实验题目:Matlab 仿真 DSB-SC 信号与双极性不 ...
- matlab 2ask,(最新整理)基于MATLAB的2ASK和2FSK调制仿真(通信原理实验报告)
<(最新整理)基于MATLAB的2ASK和2FSK调制仿真(通信原理实验报告)>由会员分享,可在线阅读,更多相关<(最新整理)基于MATLAB的2ASK和2FSK调制仿真(通信原理实 ...
- ZUCC_操作系统原理实验_Lab9进程的通信消息队列
lab9进程的通信–消息队列 一.两个进程并发执行,通过消息队列,分别进行消息的发送和接收 1.代码: //接受消息 #include<stdio.h> #include<stdli ...
- 东北大学软件学院操作系统v实验报告
课程编号:B080000070 <操作系统>实验报告 姓名 学号 班级 指导教师 实验名称 <操作系统>实验 开设学期 2016 ...
最新文章
- 可持久化线段树(主席树)【舰娘系列】【自编题】
- 关于学习Python的一点学习总结(56->random的使用)
- ubuntu14.04.03 vsftpd
- 记得【黑镜】中的Whac-A-Mole游戏吗?HoloLens实现了!
- leetcode算法题--环绕字符串中唯一的子字符串★
- map初始化_需要掌握的Go基础之map:文末附面试题一道
- VTK:InfoVis之PassThrough
- springmv的执行流程是什么
- c语言小游戏 精简_一个简易的贪吃蛇小游戏C语言源码
- element解决表格错位问题
- Nginx【学习笔记】
- VINS-Mono: A Robust and Versatile Monocular Visual-Inertial State Estimator
- 浏览器无法打开xml文件解决方案
- java设置随机数教程
- 使用迅雷9.1.48从ftp服务器下载文件
- FTP网络服务器 Xlight+FlashFXP
- lca rmq 算法资料
- 电脑里的文件夹被误删了怎么恢复呢?几个步骤轻松解决
- 微信玩这个 存款惊人_英语的8个惊人新趋势
- [Pandas] DataFrame的columns属性
热门文章
- 量化指标公式源码_最牛通达信量化副图指标公式源码
- 遗传算法c语言代码实验报告,遗传算法的c语言程序
- 电子游戏销售数据分析
- 渗透神器----Windows10 渗透工具包
- Eclipse配置jdk
- 【Power Query】使用Excel抓取淘宝天猫所有类目分类和cateId对应关系
- 有一种VR电影比爱情动作片更“爽”
- Visio图片复制到word中显示不完全(毕业论文格式下)
- Zotero数据及文件同步
- 角谱 matlab,关于角谱法实现数字全息 - 程序语言 - MATLAB/Mathematica - 小木虫论坛-学术科研互动平台...