操作系统实验:消费者-生产者问题

  • README
  • 一、实验目的
  • 二、实验内容
  • 三、实验步骤
  • 四、主要数据结构及其说明
  • 五、程序运行时的初值和运行结果
  • 六、实验体会
  • 七、源程序

README

本实验报告仅供参考,请勿直接抄袭!

一、实验目的

通过实验,掌握 Windows 和 Linux 环境下互斥锁和信号量的实现方法,加深对临界区问题和进程同步机制的理解,同时熟悉利用 Windows API 和 Pthread API 进行多线程编程的方法。

二、实验内容

  1. 在 Windows 操作系统上,利用 Win32 API 提供的信号量机制,编写应用 程序实现生产者——消费者问题。
  2. 在 Linux 操作系统上,利用 Pthread API 提供的信号量机制,编写应用程序实现生产者——消费者问题。
  3. 两种环境下,生产者和消费者均作为独立线程,并通过 empty、full、mutex 三个信号量实现对缓冲进行插入与删除。
  4. 通过打印缓冲区中的内容至屏幕,来验证应用程序的正确性。 具体内容可参见“Operating System Concepts (Seventh Edition)” Chapter 6 后的 Project(P236-241)。

三、实验步骤

  1. 首先写出解决生产者——消费者问题的伪代码,如下图所示:
  2. 查阅Win32 API提供的信号量机制和Pthread API提供的信号量机制,掌握HANDLE、CreateSemaphore、WaitForSingleObject、ReleaseSemaphore、CreateThread和sem_t、sem_init、sem_wait、sem_post、pthread_create等变量和函数的用法;
  3. 将第1步中的伪代码实现成可运行的代码:首先声明三个信号量——互斥信号量Mutex、计数信号量Empty和计数信号量Full,再声明缓冲区Buffer(1代表该位置有产品,0代表该位置没有产品),其大小为SizeOfBuffer,其中Empty的初始值为SizeOfBuffer,Full的初始值为0,Mutex的初始值为1;然后分别根据伪代码实现生产者线程produce和消费者线程consume;最后在main()中创建多线程——5个生产者和5个生产者,并使主线程等待一定时间;

四、主要数据结构及其说明

  1. HANDLE:初始化函数为 HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName),其中第一个参数表示安全控制,一般直接传入NULL,第二个参数表示初始资源数量,第三个参数表示最大并发数量,第四个参数表示信号量名称,传入NULL表示匿名信号量,返回值为创建好的HANDLE;
    wait操作为DWORD WaitForSingleObject(HANDLE hHandle, DWORDdwMilliseconds),其中第一个参数为要等待的HANDLE,第二个参数为Timeout时间,一般设为最大值INFINITE;
    signal操作为BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount),其中第一个参数为被操作的信号量,第二个参数为增加的值,第三 个参数为指向返回信号量上次值的变量的指针,如果不需要信号量上次的值,那么这个参数可以设置为NULL,该函数如果成功返回TRUE,否则返回FALSE;
  2. sem_t:初始化函数为int sem_init(sem_t *sem, int pshared, unsigned int value),其 中第一个参数为需要初始化的sem_t的地址,第二个参数决定了信号量能否在进程之间共享,第三个参数为该信号量值的大小;
    wai操作为int sem_wait(sem_t * sem),参数为需要操作的信号量,该函数成功返回0,失败的话信号量的值不变,返回-1;
    signal操作为int sem_post(sem_t *sem),参数为需要操作的信号量,该函数成功返回0,失败 的话信号量的值不变,返回-1;

五、程序运行时的初值和运行结果

  • Windows操作系统:

  • Linux操作系统:

六、实验体会

