实验题目
实验三 使用信号量解决生产者/消费者同步问题(lab3)
实验目的:
使用操作系统信号量机制,编写程序解决生产者/消费者同步问题。
实验内容:
1.理解Nachos的信号量是如何实现的;
2.生产者/消费者问题是如何用信号量实现的;
3.在Nachos中是如何创建并发线程的;
4.在Nachos下是如何测试和debug的.
实验环境:
虚拟机下Ubuntu Linux 16.04 LTS系统,nachos-3.4内核管理模块和MIPSCPU软件模拟模块,代码在lab3文件夹下面实现。
直接开搞!!!
刚开始我们打开lab3,无脑make一波
可怕的事儿还是发生啦.png
!
这一下就十分令人蒙b
打开了老师给的指导教程。
!!!
原来这个实验是一个半成品!
我们需要自己完善。
目前已完善的有:
main.cc
ring.cc
ring.h
剩下的prodcons就需要我们自己去努力了
那么我们就开始读文件了:先从ring开始
读文件
ring
class slot {
public:
slot(int id, int number);
slot() { thread_id = 0; value = 0;};
int thread_id;
int value;
};
class Ring {
public:
Ring(int sz); // Constructor: initialize variables, allocate space.
~Ring(); // Destructor: deallocate space allocated above.
void Put(slot *message); // Put a message the next empty slot.
void Get(slot *message); // Get a message from the next full slot.
int Full(); // Returns non-0 if the ring is full, 0 otherwise.
int Empty(); // Returns non-0 if the ring is empty, 0 otherwise.
private:
int size; // The size of the ring buffer.
int in, out; // Index of
slot *buffer; // A pointer to an array for the ring buffer.
};
可以看到,这里定义了两个类,一个是slot,一个是ring。
通过分析代码,我们得到以下结论:
Ring是一个环形缓冲类,给消费者和生产者使用
slot是被放置在ring当中的一个包装了线程的东西,存着id和value这两个信息。
main
感觉和上一个实验的main差别不大,没什么可分析的
prodcons
这个就是我们的重头戏了,经过阅读,发现有三个部分需要我们填充
-生产者
-消费者
-信号量
这三个的基础方法都在ring中有定义,我们只需要捏起来就可以了
image.png
还要注意到上面的一个变量声明,这里给我们提供了信号量的定义、申请和释放的方法。也就是说,锁是在这里定义的。
那么我们就发现,我们不知道semaphore是什么东西,发现他的代码在thread里面存在,那么就去看一下它的代码。
如图所示
发现这个就是我们的信号量嘛,有PV操作,可以实现锁。
开始写代码
生产者
需要增加代码来补充message携带的信息;
message->thread_id = which;
message->value = num;
增加向Ring中放消息前的信号量操作代码;
// Put the code for synchronization before ring->Put(message) here.
// ...
nempty->P();
mutex->P();
ring->Put(message);
增加向Ring 中放消息后的信号量操作代码。
// Put the code for synchronization after ring->Put(message) here.
// ...
mutex->V();
nfull->V();
消费者
需要增加从Ring中读消息前的信号量操作代码;
// Put the code for synchronization before ring->Get(message) here.
// ...
nfull->P();
mutex->P();
ring->Get(message);
从Ring 中读消息后的信号量操作代码
mutex->V();
nempty->V();
信号量
需要增加构造所有信号量代码;
mutex = new Semaphore("mutttt",1);
nfull = new Semaphore("nfull",0);
nempty = new Semaphore("empty",BUFF_SIZE);
增加构造缓冲池的代码;
ring = new Ring(BUFF_SIZE);
创建生产者线程的代码;
producers[i] = new Thread(prod_names[i]);
producers[i]->Fork(Producer,i);
创建消费者线程的代码
consumers[i] = new Thread(cons_names[i]);
consumers[i] -> Fork(Consumer,i);
写完了这些部分,再次make一波
报错!!!
问题出在哪里呢?
报错
发现是因为缺少了creat、write、exit和一些拼写错误
拼写错误修改中。。。
对于那几个函数缺失的问题,上网搜集资料
发现下面这个解决方案可以:
导入头文件
#include <unistd.h> //库中包含write方法
#include <fcntl.h> //库中包含creat方法
再把ring.cc中的exit方法剪切到ring.h中
保存,跑!
make成功
./nachos试一下
成功
欣慰
打开源目录,发现多了两个文件,里面就是存着我们生产者、消费者的相关信息。
0
1
发现生产者生产的居然全部都被消费者1抢走了
然后根据指导书上,添加一下随机数种子
添加随机数种子的方法在指导书里前面一个地方写了,是这样的
-rs seed-number
于是我们试验一下
命令 0
1
果然变了,那么实验就到此为止写完了。
网友评论