logo资料库

操作系统生产者与消费者课程设计.doc

第1页 / 共19页
第2页 / 共19页
第3页 / 共19页
第4页 / 共19页
第5页 / 共19页
第6页 / 共19页
第7页 / 共19页
第8页 / 共19页
资料共19页,剩余部分请下载后查看
《操作系统》课程设计 生产者和消费者问题 系 院:计算机科学系 学生姓名:吴伟 学 号:0734130101 专 业:软件工程 年 级:0701B 完成日期:2009 年 11 月 指导教师:刘栓
一、课程设计的性质与任务 1、生 产 者 -消 费 者 问 题 是 很 经 典 很 具 有 代 表 性 的 进 程 同 步 问 题 ,计 算 机 中 的 很 多 同 步 问 题 都 可 抽 象 为 生 产 者 -消 费 者 问 题 , 通 过 本 实 验 的 练 习 , 希 望 能 加 深 学 生 对 进 程 同 步 问 题 的 认 识 与 理 解 。 2、 熟 悉 VC 的 使 用 , 培 养 和 提 高 学 生 的 分 析 问 题 、 解 决 问 题 的 能 力 。 二、课程设计的内容及其要求 1. 实验内容 以生产者/消费者模型为依据,在 Windows 2000 环境下创建一个控制台进程,在该进程 中创建 n 个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。 2. 实验要求  学习并理解生产者/消费者模型及其同步/互斥规则;  学习了解 Windows 同步对象及其特性;  熟悉实验环境,掌握相关 API 的使用方法;  设计程序,实现生产者/消费者进程(线程)的同步与互斥;  提交实验报告。 三、课程设计的时间安排 课程设计时间 8 课时 四、课程设计的实验环境 本实验是在 winxp+VC6.0 环境下实现的,利用 Windows SDK 编制实例程序。所以试验需要 在 windows 下安装 VC 后进行。VC 是一个集成开发环境,其中包含了 Windows SDK 所有工具 和定义;所以安装了 VC 后就不用特意安装 SDK 了。
五、正文 1、实验程序的结构图(流程图); Wait Products Consume While consume 开始 Wait Buffer Produce While produce 结束 2、数据结构及信号量定义的说明; (1) CreateThread  功能——创建一个在调用进程的地址空间中执行的线程  格式 HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParamiter, DWORD dwCreationFlags, Lpdword lpThread );  参数说明 lpThreadAttributes——指向一个 LPSECURITY_ATTRIBUTES(新线程的安全性描述符)。
dwStackSize——定义原始堆栈大小。 lpStartAddress——指向使用 LPTHRAED_START_ROUTINE 类型定义的函数。 lpParamiter——定义一个给进程传递参数的指针。 dwCreationFlags——定义控制线程创建的附加标志。 lpThread——保存线程标志符(32 位) (2) CreateMutex  功能——创建一个命名或匿名的互斥量对象  格式 HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName);  参数说明 lpMutexAttributes——必须取值 NULL。 bInitialOwner——指示当前线程是否马上拥有该互斥量(即马上加锁)。 lpName——互斥量名称。 (3) CreateSemaphore  功能——创建一个命名或匿名的信号量对象  格式 HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName );  参数说明 lpSemaphoreAttributes——必须取值 NULL。 lInitialCount——信号量的初始值。该值大于 0,但小于 lMaximumCount 指定的最大值。 lMaximumCount——信号量的最大值。 lpName——信号量名称。 (4) WaitForSingleObject  功能——使程序处于等待状态,直到信号量 hHandle 出现(即其值大于等于 1)或超过
规定的等待时间  格式 DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);  参数说明 hHandle——信号量指针。 dwMilliseconds——等待的最长时间(INFINITE 为无限等待)。 (5) ReleaseSemaphore  功能——对指定信号量加上一个指定大小的量。成功执行则返回非 0 值  格式 BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lppreviousCount );  参数说明 hSemaphore——信号量指针。 lReleaseCount——信号量的增量。 lppreviousCount——保存信号量当前值。 (6) ReleaseMutex  功能——打开互斥锁,即把互斥量加 1。成功调用则返回 0  格式 BOOL ReleaseMutex(HANDLE hMutex);  参数说明 hMutex——互斥量指针。 (7) InitializeCriticalSection  功能——初始化临界区对象  格式 VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);  参数说明 lpCriticalSection——指向临界区对象的指针。 (8) EnterCriticalSection
 功能——等待指定临界区对象的所有权  格式 VOID enterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);  参数说明 lpCriticalSection——指向临界区对象的指针。 (9) LeaveCriticalSection  功能——释放指定临界区对象的所有权  格式 VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);  参数说明 lpCriticalSection——指向临界区对象的指针。 3、实验的步骤; (1) 打开 VC,选择菜单项 file->new,选择 projects 选项卡并建立一个名为" R_WP1"的 win32 console applicatoin 工程;创建时注意指定创建该工程的目录; (2) 在工程中创建源文件" R_WP1.cpp":选择菜单项 project->add to project->files,在选择框 中输入自己想要创建的文件名,这里是" R_WP1.cpp";在接下来询问是否创建新文件时回答 "yes";然后通过 Workspace->FileView->Source Files 打开该文件,在其中编辑源文件并保存. (3) 通 过调 用菜 单 命令 项 build->build all 进 行编 译连 接,可 以在 指定 的 工程 目 录下 得 到 debug-> R_WP1.exe 程序,然后把给定的 test.txt 文件存入该 debug 目录下,就可以在控制台 进入该 debug 目录运行程序了。需要强调的是在创建数据文件时,由于涉及到文件格式问题, 最好在记事本中手工逐个输入数据,而不要拷贝粘贴数据。 4、 主要算法 创建生产者和消费者线程 for(i =0;i< (int) n_Thread;i++){ if(Thread_Info[i].entity =='P') h_Thread[i]= CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Produce), &(Thread_Info[i]),0,NULL); else h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume), &(Thread_Info[i]),0,NULL);
} 生产者进程 void Produce(void *p) { //局部变量声明; DWORD wait_for_semaphore,wait_for_mutex,m_delay; int m_serial; //获得本线程的信息; m_serial = ((ThreadInfo*)(p))->serial; m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC); Sleep(m_delay); //开始请求生产 printf("Producer %2d sends the produce require.\n",m_serial); //确认有空缓冲区可供生产,同时将空位置数 empty 减 1;用于生产者和消费者的同步; wait_for_semaphore = WaitForSingleObject(empty_semaphore,-1); //互斥访问下一个可用于生产的空临界区,实现写写互斥; wait_for_mutex = WaitForSingleObject(h_mutex,-1); int ProducePos = FindProducePosition(); ReleaseMutex(h_mutex); //生产者在获得自己的空位置并做上标记后,以下的写操作在生产者之间可以并发; //核心生产步骤中,程序将生产者的 ID 作为产品编号放入,方便消费者识别; printf("Producer %2d begin to produce at position %2d.\n",m_serial,ProducePos); Buffer_Critical[ProducePos] = m_serial; printf("Producer %2d finish producing :\n ",m_serial); printf(" //使生产者写的缓冲区可以被多个消费者使用,实现读写同步; ReleaseSemaphore(h_Semaphore[m_serial],n_Thread,NULL); position[ %2d ]:%3d \n" ,ProducePos,Buffer_Critical[ProducePos]); } 消费者进程 void Consume(void * p) {
//局部变量声明; DWORD wait_for_semaphore,m_delay; int m_serial,m_requestNum; int m_thread_request[MAX_THREAD_NUM];//本消费线程的请求队列; //消费者的序列号和请求的数目; //提取本线程的信息到本地; m_serial = ((ThreadInfo*)(p))->serial; m_delay = (DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC); m_requestNum = ((ThreadInfo *)(p))->n_request; for (int i = 0;ithread_request[i]; Sleep(m_delay); //循环进行所需产品的消费 for(i =0;ithread_request[i] =-1;
分享到:
收藏