实验中产生的错误以及原因分析以及解决过程:在Linux操作系统下使用终端运行程序时,输出文件中总是提示“段错误(核心已转储)”。在CSDN上查阅了相关资料后,首先推断可能是栈空间大小不足,于是在终端中使用ulimit -c unlimited和ulimit -s 819200两条指令扩大源文件大小以及栈空间大小。再次编译运行,发现依然出现相同的问题。排除了栈空间不足这个原因之后,推断可能是访问了不存在的内存地址,即指针越界。于是逐行检查各个涉及到指针的代码的运行状况。最后发现是刚开始的时候为图方便,在没有查看函数参数含义的情况下,直接将创建线程的函数写为了pthread_create(NULL, NULL, produce, NULL),而该函数的前两个参数是不能为NULL的,否则就会出现指针越界。将此处代码修改后,再次编译运行,发现可以正确运行了!

实验的体会及收获:不可以为求省事就不查看函数的参数列表以及每个参数的取值范围,否则就会出现很难排查出来的错误。幸好此次试验的代码体量较小,只有大约100行左右,排查错误较为简单。然而,如果是在大型实验中,像本次这种指针越界的Bug,是非常难排查出来的。所以,在今后的实验中,我不能再犯这种低级错误!

七、源程序

  • OnWindows:
