多线程实验之”生产者——消费者“问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27312943/article/details/79088963

一 实例

  参考书籍《从实践中学linux应用程序开发》

/*producer-customer.c*/
#include <stdio.h>  
#include <pthread.h>  
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ipc.h>

#define MYFIFO "myfifo" /*缓冲区有名管道的名字*/

#define BUFF_SIZE 3 /*缓冲区的单元数*/
#define UNIT_SIZE 6 /*每个单元的大小*/

#define DELAY_TIME_LEVELS 5.0 /*小任务之间的最大时间间隔*/
#define RUN_TIME 30 /*运行时间*/

sem_t mutex;  //mutex信号量用于解决两个线程之间的互斥问题
sem_t full;  //表示有界缓冲区中的非空单元数
sem_t avail; //表示有界缓冲区中的空单元数

int fd;
time_t end_time;

/*生产者线程*/
void *producer(void *arg)
{
   int delay_time=0;
   int real_write=0;
   int temp;
   
   while(time(NULL) < end_time)
   {
   	/*RAND_MAX 是 <stdlib.h> 中伪随机数生成函数 rand 所能返回的最大数值*/
        delay_time=(int)(rand()* DELAY_TIME_LEVELS/(RAND_MAX))+1;
 
        sleep(delay_time);
              
        
        /*P操作信号量avail和mutex*/
        /*P操作使sem减1*/
        temp=sem_wait(&avail);
        temp+=sem_wait(&mutex);
        printf("\nproducer:delay=%d\n",delay_time);  
        if(temp !=0 )
        {
            printf("sem_wait error\n");
            break;	
        }
        
        /*生产者写入数据*/
        if( (real_write=write(fd,"hello",UNIT_SIZE)) == -1 )
        {
            /*写入数据失败*/  /*EAGAIN : Resource temporarily unavailable*/
            if(errno==EAGAIN)
            {
                printf("the fifo has not been read yet,please try later\n");		
            }
           
        }
        else
        {
            printf("write %d to the fifo\n",real_write);	
        }	
        
        /*V操作信号量full和mutex*/
        /*V操作相当于加1*/
        sem_post(&full);
        sem_post(&mutex);  	
   } 
   pthread_exit(NULL);		
}


/*消费者进程*/
void *customer(void *arg)
{
    int delay_time=0;
    unsigned char read_buffer[UNIT_SIZE];
    int real_read;
    while(time(NULL)< end_time)
    {
    	/*RAND_MAX 是 <stdlib.h> 中伪随机数生成函数 rand 所能返回的最大数值*/
        delay_time=(int)(rand()* DELAY_TIME_LEVELS/(RAND_MAX)/2.0)+1;
        sleep(delay_time);
    	      
    	 /*P操作信号量full和mutex*/
        /*P操作相当于加1*/
    	sem_wait(&full);
        sem_wait(&mutex);
        printf("\ncustomer:delay=%d\n",delay_time);  
        memset(read_buffer,0,UNIT_SIZE);
        
        /*消费者读取数据*/
        if((real_read=read(fd,read_buffer,UNIT_SIZE)) == -1)
        {
            /*读取数据失败*/
            if(errno == EAGAIN)
            {
                printf("no data yet\n");	
            }
                             	
        }
        
        printf("read %s from fifo\n",read_buffer);
        
        /*V操作对avail和mutex*/
        sem_post(&avail);
        sem_post(&mutex); 	
    }
    
    pthread_exit(NULL);		
}


int main()
{
    pthread_t thrd_prd_id,thrd_cst_id;
    pthread_t mon_th_id;
    int ret;
    
    srand(time(NULL));
    end_time=time(NULL)+RUN_TIME;
    
    /*创建有名管道*/
    /*****************
    函数原型:int mkfifo(const char * pathname,
                         mode_t mode);
    函数参数:pathname 要创建的管道
              mode O_RDONLY 读管道
                   O_WRONLY 写管道
                   O_RDWR   读写管道
                   O_CREAT  如果管道不存在,那么创建一个新的文件
                            并用第3个参数为其设置权限
                   O_EXCL   如果使用O_CREAT时文件存在,那么返回错误信息。
                            这个参数可以测试文件是否存在
    *******************/
    if( ((mkfifo(MYFIFO,O_EXCL|O_CREAT)) < 0) && (errno != EEXIST))
    {
        printf("cannot creat fifo\n");
        return errno;	
    }
    else
    {
        printf("creat fifo success\n");	
    }
    
    /*打开管道*/
    fd=open(MYFIFO,O_RDWR);
    if(fd==-1)
    {
        printf("open fifo error,fd=%d\n",fd);
        return fd;	    
    }
    else
    {
        printf("open fifo success,fd=%d\n",fd);	
    }
    
    /*初始化互斥信号量为1*/
    /************************
    函数原型:int sem_init(sem_t *sem,int pshared,unsigned int value); 
    函数参数:sem  信号量指针
              pshared  决定信号量能否在几个进程间共享
                       !!!由于目前linux还没有实现进程间共享信号量,
                          所以这个值只能是0,表示这个信号量是当前进程的局部信号量                       
              value 信号量初始化的值
    ***************************/
    ret=sem_init(&mutex,0,1);
    ret+=sem_init(&full,0,0);
    ret+=sem_init(&avail,0,BUFF_SIZE);
    
    if(ret != 0)
    {
        printf("any semaphore initialization failed\n");
        return ret;	
    }
    else
    {
        printf("any semaphore initialization success\n");	
    }
    
    /*创建两个线程*/
    ret=pthread_create(&thrd_prd_id,NULL,producer,NULL);
    if(ret!=0)
    {
        printf("creat producer thread error\n");
        return ret;	
    }
    else
    {
        printf("creat producer thread success\n");	
    }
    
    ret=pthread_create(&thrd_cst_id,NULL,customer,NULL);
    if(ret!=0)
    {
        printf("creat customer thread error\n");
        return ret;	
    }
    else
    {
        printf("creat customer thread success\n");	
    }
    
    /*等待线程结束*/
    pthread_join(thrd_prd_id,NULL);
    pthread_join(thrd_cst_id,NULL);
    /*关闭文件*/
    close(fd);
    
    unlink(MYFIFO);
    
    return 0;	
}

运行结果



猜你喜欢

转载自blog.csdn.net/qq_27312943/article/details/79088963