zoukankan      html  css  js  c++  java
  • unix及linux文件锁

    有三种不同的文件锁,这三种都是“咨询性”的,也就是说它们依靠程序之间的
    合作,所以一个项目中的所有程序封锁政策的一致是非常重要的,当你的程序需
    要和第三方软件共享文件时应该格外地小心。

    有 些程序利用诸如 FIlENAME.lock 的文件锁文件,然后简单地测试此类文件是否存在。这种方法显然不太好,因为当产生文件的进程被杀后,锁文件依然存在,这样文件也许会被永久锁住。UUCP 中把产生文件的进程号PID存入文件,但这样做仍然不保险,因为PID的利用是回收型的。

    这里是三个文件锁函数:
         flock();
         lockf();
         fcntl();

    flock()是从BSD中衍生出来的,但目前在大多数UNIX系统上都能找到,在单个主
    机上flock()简单有效,但它不能在NFS上工作。Perl中也有一个有点让人迷惑的
    flock()函数,但却是在perl内部实现的。

    fcntl()是唯一的符合POSIX标准的文件锁实现,所以也是唯一可移植的。它也同
    时是最强大的文件锁--也是最难用的。在NFS文件系统上,fcntl()请求会被递
    交给叫rpc.lockd的守护进程,然后由它负责和主机端的lockd对话,和flock()
    不同,fcntl()可以实现记录层上的封锁。

    lockf()只是一个简化了的fcntl()文件锁接口。

    无论你使用哪一种文件锁,请一定记住在锁生效之前用sync来更新你所有的文件
    输入/输出。

    代码示例1

     1       lock(fd);
     2       write_to(some_function_of(fd));
     3       flush_output_to(fd); /* 在去锁之前一定要冲洗输出 */
     4       unlock(fd);
     5       do_something_else;   /* 也许另外一个进程会更新它 */
     6       lock(fd);
     7       seek(fd, somewhere); /* 因为原来的文件指针已不安全 */
     8       do_something_with(fd); ...
     9 一些有用的fcntl()封锁方法(为了简洁略去错误处理):
    10      #include <fcntl.h>;
    11      #include <unistd.h>;
    12    
    13      read_lock(int fd)   /* 整个文件上的一个共享的文件锁 */
    14      {
    15          fcntl(fd, F_SETLKW, file_lock(F_RDLCK, SEEK_SET));
    16      }
    17    
    18      write_lock(int fd)  /* 整个文件上的一个排外文件锁 */
    19      {
    20          fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
    21      }
    22    
    23      append_lock(int fd) /* 一个封锁文件结尾的锁,
    24                             其他进程可以访问现有内容 */
    25      {
    26          fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_END));
    27      }
    28 前面所用的file_lock函数如下:
    29      struct flock* file_lock(short type, short whence)
    30      {
    31          static struct flock ret ;
    32          ret.l_type = type ;
    33          ret.l_start = 0 ;
    34          ret.l_whence = whence ;
    35          ret.l_len = 0 ;
    36          ret.l_pid = getpid() ;
    37          return &ret ;
    38      }

    代码示例2

     1 //lock.c
     2 #include <stdio.h>
     3 #include <unistd.h>
     4 #include <fcntl.h>
     5 #include <string.h>
     6 struct flock* file_lock(short type, short whence)
     7 {
     8     static struct flock ret;
     9     ret.l_type = type ;
    10     ret.l_start = 0;
    11     ret.l_whence = whence;
    12     ret.l_len = 0;
    13     ret.l_pid = getpid();
    14     return &ret;
    15 }
    16 int main()
    17 {
    18     int fd = open("1.txt", O_WRONLY|O_APPEND);
    19     for(int i=0; i<1000; ++i) {
    20         fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
    21         char buf[1024] = {0};
    22         sprintf(buf, "hello world %d/n", i);
    23         int len = strlen(buf);
    24         write(fd, buf, len);
    25         fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
    26         sleep(1);
    27     }
    28     close(fd);
    29 }
    30 //lock2.c...同lock.c相比只是修改了下buf内容
    31 #include <stdio.h>
    32 #include <unistd.h>
    33 #include <fcntl.h>
    34 #include <string.h>
    35 struct flock* file_lock(short type, short whence)
    36 {
    37     static struct flock ret;
    38     ret.l_type = type ;
    39     ret.l_start = 0;
    40     ret.l_whence = whence;
    41     ret.l_len = 0;
    42     ret.l_pid = getpid();
    43     return &ret;
    44 }
    45 int main()
    46 {
    47     int fd = open("1.txt", O_WRONLY|O_APPEND);
    48     for(int i=0; i<1000; ++i) {
    49         fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
    50         char buf[1024] = {0};
    51         sprintf(buf, "china %d/n", i);
    52         int len = strlen(buf);
    53         write(fd, buf, len);
    54         fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
    55         sleep(1);
    56     }
    57     close(fd);
    58 }
    59  
    60 g++ lock.c -o 1
    61 g++ lock2.c -o 2
    62 执行两个程序就能看到互斥的效果了
  • 相关阅读:
    https://github.com/apache/tomcat.git
    Tomcat 7最大并发连接数的正确修改方法
    如何解决svn Authorization failed错误
    Centos7下Rinetd安装与应用
    [原创]CI持续集成系统环境--Gitlab+Gerrit+Jenkins完整对接https://www.cnblogs.com/kevingrace/p/5651447.html
    git branch --set-upstream hmyq/master master
    git clone,push,pull,fetch命令详解
    差异:git clone , git fetch, git pull和git rebase
    CENTOS6.6下mysql5.7.11的percona-xtrabackup安装与备份
    Docker报错“Dockerfile parse error line 1: FROM requires either one or three arguments”
  • 原文地址:https://www.cnblogs.com/xyz123753/p/2642645.html
Copyright © 2011-2022 走看看