通过使用文件操作,仿真生产者-消费者运行模型。
本实验中需要打开两个虚拟终端,分别运行生产者程序(producer)和消费者程序(customer)。
此时两个进程同时对同一个文件进行读写操作。因为这个文件是临界资源,所以可以使用文件锁机制来保证两个进程对文件的访问都是原子操作。
文件里面就只用一个数字来表示当前的货物数量。文件中的数字最开始初始化为0。且最多容纳9个物品。
//生产者
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define N 9
int main(int argc, char *argv[])
{
int num=0;
FILE* fp;
int fd=open("fifo", O_RDWR);
if (-1==fd)
{
perror("open");
exit(-1);
}
//把文件描述符转换成对应的文件指针
fp=fdopen(fd, "r+");
//一定要把文件读写设置为无缓冲,否则有大问题
//至于是什么问题可以把底下这个if语句注释掉看看运行结果
if( setvbuf(fp, NULL, _IONBF, 0)!=0)
{
perror("setvbuf");
exit(-1);
}
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_start=0;
lock.l_whence=SEEK_SET;
lock.l_len=0;
struct flock unlock;
unlock.l_type=F_UNLCK;
unlock.l_start=0;
unlock.l_whence=SEEK_SET;
unlock.l_len=0;
while(1)
{
if (-1==fcntl(fd, F_SETLKW, &lock))
{
perror("fcntl lock");
exit(-1);
}
printf("fifo文件加锁成功!/n");
//这里就不进行出错检测了
rewind(fp);
fscanf(fp, "%d", &num);
printf("从文件中读出的num为%d/n", num);
num++;
if (num>N)
{
printf("FIFO已满!/n");
//解锁
if (-1==fcntl(fd, F_SETLK, &unlock))
{
perror("fcntl unlock");
exit(-1);
}
printf("fifo文件解锁成功!/n");
sleep(1);
}
else
{
rewind(fp);
fprintf(fp, "%d", num);
printf("生存者生产了一个物品!,当前共有%d个物品/n", num);
if (-1==fcntl(fd, F_SETLK, &unlock))
{
perror("fcntl unlock");
exit(-1);
}
printf("fifo文件解锁成功!/n");
//每隔1秒生产一个物品
sleep(1);
}
}
}
//消费者
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
int main(int argc, char *argv[])
{
int fd;
FILE* fp;
int num;
int m;
fd=open("fifo", O_RDWR);
if (-1==fd)
{
perror("open");
exit(-1);
}
fp=fdopen(fd, "r+");
//一定要把文件读写设置为无缓冲,否则有大问题
//可以把底下的if语句注释掉,看看运行结果
if (setvbuf(fp, NULL, _IONBF, 0)!=0)
{
perror("setvbuf");
exit(-1);
}
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_start=0;
lock.l_whence=SEEK_SET;
lock.l_len=0;
struct flock unlock;
unlock.l_type=F_UNLCK;
unlock.l_start=0;
unlock.l_whence=SEEK_SET;
unlock.l_len=0;
srand((unsigned int)time(NULL));
m=rand()%3+1;//每次消费的物品个数在3个以内
while(1)
{
if (-1==fcntl(fd, F_SETLKW, &lock))
{
perror("fcntl lock");
exit(-1);
}
printf("fifo文件加锁成功!/n");
rewind(fp);
fscanf(fp, "%d", &num);
printf("当前仓库有%d个物品,消费者需要消费%d个物品!/n", num, m);
if (m>num)
{
printf("当前物品不够消费!/n");
//解锁
if (-1==fcntl(fd, F_SETLK, &unlock))
{
perror("fcntl unlcok");
exit(-1);
}
printf("fifo文件解锁成功!/n");
sleep(2);
}
else
{
num-=m;
rewind(fp);
fprintf(fp, "%d", num);
printf("消费者消费了%d个物品!/n", m);
//解锁
if (-1==fcntl(fd, F_SETLKW, &unlock))
{
perror("fcntl unlcok");
exit(-1);
}
printf("fifo文件解锁成功!/n");
m=rand()%3+1;
}
}
}
fifo文件内容原始数据为0;