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來更新你所有的文件
輸入/輸出。


[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 
執行兩個程序就能看到互斥的效果了 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章