#include<iostream>
#include<stdio.h>
#include<windows.h>
using namespace std;HANDLE Mutex;//互斥信号
HANDLE Full;//计数信号 ,代表目前缓冲区内有几个位置已满
HANDLE Empty;//计数信号 ,代表目前缓冲区内有几个位置是空的
const int SizeOfBuffer = 10;//缓冲区的大小,即有几个位置
int* Buffer;//缓冲区//显示缓冲区当前的存储情况
void showBuffer()
{cout << "目前缓冲区的存储情况:";for (int i = 0; i < SizeOfBuffer; ++i){cout << Buffer[i] << " ";}cout << endl;
}//生产者线程
DWORD WINAPI produce(LPVOID param)
{do{WaitForSingleObject(Empty, INFINITE);//等待缓冲区中有空位WaitForSingleObject(Mutex, INFINITE);//对缓冲区形成互斥访问//寻找缓冲区里面的一个空位置for (int i = 0; i < SizeOfBuffer; ++i){if (Buffer[i] == 0){Buffer[i] = 1;//放置产品cout<<"ID为"<<GetCurrentThreadId()<<"的生产者在缓冲区的 第"<<i<<"个位置放置一个产品"<<endl;showBuffer();break;}}ReleaseSemaphore(Mutex, 1, NULL);//释放互斥信号量MutexReleaseSemaphore(Full, 1, NULL);//使Full加一} while (true);return 0;
}//消费者线程
DWORD WINAPI consume(LPVOID param)
{do{WaitForSingleObject(Full, INFINITE);//等待缓冲区中有产品WaitForSingleObject(Mutex, INFINITE);//对缓冲区形成互斥访问//寻找缓冲区里面的一个有产品的位置for (int i = 0; i < SizeOfBuffer; ++i){if (Buffer[i] == 1){Buffer[i] = 0;//»°◊fl≤˙∆∑cout << "ID为" << GetCurrentThreadId() << "的消费者在缓冲区的第" << i << "个位置取走了一个产品" << endl;showBuffer();break;}}ReleaseSemaphore(Mutex, 1, NULL);//释放互斥信号量MutexReleaseSemaphore(Empty, 1, NULL);//使Empty加一} while (true);return 0;
}int main()
{Empty = CreateSemaphore(NULL, 10, 10, NULL);//初始化Empty,初始值设为10,最大值为10Full = CreateSemaphore(NULL, 0, 10, NULL);//初始化Full,初始值设为0,最大值为10Mutex = CreateSemaphore(NULL, 1, 1, NULL);//初始化Mutex,初始值设为1//初始化缓冲区Buffer = new int[SizeOfBuffer];for (int i = 0; i < SizeOfBuffer; ++i){Buffer[i] = 0;}//创建5个生产者线程和5个消费者线程for (int i = 0; i < 5; ++i){CreateThread(NULL, 0, consume, NULL, 0, NULL);CreateThread(NULL, 0, produce, NULL, 0, NULL);}//让主线程等待一定的时间Sleep(1000);
}
  • OnLinux:
#include<pthread.h>
#include<semaphore.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<unistd.h>
#include<semaphore.h>//缓冲区的大小,即有几个位置
#define SizeOfBuffer 5sem_t Mutex;//互斥信号量
sem_t Full;//计数信号量,代表目前缓冲区内有几个位置已满
sem_t Empty;//计数信号量,代表目前缓冲区内有几个位置为空
int *Buffer;//缓冲区,1代表有产品,0代表没有产品//显示缓冲区当前的存储情况
void showBuffer()
{printf("\t缓冲区:");for(int i = 0; i < SizeOfBuffer; ++i){printf("%d", Buffer[i]);printf(" ");}printf("\n");
}//生产者线程
void *produce(void *arg)
{do{sem_wait(&Empty);//等待缓冲区中有空位sem_wait(&Mutex);//对缓冲区形成互斥访问//寻找缓冲区里面的一个空位置for(int i = 0; i < SizeOfBuffer; ++i){if(Buffer[i] == 0){Buffer[i] = 1;//放置产品printf("%s%lu%s%d%s", "ID为", pthread_self(), "的生产者在缓冲区的第", i, "个位置放置了一个产品");showBuffer();break;}}sem_post(&Mutex);//释放互斥信号量Mutexsem_post(&Full);//使Full加1}while(true);
}//消费者线程
void *consume(void *arg)
{do{sem_wait(&Full);//等待缓冲区中有空位sem_wait(&Mutex);//对缓冲区形成互斥访问//寻找缓冲区里面的一个产品for(int i = 0; i < SizeOfBuffer; ++i){if(Buffer[i] == 1){Buffer[i] = 0;//取走产品printf("%s%lu%s%d%s", "ID为", pthread_self(), "的消费者在缓冲区的第", i, "个位置取走了一个产品");showBuffer();break;}}sem_post(&Mutex);//释放互斥信号量Mutexsem_post(&Empty);//使Empty加1}while(true);
}int main()
{//初始化Buffer数组Buffer = (int*)malloc(SizeOfBuffer*sizeof(int*));//Buffer = new int[SizeOfBuffer];for(int i = 0; i < SizeOfBuffer; ++i){Buffer[i] = 0;}sem_init(&Mutex, 1, 1);//初始化Mutex为1sem_init(&Empty, 0, 10);//初始化Empty为10sem_init(&Full, 0, 0);//初始化Full为0pthread_t tid[10];pthread_attr_t attr;pthread_attr_init(&attr);//创建5个消费者线程和5个生产者线程for(int i = 0; i < SizeOfBuffer; ++i){pthread_create(&tid[i], &attr, consume, NULL);pthread_create(&tid[i + 5], &attr, produce, NULL);}sleep(0.999);return 0;
}

【SEUSE】操作系统实验:消费者-生产者问题相关推荐

  1. 操作系统实验之生产者和消费者程序

    这是我的操作系统实验课的实验之一,实验要求"实现生产者和消费者程序". 老师给了我们示例程序,要求我们自己修改调试.程序代码如下,已经在本地linux系统上能够正确运行. p是模拟 ...

  2. 操作系统实验二·生产者消费者问题

    生产者消费者问题 1实验目的 2实验内容 3实验环境 3.1Windows 3.2Linux虚拟机 4程序设计和实现 4.1Windows实现 4.1.1函数解释 4.1.2程序代码 4.1.3运行结 ...

  3. Linux操作系统实验:生产者和消费者问题

    一.实验目的及要求 "生产者消费者"问题是一个著名的同时性编程问题的集合.通过编写经典的"生产者消费者"问题的实验,读者可以进一步熟悉 Linux 中多线程编程 ...

  4. 2021-11-02 操作系统实验3——生产者消费者实验

    文章目录 一.实验目的 二.实验任务 三.实验要求 四.实验过程 五.实验测试 一.实验目的 了解和熟悉linux系统下的信号量集和共享内存. 二.实验任务 使用linux系统提供的信号量集和共享内存 ...

  5. 操作系统实验 生产者消费者问题详解

    操作系统课程设计 生产者消费者实验报告 一.实验目的 加深对进程概念的理解,明确进程与程序的区别. 认识并发执行的本质. 理解和掌握Linux和Windows进程通信系统调用的功能,通过实验和学习,提 ...

  6. c语言生产者与消费者实验报告,生产者和消费者实验报告.doc

    生产者和消费者实验报告 [实验目的] 加深对进程概念的理解,明确进程和程序的区别. 进一步认识并发执行的实质. 验证用信号量机制实现进程互斥的方法. 验证用信号量机制实现进程同步的方法. [实验要求] ...

  7. 操作系统中消费者与生产者的同步互斥问题

    在操作系统中,我们有进程,进程会占用资源,有些资源是可以共享的,但有些资源是只允许一个占用,不能共享,只有当占用的线程用完释放后,下一个需要用的线程才可以申请使用,这样的资源便是临界资源.属于临界资源 ...

  8. C语言生产者消费者实验报告,生产者与消费者实验报告.doc

    生产者与消费者实验报告.doc 生产者和消费者实验报告[实验目的]1. 加深对进程概念的理解,明确进程和程序的区别.2. 进一步认识并发执行的实质.3. 验证用信号量机制实现进程互斥的方法.4. 验证 ...

  9. 操作系统实验报告15:进程同步与互斥线程池

    操作系统实验报告15 实验内容 实验内容:进程同步. 内容1:编译运行课件 Lecture18 例程代码. Algorithms 18-1 ~ 18-9. 内容2:在 Lab Week 13 的基础上 ...

最新文章

  1. Silverlight2 边学边练 之五 视频
  2. php 字符串去html,PHP strip_tags() 去字符串中的 HTML、XML 以及 PHP 标签的函数
  3. 有子对象的派生类的构造函数
  4. 【NOI online 2】游戏【二项式反演】【树上背包】
  5. P1002 [NOIP2002 普及组] 过河卒(python3实现)
  6. python3 ftp服务器_python3实现ftp服务功能(服务端 For Linux)
  7. Linux下清除DNS缓存
  8. Laya中使用tiledMap瓦片地图以及遇到的坑
  9. cad的dwg文件转html文件,DWG格式CAD文件如何转为图片上传到网页?
  10. 什么是局域网?什么是广域网?CCNP是什么证书?电信能提供长途数据线路吗?
  11. Drug Discov. Today | 药物发现中的先进机器学习技术
  12. Godaddy出售域名收益/收款提现探究——待续
  13. html的中性标签,HTML的figcaption标签
  14. 决策树应用实例①——泰坦尼克号分类
  15. lol进入服务器后显示3秒白屏,LOL英雄联盟游戏大厅出现白屏的完美解决方法
  16. java继承a mya new c,java – 为什么外部类不能扩展内部类?
  17. 第二代商用计算机,紫光计算机第二代商用台式机 Unis 526S/526T G2 上市
  18. 成都超级计算机中心玻璃,成都超级计算中心 年内建成投运
  19. 新视野大学英语第三版第四册读写教程第二单元-真正的美
  20. 一个本土科技精英的近况

热门文章

  1. 工具-Ditto与X mouse Button,自定义热键复制粘贴Ctrl C /V,解放双手
  2. image.paste()函数【将一张图片粘贴到另一张图片上】
  3. ingress 详解
  4. NCE损失(Negative Sampling)
  5. 第三次工业革命给中国带来的启示 --
  6. 剑侠情缘三显示连接服务器超时,剑侠情缘手游进不去怎么办?重连黑屏解决办法攻略...
  7. 一样的产品,客户为什么不去亚马逊买而选择独立站
  8. SRE(运维)就要努力做到最好
  9. 游戏策划学习:未知性与好奇心
  10. 腾讯春招提前批面试经历(已收到offer)