操作系统实验七之有限缓冲问题
来源:互联网 发布:淘宝店铺扣满48分 编辑:程序博客网 时间:2024/05/01 03:31
一、实验描述
利用有限缓冲问题的解决思想,实现生产者消费者问题,主要利用线程同步机制完成。使用三个信号量: empty (以记录有多少空位)、full (以记录有多少满位)以及mutex (二进制信号量或互斥信号量,以保护对缓冲插入与删除的操作)。对于本项目, empty 与full 将采用标准计数信号量,而mutex 将采用二进制信号量。生产者与消费者作为独立线程,在empty、full、mutex 的同步前提下,对缓冲进行插入与删除。
二、实验测试样例
测试数据文件包括n行测试数据,分别描述创建的n个线程是生产者还是消费者,以及生产者或消费者存放或取产品的开始时间和持续时间。每行测试数据包括四个字段,各个字段间用空格分隔。第一字段为一个正整数,表示线程序号。第二字段表示相应线程角色,P表示生产者,C表示消费者。第三字段为一个正数,表示存放或取出操作的开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的使用申请。第四字段为一个正数,表示操作的持续时间。第五字段为一个正数(仅生产者有),表示生产的产品号。当线程申请成功后,开始对共享资源的操作,该操作持续相应时间后结束,并释放共享资源。例如:
1 C 3 5
2 P 4 5 1
3 C 5 2
4 C 6 5
5 P 7 3 2
6 P 8 4 3
三、知识准备
Linux POSIX线程互斥和同步相关知识。
|:mutex初始化
线程的互斥量mutex数据类型是pthread_mutex_t。 使用前要对它进行初始化,有两种方法:
(1)静态分配的互斥量的初始化:
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
(2)动态分配的互斥量的初始化:
首先申请内存(malloc),再用pthread_mutex_init进行初始化。释放时,必须先调用pthread_mutex_destroy,而后再释放内存(free)。
例如:
//创建10个线程计算0~9的和。#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <errno.h>#define THREAD_NUMBER 10static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int sum =0;void* inc(void *arg) //线程执行的函数{ int i =(*(int *)arg); pthread_mutex_lock(&mutex); sum = sum +i; pthread_mutex_unlock(&mutex); return NULL;}int main(int argc, char *argv[]){ pthread_t pt[THREAD_NUMBER]; int i; int arg[THREAD_NUMBER]; for(i=0; i<THREAD_NUMBER; i++) { arg[i]=i; if(pthread_create(&pt[i], NULL, inc, (void *)&arg[i])!=0){ printf("pthread_create error\n"); exit(1); } } for(i=0; i<THREAD_NUMBER; i++) if(pthread_join(pt[i],NULL)!=0){ printf("pthread_join error\n"); exit(1); } printf("sum is %d\n",sum); pthread_mutex_destroy(&mutex); return 0;}
|:POSIX 信号量
POSIX 信号量在多线程编程中可以起到同步或互斥的作用。用POSIX 信号量可以实现传统操作系统P、V操作(即对应课本的wait、signal)。
由于POSIX信号量不是内核负责维护,所以当进程退出后,POSIX信号量自动消亡。
#include <semaphore.h>//定义信号量sem_t sem;//创建信号量int sem_init(sem_t *sem, int pshared, unsigned int value);//相当于wait操作,即申请资源。int sem_wait(sem_t * sem);//是函数sem_wait()的非阻塞版本。若信号量大于0,它直接将信号量sem的值减一并返回0;否则,它立即返回错误类型EAGAIN。int sem_trywait(sem_t * sem);//相当于signal操作,释放资源int sem_post(sem_t * sem);//获得信号量当前值int sem_getvalue(sem_t * sem, int * sval);//用来释放信号量int sem_destroy(sem_t * sem);
四、代码实现
buffer.h
#ifndef BUFFER_H_#define BUFFER_H_#include <iostream>#define BUFFER_SIZE 5using namespace std;typedef int buffer_item;struct Buffer{ Buffer(){ count = 0; front = 0; rear = 0; for(int i = 0; i < BUFFER_SIZE; i++){ items[i] = 0; } } buffer_item items[BUFFER_SIZE]; int count; int front; int rear;};int insert_item(buffer_item item);int remove_item();#endif
buffer.cpp
#include "buffer.h"Buffer *buffer = new Buffer();int insert_item(buffer_item item){ if(buffer->count < BUFFER_SIZE){ buffer->items[buffer->rear] = item; cout << "Product: " << buffer->items[buffer->rear] << endl; buffer->count++; buffer->rear++; if(buffer->rear % BUFFER_SIZE == 0) buffer->rear = 0; return 0; } return -1;}int remove_item(){ if(buffer->count > 0){ cout<< "Consume: " << buffer->items[buffer->front] << endl; buffer->items[buffer->front] = 0; buffer->count--; buffer->front++; if(buffer->front % BUFFER_SIZE == 0) buffer->front = 0; return 0; } return -1;}
deal.h
#ifndef DEAL_H_#define DEAL_H_#include <stdio.h>#include <stdlib.h>#include <string.h>#include <cstdlib>#include <iostream>using namespace std;typedef struct Data{ Data(){ serial_num = 0; character = ' '; start = 0; last = 0; product = 0; } int serial_num; char character; int start; int last; int product;} Instruction;Instruction *Deal(char file[]);#endif
deal.cpp
#include "deal.h"Instruction *Deal(char file[]){ Instruction *ins = new Data(); int i; int j = 0; string tmp = ""; int len = strlen(file); for(i = 0; i < len; i++){ if(file[i] != ' ' && file[i] != '\n') tmp += file[i]; else{ if(tmp != ""){ switch(j){ case 0: ins->serial_num = atoi(tmp.c_str()); tmp = ""; break; case 1: ins->character = tmp.at(0); tmp = ""; break; case 2: ins->start = atoi(tmp.c_str()); tmp = ""; break; case 3: ins->last = atoi(tmp.c_str()); tmp = ""; break; case 4: ins->product = atoi(tmp.c_str()); tmp = ""; break; } j++; } } } return ins;}
Main.cpp
#include <pthread.h>#include <sys/types.h>#include <semaphore.h>#include <unistd.h>#include "buffer.h"#include "deal.h"#define MAX 20struct sto{ sem_t mutex; sem_t nempty; sem_t nstored;};struct sto shared;void *produce(void *arg){ Instruction *ins = (Instruction*)arg; sem_wait(&shared.nempty); sem_wait(&shared.mutex); sleep(ins->start); insert_item(ins->product); sleep(ins->last); sem_post(&shared.mutex); sem_post(&shared.nstored); return(NULL);}void *consume(void *arg){ Instruction *ins = (Instruction*)arg; sem_wait(&shared.nstored); sem_wait(&shared.mutex); sleep(ins->start); remove_item(); sleep(ins->last); sem_post(&shared.mutex); sem_post(&shared.nempty); return(NULL);}int main(){ FILE *fp; char file[MAX]; int i; pthread_t tid_produce; pthread_t tid_consumer; Instruction *ins = new Data(); sem_init(&shared.mutex, 0, 1); sem_init(&shared.nempty, 0, 5); sem_init(&shared.nstored, 0, 0); fp = fopen("test.txt", "r"); while(fgets(file, MAX, fp)){ ins = Deal(file); if(ins->character == 'P'){ pthread_create(&tid_produce, NULL, produce, (void*)ins); } else{ pthread_create(&tid_consumer, NULL, consume, (void*)ins); } /*cout<<ins->serial_num<<" "<<ins->character<<" "; cout<<ins->start<<" "<<ins->last<<" "; cout<<ins->product<<endl;*/ } sem_destroy(&shared.mutex); sem_destroy(&shared.nempty); sem_destroy(&shared.nstored); sleep(60); return 0;}
Makefile
CC = g++objects = Main.o buffer.o deal.oMain: $(objects) $(CC) -o Main $(objects) -pthreadMain.o: Main.cppbuffer.o: buffer.hdeal.o: deal.h.PHONY: cleanclean: -rm Main $(objects)
五、实验结果
- 操作系统实验七之有限缓冲问题
- 生产者与消费者问题/有限缓冲问题
- 操作系统的有限缓冲区问题
- 操作系统实验七:保护模式之中断测试实验
- 操作系统实验六之死锁问题实验
- 操作系统实验七实验报告
- 操作系统实验之八读者优先问题
- 七、操作系统之设备管理
- 数据结构实验之二叉树七:叶子问题
- SDUT OJ 数据结构实验之二叉树七:叶子问题
- 数据结构实验之二叉树七:叶子问题
- 数据结构实验之二叉树七:叶子问题
- SDUT 3346 数据结构实验之二叉树七:叶子问题
- 数据结构实验之二叉树七:叶子问题
- 数据结构实验之二叉树七:叶子问题 (sdut OJ3346)
- 数据结构实验之二叉树七:叶子问题
- 数据结构实验之二叉树七:叶子问题
- 数据结构实验之二叉树七:叶子问题
- Java并发编程与技术内幕:线程池深入理解
- ALS推荐系统实战
- bzoj 1087 互不侵犯king 状压DP
- Activity的启动模式
- 后台向模板中分配变量不显示
- 操作系统实验七之有限缓冲问题
- caffe中 cifar10案例(四)可视化loss和accurary曲线
- Eclipse中的各种页面变量高亮显示总结
- 菜鸟 纯属笔记
- Hibernate4中使用getCurrentSession报Could not obtain transaction-synchronized Session for current thread
- 在awk中正确使用close避免文件句柄泄露
- 构造函数的补充
- Android 两个小球转动的进度条
- shell脚本截取字符串