《操作系统》课程设计报告一、读者/写者的问题模拟实现读者/写者问题,是指保证一个writer 进程必须与其他进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述:有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是只能有一个写者在写书,并且读者必优先,也就是说,读者和写者同时提出请求时,读者优先。
当读者提出请求时,需要有一个互斥操作,另外需要有一个信号量S 来确定当前是否可操作。
信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者则是这一机制的一个经典范例。
与记录型信号量解决读者——写者问题不同,信号量机制它增加了一个限制,即最多允许RN 个读者同时读。
为此,又引入了一个信号量L,并赋予初值为RN,通过执行wait (L,1,1)操作来控制读者的数目,每当有一个读者进入时,就要执行wait (L,1,1)操作,使L 的值减1。
当有RN 个读者进入读后,L 便减为0,第RN+1 个读者要进入读时,必然会因wait(L,1,1)操作失败而堵塞。
程序实例:#include <windows.h>#include <ctype.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <malloc.h>#define MAX_PERSON 100#define READER 0 //读者#define WRITER 1 //写者#define END -1#define R READER#define W WRITERtypedef struct _Person{HANDLE m_hThread;//定义处理线程的句柄int m_nType;//进程类型(读写)int m_nStartTime;//开始时间int m_nWorkTime;//运行时间int m_nID;//进程号}Person;Person g_Persons[MAX_PERSON];int g_NumPerson = 0;long g_CurrentTime= 0;//基本时间片数int g_PersonLists[] = {//进程队列1, W, 3, 5, 2, W, 16, 5, 3, R, 5, 2,4, W, 6, 5, 5, R, 4, 3, 6, R, 17,7,END,};int g_NumOfReading = 0;int g_NumOfWriteRequest = 0;//申请写进程的个数HANDLE g_hReadSemaphore;//读者信号HANDLE g_hWriteSemaphore;//写者信号bool finished = false; //所有的读完成//bool wfinished = false; //所有的写完成void CreatePersonList(int *pPersonList);bool CreateReader(int StartTime,int WorkTime,int ID);bool CreateWriter(int StartTime,int WorkTime,int ID);DWORD WINAPI ReaderProc(LPVOID lpParam);DWORD WINAPI WriterProc(LPVOID lpParam);int main(){g_hReadSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号灯,当前可用的资源数为1,最大为100g_hWriteSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号灯,当前可用的资源数为1,最大为100CreatePersonList(g_PersonLists); // Create All the reader and writersprintf("Created all the reader and writer\n 创建\n");g_CurrentTime = 0;while(true){g_CurrentTime++;Sleep(300); // 300 msprintf("CurrentTime = %d\n",g_CurrentTime);if(finished) return 0;} // return 0;}void CreatePersonList(int *pPersonLists){int i=0;int *pList = pPersonLists;bool Ret;while(pList[0] != END){switch(pList[1]){case R:Ret = CreateReader(pList[2],pList[3],pList[0]);//351,w452,523,654break; case W:Ret = CreateWriter(pList[2],pList[3],pList[0]);break;}if(!Ret)printf("Create Person %d is wrong\n",pList[0]);pList += 4; // move to next person list}}DWORD WINAPI ReaderProc(LPVOID lpParam)//读过程{Person *pPerson = (Person*)lpParam;// wait for the start timewhile(g_CurrentTime != pPerson->m_nStartTime){ }printf("Reader %d is Requesting 等待\n",pPerson->m_nID);printf("\n\n************************************************\n");// wait for the write requestWaitForSingleObject(g_hReadSemaphore,INFINITE); if(g_NumOfReading ==0) {WaitForSingleObject(g_hWriteSemaphore,INFINITE); }g_NumOfReading++;ReleaseSemaphore(g_hReadSemaphore,1,NULL);pPerson->m_nStartTime = g_CurrentTime;printf("Reader %d is Reading the Shared Buffer等待\n",pPerson->m_nID); printf("\n\n************************************************\n"); while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime) {}printf("Reader %d is Exit退出\n",pPerson->m_nID);printf("\n\n************************************************\n"); WaitForSingleObject(g_hReadSemaphore,INFINITE);g_NumOfReading--;if(g_NumOfReading == 0){ReleaseSemaphore(g_hWriteSemaphore,1,NULL);//此时没有读者,可以写}ReleaseSemaphore(g_hReadSemaphore,1,NULL);if(pPerson->m_nID == 4) finished = true; //所有的读写完成ExitThread(0);return 0;}DWORD WINAPI WriterProc(LPVOID lpParam){Person *pPerson = (Person*)lpParam;// wait for the start timewhile(g_CurrentTime != pPerson->m_nStartTime){}printf("Writer %d is Requesting 请求进行写操作\n",pPerson->m_nID);printf("\n\n************************************************\n"); WaitForSingleObject(g_hWriteSemaphore,INFINITE);// modify the writer's real start timepPerson->m_nStartTime = g_CurrentTime;printf("Writer %d is Writting the Shared Buffer写内容\n",pPerson->m_nID);while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime){}printf("Writer %d is Exit退出\n",pPerson->m_nID);printf("\n\n************************************************\n");//g_NumOfWriteRequest--;ReleaseSemaphore(g_hWriteSemaphore,1,NULL);if(pPerson->m_nID == 4) finished = true;//所有的读写完成ExitThread(0);return 0;}bool CreateReader(int StartTime,int WorkTime,int ID){DWORD dwThreadID;if(g_NumPerson >= MAX_PERSON)return false;Person *pPerson = &g_Persons[g_NumPerson];pPerson->m_nID = ID;pPerson->m_nStartTime = StartTime;pPerson->m_nWorkTime = WorkTime;pPerson->m_nType = READER;g_NumPerson++;// Create an New ThreadpPerson->m_hThread= CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread == NULL)return false;return true;}bool CreateWriter(int StartTime,int WorkTime,int ID){DWORD dwThreadID;if(g_NumPerson >= MAX_PERSON)return false;Person *pPerson = &g_Persons[g_NumPerson];pPerson->m_nID = ID;pPerson->m_nStartTime = StartTime;pPerson->m_nWorkTime = WorkTime;pPerson->m_nType = WRITER;g_NumPerson++;// Create an New ThreadpPerson->m_hThread= CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread == NULL)return false;return true;}二、进程间通信与子进程使用管道进行父子进程间通信,程序首先判断参数是否合法,因为输入的字符将从父进程通过发送到子进程中。