Linux fcntl与文件锁

本文介绍了Linux中fcntl函数用于文件锁的操作,包括读锁和写锁的概念,锁的粒度,以及F_SETLK、F_SETLKW、F_GETLK等命令的使用。通过实例演示了加锁和验证过程,揭示了文件锁的加锁范围和阻塞等待的机制。
摘要由CSDN通过智能技术生成

一、基本概念

2.1 基础
  • 排他锁(互斥锁): 即同一时刻只有一个对象拥有该锁。
  • 共享锁:即同一时刻可以被多个对象拥有。
2.2 文件锁(读锁,写锁)
  • 读锁:其实就是共享锁。
  • 写锁:其实就是排他锁。

也就是说,同一文件的某个范围内的数据,可以被多个操作者同时读。但是最多只有一个操作者可以同时写。当有操作者在写时,读锁也无法获取。

简单的说就是:写的时候不可以读。没写的时候可以 同时读。如果已经获取了读锁,则写锁也将无法获取

2.2 加锁范围(实际上就是锁的粒度)

also known as byte-range, file-segment, or file-region locks
引用自:Ubuntu 20.4 man fcntl,说明了锁的范围可以是字节范围,文件段,或者是整个文件范围内的锁。

二、相关函数和数据结构声明

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

cmd 参数的可选项中有,F_SETLK / F_SETLKW / F_GETLK 三项。这些参数与锁的信息获取和设置(加锁解锁)相关。
关于fcntl可以查看:Linux fcntl 函数

struct flock {
   
     ...
     short l_type;    /* Type of lock: F_RDLCK,
                         F_WRLCK, F_UNLCK */
     short l_whence;  /* How to interpret l_start:
                         SEEK_SET, SEEK_CUR, SEEK_END */
     off_t l_start;   /* Starting offset for lock */
     off_t l_len;     /* Number of bytes to lock */
     pid_t l_pid;     /* PID of process blocking our lock
                         (set by F_GETLK and F_OFD_GETLK) */
     ...
 };

这里是从ubuntu 20.4版本的man fcntl中得到的。

// fcntl-linux.h 文件中的节选
/* For old implementation of BSD flock.  */
#ifndef F_EXLCK
# define F_EXLCK		4	/* or 3 */
# define F_SHLCK		8	/* or 4 */
#endif

从fcntl-linux.h头文件中可以看到l_type除了以上的三种,还有F_SHLCK(共享锁)和F_EXLCK(排他锁)
这里也说了,这两个宏定义只是为了兼容BSD的老的实现。所以,其实F_EXLCK(排他锁)就是F_WRLCK(写锁),F_SHLCK(共享锁)就是F_RDLCK(读锁)。

三、实例

3.1 F_SETLK验证:写的时候不可以读。没写的时候可以同时读。

为了方便验证,我编写了下面的工具代码,可以方便的进行文件加锁验证。

//fcntl_lock.c
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

int
main(int argc, char **args)
{
   
    int fd = 0;
    struct flock fl= {
   0};
    char *str_filename, *str_lock_type, *str_start, *str_len, *str_pid;
    int lock_type, start, len, pid;
    if (argc < 5) {
   
        printf(
            "usage: \n"
            "   fcntl_lock [filename] [lock_type] [start] [len] [pid]\n"
            "   lock_type: options is 0(F_RDLCK), 1(O_WRLCK), 2(O_UNLCK)\n"
            "   start: start is base from the start of the file head\n\n"
            "   Remark: the lock range is [start, start + len)\n"
            "   pid: thie param is option, to set the l_pid elem for flock struct\n"
            );
            exit(-1);
    }

    str_filename = args[1];
    str_lock_type = args[2];
    str_start = args[3];
    str_len = args[4];
    str_pid = argc >= 5 ? args[5] : NULL;

    // parse args
    lock_type = atoi(str_lock_type);
    start = atoi(str_start);
    len = atoi(str_len)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值