檔案鎖fcntl()函式的使用

2puT發表於2016-07-09

問:為什麼要使用檔案鎖?

答:當多個使用者共同使用、操作一個檔案的情況時,Linux採用的方法就是給檔案上鎖,來避免共享的資源產生競爭的狀態。

問:檔案鎖有哪些型別?

答:檔案鎖包括建議性鎖和強制性鎖。一般情況下,核心和系統都不適用建議性鎖,採用強制性鎖的影響很大,每次讀寫操作都必須檢查是否有所存在。

問:怎樣實現檔案上鎖?

答:在Linux中,實現檔案上鎖的函式有lockf() 和fcntl() ,其中lockf()用於對檔案施加建議性鎖,而fcntl() 不僅可以施加建議性鎖,而且可以施加強制性鎖。fcntl()還能對檔案的某一記錄上鎖,也就是記錄鎖。記錄鎖又可分讀取鎖(共享鎖)和寫入鎖(排斥鎖),檔案的同一部分不能同時建立讀取鎖和寫入鎖。

fcntl()使用例項:

檔案記錄鎖功能原始碼:

  1. /* 
  2.  * lock_set.c 
  3.  * 
  4.  *  Created on: 2012-7-17 
  5.  *      Author: liwei.cai 
  6.  */  
  7. int lock_set(int fd, int type)  
  8. {  
  9.     struct flock old_lock, lock;  
  10.     lock.l_whence = SEEK_SET;  
  11.     lock.l_start = 0;  
  12.     lock.l_len = 0;  
  13.     lock.l_type = type;  
  14.     lock.l_pid -1;  
  15.   
  16.     //判斷檔案是否上鎖  
  17.     fcntl(fd, F_GETLK, &lock);  
  18.     if (lock.l_type != F_UNLCK)  
  19.     {  
  20.         //判斷檔案不能上鎖的原因  
  21.         if (lock.l_type == F_RDLCK) //該檔案已有讀取鎖  
  22.         {  
  23.             printf("Read lock already set by %d .\n", lock.l_pid);  
  24.         }  
  25.         else if(lock.l_type == F_WRLCK) //該檔案已有寫入鎖  
  26.         {  
  27.             printf("Write lock already set by %d .\n", lock.l_pid);  
  28.         }  
  29.     }  
  30.     //l_type 可能已被F_FETLK修改過  
  31.     lock.l_type = type;  
  32.   
  33.     //根據不同的type值進行阻塞式上鎖或解鎖  
  34.     if((fcntl(fd, F_SETLKW, &lock)) < 0)  
  35.     {  
  36.         printf("Lock failed:type = %d\n", lock.l_type);  
  37.         return 1;  
  38.     }  
  39.   
  40.     switch(lock.l_type)  
  41.     {  
  42.     case F_RDLCK:  
  43.         {  
  44.             printf("Read lock set by %d \n", getpid());  
  45.         }  
  46.         break;  
  47.     case F_WRLCK:  
  48.         {  
  49.             printf("Write lock set by %d \n", getpid());  
  50.         }  
  51.         break;  
  52.     case F_UNLCK:  
  53.         {  
  54.             printf("Release lock by %d \n", getpid());  
  55.             return 1;  
  56.         }  
  57.         break;  
  58.     default:  
  59.         break;  
  60.     }  
  61.     return 0;  
  62. }  

檔案寫入鎖的測試用例,這裡首先建立了一個“hello”檔案,之後對其上寫入鎖,最後釋放寫入鎖。

  1. /* 
  2.  * write_lock.c 
  3.  * 
  4.  *  Created on: 2012-7-17 
  5.  *      Author: liwei.cai 
  6.  */  
  7. #include <unistd.h>  
  8. #include <sys/file.h>  
  9. #include <sys/types.h>  
  10. #include <sys/stat.h>  
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13. #include "lock_set.c"  
  14.   
  15. int main()  
  16. {  
  17.     int fd;  
  18.   
  19.     //首先開啟檔案  
  20.     fd = open("hello", O_RDWR|O_CREAT, 0644);  
  21.     if (fd < 0)  
  22.     {  
  23.         printf("Open file error!\n");  
  24.         exit(1);  
  25.     }  
  26.     //給檔案上寫入鎖  
  27.     lock_set(fd, F_WRLCK);  
  28.     getchar();  
  29.     //給檔案解鎖  
  30.     lock_set(fd, F_UNLCK);  
  31.     getchar();  
  32.     close(fd);  
  33.     exit(0);  
  34. }  
建議開啟兩個終端,並且同時執行該程式,以達到多個程式操作一個檔案的效果,並檢視結果。

讀取鎖與寫入鎖類似。

  1. /* 
  2.  * fcntl_read.c 
  3.  * 
  4.  *  Created on: 2012-7-17 
  5.  *      Author: liwei.cai 
  6.  */  
  7. #include <unistd.h>  
  8. #include <sys/file.h>  
  9. #include <sys/types.h>  
  10. #include <sys/stat.h>  
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13. #include "lock_set.c"  
  14.   
  15. int main()  
  16. {  
  17.     int fd;  
  18.   
  19.     //首先開啟檔案  
  20.     fd = open("hello", O_RDWR|O_CREAT, 0644);  
  21.     if (fd < 0)  
  22.     {  
  23.         printf("Open file error!\n");  
  24.         exit(1);  
  25.     }  
  26.     //給檔案上寫入鎖  
  27.     lock_set(fd, F_RDLCK);  
  28.     getchar();  
  29.     //給檔案解鎖  
  30.     lock_set(fd, F_UNLCK);  
  31.     getchar();  
  32.     close(fd);  
  33.     exit(0);  
  34. }  
從結果中可以很好的看出共享鎖與排斥鎖的區別。

相關文章