📄 scz.txt
字号:
#include "stdio.h"
#include
#include
//Can only be used in independent situation;
//#define getmem(type) (type*)malloc(sizeof(type))
#define buffersize 5
int processnum=0;//the num of processes
struct pcb { /* 定义进程控制块PCB */
int flag;//flag=1 denote producer;flag=2 denote consumer;
int numlabel;
char product;
char state;
struct pcb* processlink;
}*exe=NULL,*over=NULL;
typedef struct pcb PCB;
PCB* readyhead=NULL,* readytail=NULL;
PCB* consumerhead=NULL,* consumertail=NULL;
PCB* producerhead=NULL,* producertail=NULL;
//产品数量
int productnum=0;
int full=0,empty=buffersize;// semaphore
char buffer[buffersize];//缓冲区
int bufferpoint=0;//缓冲区指针
void linkqueue(PCB* process,PCB** tail);
PCB* getq(PCB* head,PCB** tail);
bool hasElement(PCB* pro);
void display(PCB* p);
void linklist(PCB* p,PCB* listhead);
void freelink(PCB* linkhead);
bool processproc();
bool waitempty();
bool waitfull();
void signalempty();
void signalfull();
void producerrun();
void comsuerrun();
bool hasElement(PCB* pro);
void linklist(PCB* p,PCB* listhead)
{
PCB* cursor=listhead;
while(cursor->processlink!=NULL){
cursor=cursor->processlink;
}
cursor->processlink=p;
}
void freelink(PCB* linkhead)
{
PCB* p;
while(linkhead!=NULL){
p=linkhead;
linkhead=linkhead->processlink;
free(p);
}
}
void linkqueue(PCB* process,PCB** tail)
{
if((*tail)!=NULL){
(*tail)->processlink=process;
(*tail)=process;
}
else{
printf("队列未初始化!");
printf("资料来源:www.zhuicha.com 追查网 请保留此信息,谢谢\n");
printf("IP地址查询 手机号码归属 邮编区号 身份证验证查询 火车时刻表 成语词典 运程测算 周公解梦 在线学习手册 专业查询网\n");
}
}
PCB* getq(PCB* head,PCB** tail)
{
PCB* p;
p=head->processlink;
if(p!=NULL){
head->processlink=p->processlink;
p->processlink=NULL;
if( head->processlink ==NULL )
(*tail)=head;
}
else
return NULL;
return p;
}
bool processproc()
{
int i,f,num;
char ch;
PCB* p=NULL;
PCB** p1=NULL;
printf("\n 请输入希望产生的进程个数?");
scanf("%d",&num);
getchar();
// if(num>=100){
// printf("您怎么要产生这么多进程!Demands Denied!");
// return false;
// }
for(i=0;i printf("\n 请输入您要产生的进程:输入1为生产者进程;输入2为消费者进程\n");
scanf("%d",&f);
getchar();
p=(PCB*)malloc(sizeof(PCB)) ;
if( !p) {
printf("内存分配失败");
return false;
}
p->flag=f;
processnum++;
p->numlabel=processnum;
p->state='w';
p->processlink=NULL;
if(p->flag==1){
printf("您要产生的进程是生产者,它是第%d个进程。请您输入您要该进程产生的字符!\n",processnum);
scanf("%c",&ch);
getchar();
p->product=ch;
productnum++;
printf("您要该进程产生的字符是%c \n",p->product);
}
else {
printf("您要产生的进程是消费者,它是第%d个进程。\n",p->numlabel);
}
linkqueue(p,&readytail);
}
return true;
}
bool waitempty()
{
if(empty<=0)
{
printf("进程%d:缓冲区存数,缓冲区满,该进程进入生产者等待队列\n",exe->numlabel);
linkqueue(exe,&producertail);
return false;
}
else{
empty--;
return true;
}
}
void signalempty()
{
PCB* p;
if(hasElement(producerhead)){
p=getq(producerhead,&producertail);
linkqueue(p,&readytail);
printf("等待中的生产者进程进入就绪队列,它的进程号是%d\n",p->numlabel);
}
empty++;
}
bool waitfull()
{
if(full<=0)
{
printf("进程%d:缓冲区取数,缓冲区空,该进程进入消费者等待队列\n",exe->numlabel);
linkqueue(exe,&consumertail);
return false;
}
else{
full--;
return true;}
}
void signalfull()
{
PCB* p;
if(hasElement(consumerhead)){
p=getq(consumerhead,&consumertail);
linkqueue(p,&readytail);
printf("等待中的消费者进程进入就绪队列,它的进程号是%d\n",p->numlabel);
}
full++;
}
void producerrun()
{
if(!waitempty())
return;
printf("资料来源:www.zhuicha.com 追查网 请保留此信息,谢谢\n");
printf("IP地址查询 手机号码归属 邮编区号 身份证验证查询 火车时刻表 成语词典 运程测算 周公解梦 在线学习手册 专业查询网\n");
printf("进程%d开始向缓冲区存数%c\n",exe->numlabel,exe->product);
buffer[bufferpoint]=exe->product;
bufferpoint++;
printf("进程%d向缓冲区存数操作结束\n",exe->numlabel);
signalfull();
linklist(exe,over);
}
void comsuerrun()
{
if(!waitfull())
return;
printf("进程%d开始向缓冲区取数\n",exe->numlabel);
exe->product=buffer[bufferpoint-1];
bufferpoint--;
printf("进程%d向缓冲区取数操作结束,取数是%c\n",exe->numlabel,exe->product);
signalempty();
linklist(exe,over);
}
void display(PCB* p)
{
p=p->processlink;
while(p!=NULL){
printf("进程%d,它是一个",p->numlabel);
p->flag==1? printf("生产者\n"):printf("消费者\n");
p=p->processlink;
}
}
bool hasElement(PCB* pro)
{
if(pro->processlink==NULL)
return false;
else return true;
}
void main()
{
char terminate;
bool element;
printf("你想开始程序吗?(y/n)");
scanf("%c",&terminate);
getchar();
//Queue initialize;
readyhead=(PCB*)malloc(sizeof(PCB));
if(readyhead==NULL) return;
readytail=readyhead;
readyhead->flag=3;
readyhead->numlabel=processnum;
readyhead->state='w';
readyhead->processlink=NULL;
consumerhead=(PCB*)malloc(sizeof(PCB));
if(consumerhead==NULL) return;
consumertail=consumerhead;
consumerhead->processlink=NULL;
consumerhead->flag=4;
consumerhead->numlabel=processnum;
consumerhead->state='w';
consumerhead->processlink=NULL;
producerhead=(PCB*)malloc(sizeof(PCB));
if(producerhead==NULL) return;
producertail=producerhead;
producerhead->processlink=NULL;
producerhead->flag=5;
producerhead->numlabel=processnum;
producerhead->state='w';
producerhead->processlink=NULL;
over=(PCB*)malloc(sizeof(PCB));
if(over==NULL) return;
over->processlink=NULL;
while(terminate=='y')
{
if(!processproc()) break;
element=hasElement(readyhead);
while(element){
exe=getq(readyhead,&readytail);
printf("资料来源:www.zhuicha.com 追查网 请保留此信息,谢谢\n");
printf("IP地址查询 手机号码归属 邮编区号 身份证验证查询 火车时刻表 成语词典 运程测算 周公解梦 在线学习手册 专业查询网\n");
printf("进程%d申请运行,它是一个",exe->numlabel);
exe->flag==1? printf("生产者\n"):printf("消费者\n");
if(exe->flag==1)
producerrun();
else
comsuerrun();
element=hasElement(readyhead);
}
printf("就绪队列没有进程\n");
if(hasElement(consumerhead))
{ printf("消费者等待队列中有进程:\n");
display(consumerhead);
}
else {
printf("消费者等待队列中没有进程\n");
}
if(hasElement(producerhead))
{ printf("生产者等待队列中有进程:\n");
display(producerhead);
}
else {
printf("生产者等待队列中没有进程\n");
}
printf("你想继续吗?(press 'y' for on)");
scanf("%c",&terminate);
getchar();
}
printf("\n\n 进程模拟完成.\n");
printf("资料来源:www.zhuicha.com 追查网 请保留此信息,谢谢\n");
printf("IP地址查询 手机号码归属 邮编区号 身份证验证查询 火车时刻表 成语词典 运程测算 周公解梦 在线学习手册 专业查询网\n");
//Free the room;
freelink(over);
over=NULL;
freelink(readyhead);
readyhead=NULL;
readytail=NULL;
freelink(consumerhead);
consumerhead=NULL;
consumertail=NULL;
freelink(producerhead);
producerhead=NULL;
producertail=NULL;
getchar();
}
操作系统课程设计]生产者与消费者算法思想 与源代码
生产者与消费者算法思想
算法思想以及相关代码是网上转载的,在此申明!
只是为了方便需要的人查找而已,仅供参考!
设计思想
因为有多个缓冲区,所以生产者线程没有必要在生成新的数据之前等待最后一个数据被消费者线程处理完毕。同样,消费者线程并不一定每次只能处理一个数据。在多缓冲区机制下,线程之间不必互相等待形成死锁,因而提高了效率。
多个缓冲区就好像使用一条传送带替代托架,传送带上一次可以放多个产品。生产者在缓冲区尾加入数据,而消费者则在缓冲区头读取数据。当缓冲区满的时候,缓冲区就上锁并等待消费者线程读取数据;每一个生产或消费动作使得传送带向前移动一个单位,因而,消费者线程读取数据的顺序和数据产生顺序是相同的。
可以引入一个count计数器来表示已经被使用的缓冲区数量。用hNotEmptyEvent 和hNotFullEvent 来同步生产者和消费者线程。每当生产者线程发现缓冲区满( count=BufferSize ),它就等待hNotEmptyEvent 事件。同样,当消费者线程发现缓冲区空,它就开始等待hNotEmptyEvent。生产者线程写入一个新的数据之后,就立刻发出hNotEmptyEvent 来唤醒正在等待的消费者线程;消费者线程在读取一个数据之后,就发出hNotFullEvent 来唤醒正在等待的生产者线程。
程序的设计思想大致为:设置一while循环,pi生产者访问临界区,得到权限访问缓冲区,如果缓冲区满的,则等待,直到缓冲区非满;访问互斥锁,当得到互斥锁且缓冲区非满时,跳出while循环,开始产生新数据,并把数据存放于Buffer缓冲区中,当数据存放结束则结束临界区;接着唤醒消费者线程;ci消费者访问临界区,得到权限访问缓冲区,如果缓冲区为空,没有可以处理的数据,则释放互斥锁且等待,直到缓冲区非空;当等到缓冲区非空时,跳出while循环;消费者获得数据,并根据所获得的数据按类别消费(当消费者获得的数据为大写字母时,则把大写字母转换成小写字母,并显示;当消费者获得的数据为小写字母时,则把小写字母转换成大写字母,并显示;当消费者获得的数据为字符0、1、2、……8、9时,把这些字符直接显示到屏幕;当消费者获得的数据为符号(+、-、*、\……)时,把这些符号打印成7行7列的菱形);处理完数据后,结束临界区;接着唤醒生产者线程。
#include<stdio.h>
#include< iostream.h>
#include< windows.h>
#define BufferSize 15
char Buffer[BufferSize];
int head,tail=0;//Buffer数组下标
int count;//被使用的缓冲区数量
HANDLE hMutex;
HANDLE hNotFullEvent, hNotEmptyEvent;//用来同步生产者和消费者线程
////////缓冲区存储情况
display(char a[15])
{
int i;
cout<<"缓冲区存储情况为:"<<endl;
for (i=14;i>=0;i--){
cout<<"\t|----"<<a<<"----|"<<endl;
}
}
//p1
void p1_Producer()
{
int i;
char ch;
char p1[]={'a','A','b','B','c','C','D','d','E','e'};
if(tail<15){
for(i=0;i<10;i++){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -