这是操作系统期中考试时我写的小论文,想要文档及代码的点击下载。
要求如下:
本篇为了简洁,只贴有用的信息。
执行逻辑说明:
程序启动后首先初始化信号量集和循环缓冲队列。然后按照提示信息输入生产者数量和消费者数量。根据生产者和消费者数量创建相应的生产者线程和消费者线程。生产者线程执行生产者函数,向缓冲区放一个值,然后write指针加1。消费者执行消费者函数,从缓冲区读一个值,然后read指针加1。
源码如下:
/* pc.c:Producer and Consumer Problem *author : houjialin *To compile: g++ pc.c -o pc -l pthread */ #include<stdio.h> #include<stdlib.h>//exit #include<sys/types.h> #include<sys/ipc.h> #include<sys/sem.h> #include<pthread.h> #include <unistd.h>//sleep #include<signal.h> #define Maxbuf 10 //定义循环缓冲队列及对其的一组操作 struct Circlebuf//循环缓冲队列结构 { int read;//读指针 int write;//写指针 int buf[Maxbuf];//缓冲区 } circlebuf; void writeCirclebuf(Circlebuf *circlebuf,int *value)//向缓冲区中写一个值 { circlebuf->buf[circlebuf->write]=(*value); circlebuf->write=(circlebuf->write+1)%Maxbuf;//写过后指针+1 } int readCirclebuf(Circlebuf *circlebuf)//从当前指针读一个值,返回value { int value=0; value=circlebuf->buf[circlebuf->read]; circlebuf->buf[circlebuf->read]=0; //读过后置0 circlebuf->read=(circlebuf->read+1)%Maxbuf;//读过后read+1 return value; } void OutCirclebuf(Circlebuf *circlebuf) { printf("Circlebuf value:"); for(int i=0;i<Maxbuf;i++) { printf("%d ", circlebuf->buf[i]); } printf("\n"); } //定义信号量及对其的操作 #define SEM_Key 4001 //信号量Key值 struct sembuf semaphore;//定义一个信号量 int semid;//信号量ID bool initSembuf()//创建信号量集,并初始化 { int sem=0; if((semid=semget(SEM_Key,3,IPC_CREAT|0666))>=0) { sem=1; semctl(semid,0,SETVAL,sem);//第0个信号量,初值为1,缓冲区互斥使用(mutex) sem=10; semctl(semid,1,SETVAL,sem);//第1个信号量,初值为10,当前空缓冲区数(empty) sem=0; semctl(semid,2,SETVAL,sem);//第2个信号量,初值为0,当前满缓冲区数(full) return true; } else return false; } //对信号量的PV操作 void Pmutex() { semaphore.sem_num=0; semaphore.sem_op=-1; semaphore.sem_flg=SEM_UNDO; semop(semid,&semaphore,1); } void Vmutex() { semaphore.sem_num=0; semaphore.sem_op=1; semaphore.sem_flg=SEM_UNDO; semop(semid,&semaphore,1); } void Pempty() { semaphore.sem_num=1; semaphore.sem_op=-1; semaphore.sem_flg=SEM_UNDO; semop(semid,&semaphore,1); } void Vempty() { semaphore.sem_num=1; semaphore.sem_op=1; semaphore.sem_flg=SEM_UNDO; semop(semid,&semaphore,1); } void Pfull() { semaphore.sem_num=2; semaphore.sem_op=-1; semaphore.sem_flg=SEM_UNDO; semop(semid,&semaphore,1); } void Vfull() { semaphore.sem_num=2; semaphore.sem_op=1; semaphore.sem_flg=SEM_UNDO; semop(semid,&semaphore,1); } void sigend(int sig) { semctl(semid, IPC_RMID, 0); exit(0); } void * productThread(void *i)//生产者线程 { int *n=(int *)i; while(true) { Pempty();//① Pmutex();//② writeCirclebuf(&circlebuf,n); printf("Producer %d succeeded put a value=%d into the circlebuf.\n",*n,*n); OutCirclebuf(&circlebuf); Vmutex();//③ Vfull();//④ } } void * consumerThread(void *i)//消费者 { int *n=(int *)i; int value=0;//消费品存放处 while(true) { Pfull();//⑤ Pmutex();//⑥ value=readCirclebuf(&circlebuf); printf("The consumer %d succeful consume .The value is %d \n",*n,value); Vmutex();//⑦ Vempty();//⑧ } } int main() { While(! initSembuf());//初始化信号量集 signal(SIGINT, sigend); signal(SIGTERM, sigend); int ConsNum=0,ProdNum=0,ret;//初始化生产者消费者数量 pthread_t cpid,ppid;//线程ID //初始化循环缓冲队列 circlebuf.read=circlebuf.write=0; for(int i=0;i<Maxbuf;i++) { circlebuf.buf[i]=0; } printf("Please input the number of producter :"); scanf("%d",&ProdNum); int *pro=new int[ProdNum]; printf("Please input the number of consumer :"); scanf("%d",&ConsNum); int *con=new int[ConsNum]; for(int i=1;i<=ProdNum;i++)//启动生产者 { ppid=i+100;//为了和消费者线程ID区别,每个线程号都加100 pro[i-1]=i; ret=pthread_create(&ppid,NULL,productThread,(void *)&pro[i-1]);// if(ret!=0) { printf("Create thread error"); exit(1); } } for(int i=1;i<=ConsNum;i++)//启动消费者 { cpid=i; con[i-1]=i; ret=pthread_create(&cpid,NULL,consumerThread,(void *)&con[i-1]); if(ret!=0) { printf("Create thread error"); exit(1); } } sleep(100000);//不让main线程停止 }编程平台说明:
操作系统:Ubuntu11.04
编译器: g++
同步机制:采用Linux下的信号量机制实现并发进程间的同步和互斥。源程序建立的信号量集中有三个信号量。第一信号量初值为1,缓冲区互斥时使用。第二个初值为10,相当于当前可用空缓冲区数量。第三个初值为0,表示当前已放入产品的缓冲区数量。
静态条件说明和执行结果分析:
(由于格式换着太麻烦了,这里直接上图片了。)