操作系统笔记《7》-------生产者、消费者问题 。读者、写者问题 程序实现

本文探讨了操作系统中的经典同步问题——生产者消费者问题及读写者问题。通过详细解析并提供代码示例,展示了如何利用信号量、互斥锁等机制解决进程间同步问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

操作系统笔记《7》-------生产者、消费者问题 。读者、写者问题 程序实现

(2011-09-23 21:28:12)

转载

标签:

缓冲区

信号量

进程

读者

pv操作

代码实现

分类: OS

生产者------消费者问题
分析:
       
该问题的基本工作模式为:如果缓冲区为空则消费者不能取;如果缓冲区为满则生产者不可以继续生产。
                                             
如果缓冲区曼,需要唤醒消费者;如果缓冲区为空则需要唤醒生产者        
     
  N个缓冲区;
        如果只有一个信号量empty时,则:empty = N,in表示生产者放入缓冲区的商品的个数、out表示消费者取出
商品个数.in、out为共享变量。因此为了防止多个进程同时修改它们,将对他们的操作放在PV操作中。
       Producer:
                     p(empty) //如果empty==0,则生产者进程自我阻塞。
                      p(mutex)
                       in:=in+1;
                      v(mutex)
       
Consumer:
                       v(empty)
                       p(mutex)
                       out:=out+1;
                       v(mutex)
小结:以上程序缺少了唤醒操作。因此引入多个信号量。用于唤醒阻塞的进程。
       Producer:
                     p(empty) //如果empty==0,则生产者进程自我阻塞。
                      p(mutex)
                       in:=in+1 mod N;
                      v(mutex)
                      v(full)
       Consumer:
                       p(full)
                       p(mutex)
                       out:=out+1 mod N;
                       v(mutex)

                       v(empty)
对于inout取余的原因是为了用于循环。
实现程序:(锁和PV信号量)
文件:local.c
#ifndef _LOCAL_H
#define _LOCAL_H

#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/sem.h>

union semun {
    int val;
    struct semid_ds *buf;
    ushort *array;
};
typedef struct MES{
    int  num;
    int  sem1[5];//
该程序只使用了两个信号集
}MES;

#define BUFF   3
pthread_mutex_t  mutex;

struct sembuf sbuf1={0,-1,IPC_NOWAIT};
struct sembuf sbuf2={0,1,IPC_NOWAIT};
//
信号在信号集中的索引、操作类型(释放或归还)、是否阻塞
void *Producer_pthread(void *mes);
void *Consumer_pthread(void *mes);
int create_semaphore(char * path, int number, char c,union semun* sem);
//
创建了两个信号量集,empty为第一个、full为第二个
#endif

文件: producer_constum.c
#include"local.h"

int create_semaphore(char * path, int number, char c,union semun* sem)
{
//
如果number>0,表示empty信号量。
//
如果number = 0,表示full信号量。
    key_t key;
    int semid;
    if((key = ftok(path,c))==-1) {
       perror("ftok error\n");
        return -1;
    }
    if((semid= semget(key,1,IPC_CREAT|0666))==-1){
       perror("segmet error\n");
        return -1;
    }
    sem->val=  number;
    if(semctl(semid,0,SETVAL,sem)==-1){
       perror("semctl error\n");
        return -1;
    }
    return semid;
}
   
void* Consumer_pthread(void *mes)
{
    int i =0;

    while(i<10) {
       semop(((MES*)mes)->sem1[1],&sbuf1,1);
       pthread_mutex_lock(&mutex);
        sleep(1);
       printf("cumsumer:  out =  %d\n",((MES*)mes)->num+1);
       ((MES*)mes)->num = (((MES*)mes)->num+1)%BUFF;
       pthread_mutex_unlock(&mutex);
       semop(((MES*)mes)->sem1[0],&sbuf2,1);
        i++;
        sleep(1);
    }
    return NULL;
}
void* Producer_pthread(void *mes)
{
    int i=0;
    while(i<10) {
       semop(((MES*)mes)->sem1[0],&sbuf1,1);
       pthread_mutex_lock(&mutex);
       printf("producer:  in =  %d\n",((MES*)mes)->num+1);
        sleep(1);
       ((MES*)mes)->num =(((MES*)mes)->num+1)%BUFF;
       pthread_mutex_unlock(&mutex);

       sleep(1);

       printf("wakeup consumer\n");
       semop(((MES*)mes)->sem1[1],&sbuf2,1);
        i++;
    }
    return NULL;
}
int main()
{

   pthread_t   produce , consume;

   MES mes1,mes2;
    union semun  semopts1,semopts2 ;

    pthread_mutex_init(&mutex,NULL);//
建立具有默认值属性的
    mes1.num= 0;
    mes1.sem1[0]=create_semaphore(".",BUFF, 's',&semopts1);
    mes1.sem1[1]=create_semaphore(".",0, 'k',&semopts2);       
    mes2 = mes1;
    if(pthread_create(&produce,NULL,Producer_pthread,(void*)&mes1)==-1)
       printf("produce ceate fail\n");
    if(pthread_create(&consume,NULL,Consumer_pthread,(void*)&mes2)==-1)
       printf("consume create fail\n");

    pthread_join(produce,NULL);
    pthread_join(consume,NULL);
    pthread_mutex_destroy(&mutex);
    return 0;
}
 
                                   问题二

