zoukankan      html  css  js  c++  java
  • 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!
    ");
        }
        else{
            printf("file1 open success!
    ");
        }
    
        if (flock(fp, LOCK_EX) != 0) //给该文件加锁
        {
            printf("file1 lock by others
    ");
        }
        else{
            printf("file1 no user by others
    ");
        }
        while (1) //进入循环,加锁时间为20秒,打印倒计时
        {
            printf("%d
    ", 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!
    ");
        }else{
            printf("file2 open success!
    ");
        }
       
        if (flock(fp, LOCK_EX) != 0) //给该文件加锁
        {
            printf("file2 lock by others
    ");
        }
        else{
            printf("file2 no user by others
    ");
        }
        while(1) //进入循环
        {   
            printf("%d
    ", 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会开始运行。

     1、4个文件,a进程文件a1,a2,b进程b1,b2
    2、a进程加锁文件a1,b进程加锁文件b1
    3、a进程创建a2文件,然后轮询查看b2文件是否存在(这里可以轮询,因为时间很短),不存在代表b进程还没创建,b进程同理
    4、a进程轮询到b2文件存在了,代表b进程已经创建并可能在对b1文件加锁,此时删除文件b2,代表a进程已经加锁完毕,允许b进程读取a进程的锁,b进程同理
    5、a进程监听文件a2,如果a2被删除,代表b进程进行到了步骤4已经对b1加锁完成,可以开始读取b1文件的锁(不能直接监听a2文件删除,也就是不能跳过34步,这也是最难想的一部分,如果那样可能此时b进程还没创建,和b进程创建完成并加锁完成的状态是一样的,就会让进程a误以为进程b加锁完成),b进程同理

    a.c

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <sys/file.h>  
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h> 
    
    #define a1 "a1"
    #define a2 "a2"
    #define b1 "b1"
    #define b2 "b2"
    
    
    void  observer_file_exist(char* file_path){
        int lockFD = access(file_path, F_OK);
        while (lockFD == -1){
            lockFD = access(file_path, F_OK);
            printf("wait %s create!
    ", file_path);
            sleep(1);
        }
        printf("%s create  finish!
    ", file_path);
    }
    
    void  observer_file_delete(char* file_path){
        int lockFD = access(file_path, F_OK);
        while (lockFD != -1){
            lockFD = access(file_path, F_OK);
            printf("wait %s  to be delete!
    ", file_path);
            sleep(1);
        }
        printf("%s create  finish!
    ", file_path);
    }
    
    void remove_path_file(char* file_path){
        int lockFD = access(file_path,F_OK);
        if(lockFD!=-1){
            printf("%s exsit  remove  ... ing!
    ",file_path);
            int result=remove(file_path);
            printf("%s exsit remove  finish!
    ",file_path);
        }else{
             printf("%s not exsit!
    ",file_path);
        }
    }
    
    int main(void)
    {
    
        int fd1 = open(a1, O_WRONLY | O_CREAT,0777);;
        if (fd1 == -1) //打开文件
        {
            printf("%s has been created and completed !
    ", a1);
        }
        else{
            printf("%s crate success!
    ", a1);
        }
    
        if (flock(fd1, LOCK_EX) != 0) //给该文件加锁
        { 
             printf("no user by others, %s lock success
    ",a1);
        }else{
             printf("lock by others ,%s lock fail 
    ",a1);
        }
    
        int fd2 = open(a2, O_WRONLY | O_CREAT,0777);;
        if (fd2 == -1) //打开文件
        {
            printf("%s has been created and completed !
    ", a2);
        }
        else{
            printf("%s crate success!
    ", a2);
        }
        close(fd2);
        observer_file_exist(b2);
        remove_path_file(b2);
        observer_file_delete(a2);
        printf("b process  crate success!
    ");
        
        printf("wait %s release lock.
    ",b1);
        int fdb1 = open(b1, O_WRONLY);
        if (flock(fdb1, LOCK_EX) == 0){
            printf("%s the file was unlocked 
    ",b1);
        }else{
            printf("%s the file was not unlocked. 
    ",b1);
        }
    
        //close(fd1); 
        return 0;
    
    }

    b.c

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <sys/file.h>  
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h> 
    
    #define a1 "a1"
    #define a2 "a2"
    #define b1 "b1"
    #define b2 "b2"
    
    
    void  observer_file_exist(char* file_path){
        int lockFD = access(file_path,F_OK);
        while(lockFD == -1){
            lockFD = access(file_path,F_OK);
            printf("wait %s create!
    ",file_path);
            sleep(1);
        }
      printf("%s create  finish!
    ",file_path);
    }
    
    void  observer_file_delete(char* file_path){
        int lockFD = access(file_path,F_OK);
        while(lockFD != -1){
            lockFD = access(file_path,F_OK);
            printf("wait %s to be  delete!
    ",file_path);
            sleep(1);
        }
      printf("%s create  finish!
    ",file_path);
    }
    
    void remove_path_file(char* file_path){
        int lockFD = access(file_path,F_OK);
        if(lockFD!=-1){
            printf("%s exsit  remove  ... ing!
    ",file_path);
            int result=remove(file_path);
            printf("%s exsit remove  finish!
    ",file_path);
        }else{
             printf("%s not exsit!
    ",file_path);
        }
    }
    
    int main(void)
    {
        
        int fd1 = open(b1, O_WRONLY|O_CREAT,0777);;
        if (fd1 == -1) //打开文件
        {
            printf("%s has been created and completed !
    ",b1);
        }else{
            printf("%s crate success!
    ",b1);
        }
        
         if (flock(fd1, LOCK_EX) == 0) //给该文件加锁
        { 
             printf("no user by others, %s lock success
    ",b1);
        }else{
             printf("lock by others ,%s lock fail 
    ",b1);
        }
        
         
        int fd2 = open(b2, O_WRONLY|O_CREAT,0777);;
        if (fd2 == -1) //打开文件
        {
            printf("%s has been created and completed !
    ",b2);
        }else{
            printf("%s crate success!
    ",b2);
        }
        close(fd2); 
        observer_file_exist(a2);
        remove_path_file(a2);
        observer_file_delete(b2);
        printf("a process  crate success!
    ");
        
        printf("wait %s release lock.
    ",a1);
        int fda1 = open(a1, O_WRONLY);
        if(flock(fda1, LOCK_EX)==0){
            printf("%s the file was unlocked.
    ",a1);
        }
        else{
            printf("%s the file was not unlocked.
    ",a1);
        }
    
        //close(fd1);
        return 0;
    
    }
  • 相关阅读:
    java 中文排序 中文拼音排序 pinyin4j (怡,阿等) 拂晓风起
    jQuery 和 json 简单例子(注意callback函数的处理!!) (servlet返回json,jquery更新,java json) 拂晓风起
    推荐一个免费在线制作Banner的好地方
    Jquery焦点图/幻灯片效果 插件 KinSlideshow
    C#关于伪静态页面的两种实现方法
    cu3er 3D幻灯切换效果 div被遮住的解决方法
    推荐一个亲子教学网站,悟空学字
    怎么通过小米账号查出买家的手机号?
    添加网页桌面快捷方式的代码
    卖小米资格号怎么才不会受骗,怎么才不会淘宝退款?
  • 原文地址:https://www.cnblogs.com/mingfeng002/p/7016321.html
Copyright © 2011-2022 走看看