Linux文件锁flock

Posted mingfeng002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux文件锁flock相关的知识,希望对你有一定的参考价值。

     表头文件  #include<sys/file.h>

  定义函数  int flock(int fd,int operation);

  函数说明  flock()会依参数operation所指定的方式对参数fd所指的文件做各种锁定或解除锁定的动作。此函数只能锁定整个文件,无法锁定文件的某一区域。

在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要锁操作来保证数据的完整性,这里介绍的针对文件的锁,称之为“文件锁”-flock。

 
flock,建议性锁,不具备强制性。一个进程使用flock将文件锁住,另一个进程可以直接操作正在被锁的文件,修改文件中的数据,原因在于flock只是用于检测文件是否被加锁,针对文件已经被加锁,另一个进程写入数据的情况,内核不会阻止这个进程的写入操作,也就是建议性锁的内核处理策略。
 

 参数  operation有下列四种情况:

  LOCK_SH 建立共享锁定。多个进程可同时对同一个文件作共享锁定。

  LOCK_EX 建立互斥锁定。一个文件同时只有一个互斥锁定。

  LOCK_UN 解除文件锁定状态。

  LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。通常与LOCK_SH或LOCK_EX 做OR(|)组合。

  单一文件无法同时建立共享锁定和互斥锁定,而当使用dup()或fork()时文件描述词不会继承此种锁定。

  返回值  返回0表示成功,若有错误则返回-1,错误代码存于errno。

 
进程使用flock尝试锁文件时,如果文件已经被其他进程锁住,进程会被阻塞直到锁被释放掉,或者在调用flock的时候,采用LOCK_NB参数,在尝试锁住该文件的时候,发现已经被其他服务锁住,会返回错误,errno错误码为EWOULDBLOCK。即提供两种工作模式:阻塞与非阻塞类型。
 
服务会阻塞等待直到锁被释放:
flock(lockfd,LOCK_EX)
服务会返回错误发现文件已经被锁住时:
ret  = flock(lockfd,LOCK_EX|LOCK_NB)
同时ret = -1, errno = EWOULDBLOCK 
 
flock锁的释放非常具有特色,即可调用LOCK_UN参数来释放文件锁,也可以通过关闭fd的方式来释放文件锁(flock的第一个参数是fd),意味着flock会随着进程的关闭而被自动释放掉。
 
flock其中的一个使用场景为:检测进程是否已经存在;
int checkexit(char* pfile){
     if (pfile == NULL)
          return -1;
     int lockfd = open(pfile,O_RDWR);
     if (lockfd == -1)
          return -2;
     int iret = flock(lockfd,LOCK_EX|LOCK_NB)
     if (iret == -1)
          return -3;

     return 0;
}

下面为两个进程的实例:

  file1.c

#include <stdio.h>  
#include <stdlib.h>  
#include <sys/file.h>  
#include <unistd.h>

int main(void)
{
    int fp = open("file_lock.test", O_WRONLY);
    int i = 20;

    if (fp == -1) //打开文件
    {
        printf("file1 open error!\n");
    }
    else{
        printf("file1 open success!\n");
    }

    if (flock(fp, LOCK_EX) != 0) //给该文件加锁
    {
        printf("file1 lock by others\n");
    }
    else{
        printf("file1 no user by others\n");
    }
    while (1) //进入循环,加锁时间为20秒,打印倒计时
    {
        printf("%d\n", i--);
        sleep(1);
        if (i == 0)
            break;
    }
    close(fp); //20秒后退出,关闭文件
    flock(fp, LOCK_UN); //文件解锁
    return 0;

}

 

 file2.c

#include <stdio.h>  
#include <stdlib.h>  
#include <sys/file.h>  
#include <unistd.h>

int main(void)
{
    int fp = open("file_lock.test", O_WRONLY);
    int i = 0;
    
    if (fp == -1) //打开文件
    {
        printf("file2 open error!\n");
    }else{
        printf("file2 open success!\n");
    }
   
    if (flock(fp, LOCK_EX) != 0) //给该文件加锁
    {
        printf("file2 lock by others\n");
    }
    else{
        printf("file2 no user by others\n");
    }
    while(1) //进入循环
    {   
        printf("%d\n", i++);
        sleep(1);
    }   
    close(fp); //关闭文件
    flock(fp, LOCK_UN); //释放文件锁
    return 0;
 
}

 

 

首先运行file1.c,紧接着运行file2.c(运行file1.c后20秒内要运行file2.c否则看不到现象)
现象是:file1.c执行起来以后,开始倒计时。此时运行file2.c会阻塞在加锁处。当file1.c运行20秒后关闭文件,并释放文件锁后,file2.c会开始运行。

 

以上是关于Linux文件锁flock的主要内容,如果未能解决你的问题,请参考以下文章

JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段

linux 生成的.o文件为啥带锁标志

为啥基于锁的程序不能组成正确的线程安全片段?

Linux互斥锁必须是全局的吗?

linux fifo 读写需要锁吗

LockSupport.java 中的 FIFO 互斥代码片段