分类: LINUX
2010-07-09 11:11:54
今天完成一个经典模型生产者-消费者实验。
1 应用了文件操作的知识
常用函数open,read,write,fcntl
2 利用FIFO通信方式实现
源代码来自华清远见:
生产者
#include
#include
#include
#include
#include
#include"lock_set.c"
#define MAXLEN 10
#define ALPHABET 1
#define ALPHABET_START 'a'
#define COUNT_OF_ALPHABET 26
#define DIGIT 2
#define DIGIT_START '0'
#define COUNT_OF_DIGIT 10
#define SIGN_TYPE ALPHABET
const char *fifo_file = "./myfifo";
char buff[MAXLEN];
/*生产一个字符并写入FIFO中*/
int product(void)
{
int fd;
unsigned int sign_type, sign_start, sign_count, size;
static unsigned int counter = 0;
if((fd = open(fifo_file, O_CREAT|O_RDWR|O_APPEND, 0644)) < 0)//打开FIFO
{
printf("open fifo file error!\n");
exit(1);
}
sign_type = SIGN_TYPE;
switch(sign_type)
{
case ALPHABET://英文字符
{
sign_start = ALPHABET_START;
sign_count = COUNT_OF_ALPHABET;
}
break;
case DIGIT://数字字符
{
sign_start = DIGIT_START;
sign_count = COUNT_OF_DIGIT;
}
break;
default:
{
return -1;
}
}
sprintf(buff, "%c", (sign_start + counter));
counter = (counter + 1) % sign_count;
lock_set(fd, F_WRLCK);//写入锁
if((size = write(fd, buff, strlen(buff))) < 0)
{
printf("producer: write error\n");
return -1;
}
lock_set(fd, F_UNLCK);//解锁
close(fd);
return 0;
}
int main(int argc, char *argv[])
{
int time_step = 1;//生产周期
int time_life = 10;//需要生产的数目
if(argc > 1)
{
sscanf(argv[1], "%d", &time_step);//第一个参数是生产周期
}
if(argc > 2)
{
sscanf(argv[2], "%d", &time_life);//第二个参数是生产数目
}
while(time_life--)
{
if(product() < 0)
{
break;
}
sleep(time_step);
}
exit(EXIT_SUCCESS);
}
消费者
#include
#include
#include
#include
#include"lock_set.c"
#define MAX_FILE_SIZE 100*1024*1024
const char *fifo_file = "./myfifo";
const char *tmp_file = "./tmp";
/*资源消费函数*/
int customing(const char *myfifo, int need)
{
int fd;
char buff;
int counter = 0;
if((fd = open(myfifo, O_RDONLY)) < 0)//打开管道
{
printf("function customing error\n");
return -1;
}
printf("enjoy:");
lseek(fd, SEEK_SET, 0);
while(counter < need)
{
while((read(fd, &buff, 1) == 1) && (counter < need))//读管道
{
fputc(buff, stdout);
counter++;
}
}
fputs("\n", stdout);
close(fd);//关闭
return 0;
}
/*文件复制函数*/
int myfilecopy(const char *sour_file, const char *dest_file, int offset, int count, int copy_mode)
{
int in_file, out_file;
int counter = 0;
char buff_unit;
if((in_file = open(sour_file, O_RDONLY|O_NONBLOCK)) < 0)
{
printf("function myfilecopy error in source file\n");
return -1;
}
if((out_file = open(dest_file, O_CREAT|O_RDWR|O_TRUNC|O_NONBLOCK, 0644)) < 0)
{
printf("function myfilecopy error in destination file\n");
return -1;
}
lseek(in_file, offset, SEEK_SET);
while((read(in_file, &buff_unit, 1) == 1) && (counter < count))
{
write(out_file, &buff_unit, 1);
counter++;
}
close(in_file);
close(out_file);
return 0;
}
/*实现消费函数*/
int custom(int need)
{
int fd;
customing(fifo_file, need);//need标示消费的数目
if((fd = open(fifo_file, O_RDWR)) < 0)
{
printf("function myfilecopy error in source_file:\n");
return -1;
}
lock_set(fd, F_WRLCK);//写入锁
myfilecopy(fifo_file, tmp_file, need, MAX_FILE_SIZE, 0);
myfilecopy(tmp_file, fifo_file, 0, MAX_FILE_SIZE, 0);
lock_set(fd, F_UNLCK);//解锁
unlink(tmp_file);
close(fd);
return 0;
}
int main(int argc, char *argv[])
{
int customer_capacity = 10;
if(argc > 1)//参数指定消费的资源数
{
sscanf(argv[1], "%d", &customer_capacity);
}
if(customer_capacity > 0)
{
custom(customer_capacity);
}
exit(EXIT_SUCCESS);
}
编译以后,在两个终端运行。1号生产,2号消费。
结果如下:
可以看到生产了5个字母:abcde
可以看到消费了3个字母,剩下2个:de
另外代码中用到的lock_set函数代码附在下面:
int lock_set(int fd, int type)
{
struct flock old_lock, lock;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=0;
lock.l_type=type;
lock.l_pid=-1;
//判断是否可以上锁
fcntl(fd, F_GETLK, &lock);
if(lock.l_type!=F_UNLCK)
{
if(lock.l_type==F_RDLCK)//已有读取锁
{
printf("read lock already set by %d\n", lock.l_pid);
}
else if(lock.l_type==F_WRLCK)//已有写入锁
{
printf("write lock already set by %d\n",lock.l_pid);
}
}
lock.l_type=type;//可能已近被修改
if((fcntl(fd, F_SETLKW, &lock))<0)
{
printf("lock failed:type=%d\n",lock.l_type);
return 1;
}
//根据不同TYPE进行上锁
switch(lock.l_type)
{
case F_RDLCK:
{
printf("read lock set by %d\n",getpid());
}
break;
case F_WRLCK:
{
printf("write lock set by %d\n",getpid());
}
break;
case F_UNLCK:
{
printf("release lock by %d\n",getpid());
return 1;
}
break;
default:
break;
}
return 0;
}