读者-----------写者问题(以缓冲区为媒介,实现读者和写者的交互)
          分析:
                 
该问题的工作原则:如果缓冲区为空时,读者不能访问缓冲区并且需要唤醒写者
                                                
如果缓冲区为满时,写者不能将信息写入缓冲区且需要唤醒读者
                                                
如果读者此时占有缓冲区,那么只允许读者进程访问该缓冲区
                                                
如果写者进程占有缓冲区,那么不允许其他进程访问该缓冲区(其他进程包括:
                                                                                                                               
读者进程和别的写者进程)
                  
由上面分析到需要下面的变量:
                                                                wm=1 rm = 1 counter = 0 (
共享变量
     
实现:
             reader :
                      if(counter >=0)//
读者进来,则阻塞写者进程 
                        p(wm)

                     p(rm)
                        counter +=1

                      v(rm)
                      

                     p(rm)//
读者读完离开
                         counter -=1;
                     v(rm)
                    if(count==0)
                       v(wm);
此时无读者进程,将写者进程唤醒。让读者和写者进程同时竞争资源
                 
                  write :
                             p(rm)
                             p(wm)
                             

                             v(wm)
                             v(rm)
                           上面分析得因为写者进程和读者进程不可以并发执行,因此需要阻塞读者进程,因此会想到对
rm
信号量进行pv操作,但是如果要看能否运行写者进程的大前提已经在读者进程中实现了,因为只有counter=0时,才会唤醒写者进程。
                          
只需要:
                
           p(wm)
                             

                            v(wm) 

代码实现(锁条件变量):
 local_cond.h文件
#ifndef _LOCAL_COND_H
#define _LOCAL_COND_H
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>

pthread_mutex_t rm ,wm;
pthread_cond_t cond;

void * Reader(void *counter);
void * Writer(void*arg);
#endif  

 reader_writer.c文件
#include"local_cond.h"

void * Reader(void * counter)
{
    while(1) {
    if(*((int*)counter) >=0)
       pthread_mutex_lock(&wm);
    pthread_mutex_lock(&rm);
    pthread_cond_wait(&cond,&wm);
    (*(int*)counter) +=1;
    printf("reader is reading\n");
    printf("Reader :=%d\n",(*(int*)counter));
    pthread_mutex_unlock(&rm);
   
    pthread_mutex_lock(&rm);
    printf("reader left \n");
    (*(int*)counter) -=1;
    printf("Reader :=%d\n",(*(int*)counter));
    pthread_cond_wait(&cond,&wm);
    pthread_mutex_unlock(&rm);
    if((*(int*)counter)==0)
       pthread_mutex_unlock(&wm);
    sleep(1);
    }
    return NULL;
}
void* Writer(void *arg)
{
    while(1) {
       pthread_mutex_lock(&wm);
       pthread_cond_wait(&cond,&wm);
       printf("Writer is writing\n");
       pthread_mutex_unlock(&wm);
       pthread_cond_signal(&cond);
        sleep(1);
    }
    return NULL;
}
int main()
{
 pthread_t reader,writer;
 int counter = 0;

 pthread_mutex_init(&rm,NULL);
 pthread_mutex_init(&wm,NULL);
 pthread_cond_init(&cond,NULL);
 
 pthread_create(&writer,NULL,(void*)Writer,NULL);
 pthread_create(&reader,NULL,(void*)Reader,(void*)&counter);

 do{
     pthread_cond_signal(&cond);
 }while(1);

 pthread_join(writer,NULL);
 pthread_join(reader,NULL);
 pthread_mutex_destory(&rm);
 pthread_mutex_destory(&wm);
 pthread_cond_destory(&cond);

 return 0;
}

分享: 分享到新浪Qing

喜欢

阅读 评论 收藏 转载 喜欢 打印举报

已投稿到:

排行榜 圈子

加载中,请稍候......

前一篇:操作系统笔记《6》-----进程间的同步和通信

后一篇:操作系统笔记《7》-------哲学家吃饭问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值