fcntl()记录锁

fcntl()函数实现记录锁,在文章http://blog.csdn.net/anonymalias/article/details/9197641讲解得十分详细。
这里我记录的是一些简单的概念及其使用,以后若用到,再回来深究。

1. fcntl()函数的4个常用功能

这里写图片描述
以上是fcntl()函数的常用功能,使用代码基本在http://blog.csdn.net/qq_29344757/article/details/71083191讲解。

2. 记录锁

2.1 函数接口

记录锁也是fcntl()常用功能,cmd取值有:

cmd = F_GETLK: 测试能否建立一把锁
cmd = F_SETLK: 设置锁
cmd = F_SETLKW: 阻塞设置一把锁

fcntl()函数的第3个参数为struct flock结构体类型变量,原型为:

struct flock {
    short   l_type;             //锁的类型,取值为F_RDLCK(共享读锁)、F_WRLCK(独占写锁)、F_UNLCK
    short   l_whence;           //加锁的起始位置,取值为SEEK_SET、SEEK_CUR、SEEK_END
    __kernel_off_t  l_start;    //加锁的起始偏移
    __kernel_off_t  l_len;      //上锁的字节数,为0表示从偏移处一直到文件末尾
    __kernel_pid_t  l_pid;      //已经占用锁的PID(只对F_GETLK命令有效)
    __ARCH_FLOCK_PAD
};

1) F_SETLK: 获取(l_type = F_RDLCK或者F_WRLCK)、释放(l_type = F_UNLCK)由flock结构体所描述的锁。若无法获取锁时,该函数会立即返回错误而不发生阻塞。
2) F_SETLKW: 与F_SETLKW的区别在于,无法操作锁的时候,发生阻塞
3) F_GETLK: 检测是否已经有某个锁已存在调用进程中,如果没有该锁,lock所指向的flock结构体l_type成员就会被置为F_UNLCK,否则已存在的锁的信息将会写入lock所指向的flock结构中

2.2 规则说明

记录锁相当于读写锁的一种扩展类型,在多进程中,记录锁和读写锁一样具有两种锁:共享读锁(F_RDLCK)、独占写锁(F_WRLCK)
1) 共享锁: 文件在给定字节区间,多个进程可以有一把共享读锁,那么允许多个进程以读方式访问该字节区间
2) 独占锁: 文件在给定字节区间,只能有一个进程有一把独占写锁,那么只允许有一个进程以写方式访问该字节区间。
3) 另外,文件在给定的字节区间,若有一把或多把读锁,不能在该字节区再加读写锁,同理,若有一把写锁,就不能在该字节区间再加任何读写锁

如果是在一个进程中对一个文件区间已经加了一把锁,后来该进程中又试图在同一文件区间再加一把锁,那么新锁会覆盖老锁。

测试代码: (摘自《Linux高级程序设计-第3版》P117)

进程2:

// 进程1
struct flock* file_lock(short type, short whence)
{
    static struct flock ret;

    ret.l_type = type;          //锁的类型: 共享读锁(F_RDLCK)、独占写锁(F_WRLCK)、不锁(F_UNLCK)
    ret.l_whence = whence;      //加锁的起始位置
    ret.l_start = 0;            //加锁的起始偏移
    ret.l_len = 0;              //加锁的区域长度(字节),0表示一直到末尾
    ret.l_pid = getpid();

    return &ret;
}

int main(int argc, char *argv[])
{
    int fd;
    int i;
    time_t now;

    fd = open("./tmp.file", O_WRONLY | O_APPEND);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }

    for (i = 0; i < 1000; i++)
    {
        //阻塞设置独占写锁
        fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
        time(&now);
        printf("%s\t%s F_SETLKW lock file %s for 5s\n", ctime(&now), argv[0], "tmp.file");
        char buf[1024] = {};
        sprintf(buf, "hello world %d\n", i);
        int len = strlen(buf);
        if (write(fd, buf, len))
            printf("%s\t%s write file sccess\n", ctime(&now), argv[0], "tmp.file");

        sleep(5);

        //阻塞设置解锁
        fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
        sleep(1);       
    }
    close(fd);

    return 0;
}

进程2:

struct flock* file_lock(short type, short whence)
{
    static struct flock ret;

    ret.l_type = type;          //锁的类型: 共享读锁(F_RDLCK)、独占写锁(F_WRLCK)、不锁(F_UNLCK)
    ret.l_whence = whence;      //加锁的起始位置
    ret.l_start = 0;            //加锁的起始偏移
    ret.l_len = 0;              //加锁的区域长度(字节),0表示一直到末尾
    ret.l_pid = getpid();

    return &ret;
}

int main(int argc, char *argv[])
{
    int fd;
    int i;
    time_t now;

    fd = open("./tmp.file", O_WRONLY | O_APPEND);
    if (fd < 0)
    {
        perror("open");
        return -1;
    }

    for (i = 0; i < 1000; i++)
    {
        //阻塞设置独占写锁
        fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
        time(&now);
        printf("%s\t%s F_SETLKW lock file %s for 3s\n", ctime(&now), argv[0], "tmp.file");
        char buf[1024] = {};
        sprintf(buf, "china %d\n", i);
        int len = strlen(buf);
        if (write(fd, buf, len))
            printf("%s\t%s write file sccess\n", ctime(&now), argv[0], "tmp.file");

        sleep(3);

        //阻塞设置解锁
        fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
        sleep(1);       
    }
    close(fd);

    return 0;
}

运行结果:
进程1
这里写图片描述
进程2
这里写图片描述
tmp.file的文件内容为:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值