Chinaunix首页 | 论坛 | 博客
  • 博客访问: 291392
  • 博文数量: 109
  • 博客积分: 2116
  • 博客等级: 大尉
  • 技术积分: 1062
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-22 15:38
文章分类

全部博文(109)

文章存档

2013年(2)

2011年(16)

2010年(90)

2009年(1)

我的朋友

分类: 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;

}

阅读(1141) | 评论(0) | 转发(0) |
0

上一篇:文件锁

下一篇:守护进程

给主人留下些什么吧!~~