linux I/O编程,用fcntl()函数实现生产者消费者的程序

代码分析

  程序分析

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
int lock_set(int fd,int type)
{
    struct flock lock;
    lock.l_whence= SEEK_SET;    //设置当前位置为文件开头
    lock.l_start = 0;           //加锁区域的偏移量,与l_whence一起决定加锁区域的位置
    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 alread set by %d\n",lock.l_pid);
        }
        else if(lock.l_type == F_WRLCK)
        {                       //排斥锁,即写锁
            printf("Write lock alread 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;
    }
    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());
            }
            break;
    }
    return 0;
}
int custum()
{
    int fs,fd;
    int count;
    char c;
    if((fs = open("produce.txt",O_RDWR)) < 0)
    {
        printf("open error\n");
        return -1;
    }
//  if((fd = open("temp.txt",O_RDWR)) < 0)
//  {
//      printf("open error2\n");
//      return -1;
//  }
    while(1)
    {
        lock_set(fs,F_WRLCK);     //给fs上写锁
        lseek(fs,0,SEEK_SET);
    //  fd=open("temp.txt",O_RDWR|O_CREAT|O_TRUNC,0777);
        count=read(fs,&c,1);      //返回值是读到的字节数
        if(count <= 0)
        {
            printf("no product!\n");
            lock_set(fs,F_UNLCK); //读完了,释放锁
            sleep(1);             //延迟
            continue;
        }
        printf("get a character: %c \n",c);
        lseek(fs,0,SEEK_CUR);
    //  lseek(fd,0,SEEK_SET);
        count = 0;
        while(((count = read(fs,&c,1)) == 1) && c!= '\n')
        {
            printf("read fs: %c\n", c);             //这个whlie的作用是复制到temp
            write(fd,&c,count);   
        }
        close(fs);
        fs = open("produce.txt",O_RDWR|O_TRUNC);    //以读写重新打开,删去原程序
        lseek(fs,0,SEEK_SET);
        lseek(fd,0,SEEK_SET);
        while(((count = read(fd,&c,1)) == 1) /*&& c!='\n'*/)
        {                                           //这个while的作用是重新写回
        //  printf("read fd: %c\n", c);
            write(fs,&c,count);     
        }
        unlink("temp.txt");                         //关闭文件
        close(fd);
        lock_set(fs,F_UNLCK);
        sleep(2);
    }
}
 
int main(int argc, const char *argv[])
{
    custum();
    return 0;
}

  生产者程序分析 (上锁部分类似,不作新注释)

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
int lock_set(int fd,int type)
{
    struct flock 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 alread set by %d\n",lock.l_pid);
        }
        else if(lock.l_type == F_WRLCK)
        {
            printf("Write lock alread 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;
    }
    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());
            }
            break;
    }
    return 0;
}
int produce()
{
    int fd;
    char a='A';
    if((fd = open("produce.txt",O_WRONLY|O_APPEND)) < 0) //只读|添加方式打开文件,定位到文件末尾
    {
        printf("open failed\n");
        return -1;
    }
    while(1)
    {
        lock_set(fd,F_RDLCK);       //此处原来是上写锁,但是只有一对生产者消费者的话,应该是生产者写的时候,消费者不能读,这样的逻辑吧,如有错误还请指正
        write(fd,&a,1);
        printf("hava produce one character %c \n",a);
        a++;
        lock_set(fd,F_UNLCK);
        sleep(3);
    }
    close(fd);
}
int main(int argc, const char *argv[])
{
     
    produce();
    return 0;
}

执行结果

  左:生产者进程;右:消费者进程
执行结果

  事实上,如果把延时(即sleep函数)的值设置为10秒会很清楚地看到是生产者生产了一个字符,下一秒或者说下一时间消费者才会取出这个字符。

代码来源:https://www.cnblogs.com/jiaan/p/9351202.html