版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}
运行结果