实验目的
- 加深对进程同步与互斥概念的认识
- 掌握信号量的使用,应用它解决 生产者–消费者问题
- 掌握信号量的实现原理
实验内容
- 在Ubuntu下编写程序,用信号量解决生产者-消费者问题
- 在0.11中实现信号量,用生产者-消费者程序(1)检验
在Ubuntu下编写测试程序
-
程序要求
生产者往文件中写入数字从0开始到最大为500,消费者从文件当中读取数字并更新文件,同时消费者向终端输出:
进程ID : 读取的数字
缓冲区最大10个数字。
-
分析
做信号量相关的程序需要分析哪里需要设置信号量,以及设置什么信号量。文件为空需要通知生产者写入数字,当文件为满,需要通知消费者赶快取走数据,当缓冲区数据不为空也不为满呢?这就是需要做互斥了。当生产者拿到锁进入缓冲区发现缓冲区为满那么就直接退出,或消费者拿到锁发现缓冲区为空那么也直接退出去。
-
程序设计
/** * 一个生产者+多个消费者,共享区为文件,这个文件最大存储10个数,消费者拿走一个数据的同时需要清除缓冲区数据并在终端以: * 进程ID+数字形式显示出来。 *显然,这里存在两种同步机制:互斥+资源共享。任何时刻只能有一个进程访问资源,当资源满或空需要进行资源控制 **/ #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <semaphore.h> #include <stdio.h> #include <sys/wait.h> /** * @brief 使用的信号量操作函数如下:1. sem_open()建立信号量; 2. sem_close()关闭信号量; 3. sem_wait()信号量-1; 4. sem_post()信号量+1 * @note * @param * @param * @retval */ int COUNTER =4; int main(int argc, char const *argv[]) { pid_t writer,reader[COUNTER];//writer生产者, reader消费者 int fp = open("file", O_CREAT | O_RDWR | O_TRUNC, 0666); int count=0; //记录当前共享区的数字个数 //创建信号量 sem_t* full=sem_open("/full",O_CREAT,0666,0); sem_t* empty=sem_open("/empty",O_CREAT,0666,10); sem_t* mutex=sem_open("/mutex",O_CREAT,0666,1); int tmp=0,position=0; for(int i=0;i<COUNTER;i++)//消费者进程 { pid_t cur_pid=fork(); if(cur_pid<0) { printf("fork :[%d] error\n",i); return 0; } else if(cur_pid==0) { while(1) { sem_wait(full); sem_wait(mutex); //检查是否达到缓冲区大小 lseek(fp,0,SEEK_SET); read(fp,&tmp,sizeof(int)); if(tmp==500) //达到极限 { sem_post(mutex); sem_post(full); break; } //如果没达到就读取 position=(tmp+1)%500+1; lseek(fp,position*sizeof(int),SEEK_SET); read(fp,&tmp,sizeof(int)); printf("%d : %d\n",getpid(),tmp); fflush(stdout); //将本次读取的数据写入标志位(数组下标为0的位置 ) lseek(fp,0,SEEK_SET); write(fp,(void *)&tmp,sizeof(int)); //释放信号量 sem_post(mutex); sem_post(empty); } return 0; } } /** * @brief 在生产者进程加入数据时需要更新标志位, * @note * @retval None */ for(int i=0;i<500+COUNTER+1;i++) { sem_wait(empty); sem_wait(mutex); position=(i%500)+1