文件锁-Unix

       在unix环境中并没有限定多个进程不能读写一个文件,为此内核同步机制提供了读写锁来区分开某文件读取和写入的场景,使文件的操作保持读-写和写-写互斥,避免共享的资源产生竞争的状态。但采用强制性锁对性能的影响很大,每次读写操作都必须检查是否有锁存在,故一般情况下操作文件时是不使用锁的。

      近期开发时,需要保证某进程启动的唯一性,于是想到了读写锁的功能来实现。进程启动时,需要将该进程的pid写入指定文件中。根据unix的锁机制,如果能够获取对某文件的写入锁,就代表无相同进程在运行;否则就表示已有相同进程运行。

      当然如果要取得读锁,这个文件描述符必须被打开可以去读;如果要或者写锁,这个文件的描述符必须可以被打开可以去写。

      下面大概记录下对文件读写锁的了解:

      1.读写锁基础

      (1)flock结构体简介

                struct flock 
               {
                       short l_type; 
                       off_t l_start; 
                       short l_whence; 
                       off_t l_len; 
                       pid_t l_pid;          
               };

               l_type       : 包含三种锁类型,F_RDLCK(读取锁), F_WRLCK(写入锁),  F_UNLCK(解锁)

                                  读取锁又称为共享锁,它能够使多个进程都能在文件的同一部分建立读取锁;

                                  写入锁又称为排斥锁,在任何时刻只能有一个进程在文件的某个部分上建立写入锁;

                                  同时,读取锁和写入锁也不能同时建立。故读-写、写-写均互斥。

               l_whence : 锁开始的位置,SEEK_SET(文件开头),SEEK_CUR(文件指针的位置),SEEK_END(文件结尾)

               l_start      : 相对于l_whence的偏移量,单位为字节

                                 注:当前位置l_whence,新位置为当前位置加上偏移量

              l_len          : 长度, 字节为单位。当为0时,意味着锁的区域为可以到达的最大文件偏移位置(文件结尾)。

               l_pid        : 记录拥有锁的进程id,仅以F_GETLK形式返回即fcntl函数的cmd参数为F_GETLK时返回该值

        (2)  fcntl函数使用

              头文件#include<fcntl.h>   #include <unistd.h>

              函数原型:int fcntl(int fd, int cmd, struct flock *lock);

               fd:文件描述符

               cmd:F_GETLK:决定以flock描述的锁,是否被其他的锁阻塞。可用于探针功能-根据flock的l_type来检查文件是否可以上锁。
                         F_SETLK :设置锁。
                         F_SETLKW:对应着F_GETLK的可以阻塞的版本(wait)

              struct flock:锁的状态。

              返回值:1,出错;0,成功。

      3.使用场景

                #define read_lock(fd, offset, whence, len)     lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)

                #define write_lock(fd, offset, whence, len)    lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len)

                #define un_lock(fd, offset, whence, len)        lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len)

                //F_SETLKW  可设置阻塞

                int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) {

                       struct flock lock;

                       lock.l_type = type;

                       lock.l_start = offset;

                       lock.l_whence = whence;

                       lock.l_len = len;

                       return (fcntl(fd, cmd, &lock));

                 } 

                 在使用时可以根据errno的值来判断获取锁操作的执行状态,例如errno为EACCES或EAGAIN时代表对文件加锁失败。

                 其中,EACCES/* Permission denied */;EAGAIN/* Try again */ 。        

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值