Linux 文件锁的分类及操作

来源:互联网 发布:linux gz解压命令 编辑:程序博客网 时间:2024/05/21 15:52

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

有些程序利用诸如 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来更新你所有的文件
输入/输出。


[cpp:nogutter] view plaincopyprint?
      lock(fd); 
      write_to(some_function_of(fd)); 
      flush_output_to(fd); /* 在去锁之前一定要冲洗输出 */ 
      unlock(fd); 
      do_something_else;   /* 也许另外一个进程会更新它 */ 
      lock(fd); 
      seek(fd, somewhere); /* 因为原来的文件指针已不安全 */ 
      do_something_with(fd); ... 
一些有用的fcntl()封锁方法(为了简洁略去错误处理): 
     #include <fcntl.h>;  
     #include <unistd.h>;  
    
     read_lock(int fd)   /* 整个文件上的一个共享的文件锁 */ 
     { 
         fcntl(fd, F_SETLKW, file_lock(F_RDLCK, SEEK_SET)); 
     } 
    
     write_lock(int fd)  /* 整个文件上的一个排外文件锁 */ 
     { 
         fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET)); 
     } 
    
     append_lock(int fd) /* 一个封锁文件结尾的锁,
                            其他进程可以访问现有内容 */ 
     { 
         fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_END)); 
     } 
前面所用的file_lock函数如下: 
     struct flock* file_lock(short type, short whence) 
     { 
         static struct flock ret ; 
         ret.l_type = type ; 
         ret.l_start = 0 ; 
         ret.l_whence = whence ; 
         ret.l_len = 0 ; 
         ret.l_pid = getpid() ; 
         return &ret ; 
     } 
      lock(fd);
      write_to(some_function_of(fd));
      flush_output_to(fd); /* 在去锁之前一定要冲洗输出 */
      unlock(fd);
      do_something_else;   /* 也许另外一个进程会更新它 */
      lock(fd);
      seek(fd, somewhere); /* 因为原来的文件指针已不安全 */
      do_something_with(fd); ...
一些有用的fcntl()封锁方法(为了简洁略去错误处理):
     #include <fcntl.h>;
     #include <unistd.h>;
  
     read_lock(int fd)   /* 整个文件上的一个共享的文件锁 */
     {
         fcntl(fd, F_SETLKW, file_lock(F_RDLCK, SEEK_SET));
     }
  
     write_lock(int fd)  /* 整个文件上的一个排外文件锁 */
     {
         fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
     }
  
     append_lock(int fd) /* 一个封锁文件结尾的锁,
                            其他进程可以访问现有内容 */
     {
         fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_END));
     }
前面所用的file_lock函数如下:
     struct flock* file_lock(short type, short whence)
     {
         static struct flock ret ;
         ret.l_type = type ;
         ret.l_start = 0 ;
         ret.l_whence = whence ;
         ret.l_len = 0 ;
         ret.l_pid = getpid() ;
         return &ret ;
     }
 
  [c-sharp] view plaincopyprint?
  //lock.c 
  #include <stdio.h> 
  #include <unistd.h> 
  #include <fcntl.h> 
  #include <string.h>  
  struct flock* file_lock(short type, short whence) 
  { 
    static struct flock ret; 
    ret.l_type = type ; 
    ret.l_start = 0; 
    ret.l_whence = whence; 
    ret.l_len = 0; 
    ret.l_pid = getpid(); 
    return &ret; 
  } 
  int main() 
  { 
    int fd = open("1.txt", O_WRONLY|O_APPEND); 
    for(int i=0; i<1000; ++i)
    { 
      fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET)); 
      char buf[1024] = {0}; 
      sprintf(buf, "hello world %d/n", i); 
      int len = strlen(buf); 
      write(fd, buf, len); 
      fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET)); 
      sleep(1); 
    } 
    close(fd); 
  } 
 
 
  //lock2.c...同lock.c相比只是修改了下buf内容 
  #include <stdio.h> 
  #include <unistd.h> 
  #include <fcntl.h> 
  #include <string.h>  
  struct flock* file_lock(short type, short whence) 
  { 
      static struct flock ret; 
      ret.l_type = type ; 
      ret.l_start = 0; 
     ret.l_whence = whence; 
      ret.l_len = 0; 
      ret.l_pid = getpid(); 
      return &ret; 
  } 
  int main() 
  { 
     int fd = open("1.txt", O_WRONLY|O_APPEND); 
      for(int i=0; i<1000; ++i) { 
          fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET)); 
          char buf[1024] = {0}; 
          sprintf(buf, "china %d/n", i); 
          int len = strlen(buf); 
          write(fd, buf, len); 
          fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET)); 
          sleep(1); 
      } 
      close(fd); 
  } 
    
  g++ lock.c -o 1 
  g++ lock2.c -o 2 
执行两个程序就能看到互斥的效果了 

0 0
原创粉丝点击