linux低級檔案編程中也講到
    多使用者多任務作業系統中非常重要的一個內容就是檔案鎖。使用者在更新檔案時,期望可以使用某種機制,防止兩種進程同時更新檔案同一地區而造成丟失,或者防止檔案內容在未更新完畢時被讀取等並發引起的問題,這種機制就是檔案鎖。
     進程在操作檔案期間,可以使用檔案鎖,鎖定檔案中的敏感部分,防止其他進程越權操作該部分資料。函數fcntl提供了對檔案任意地區置鎖的能力,既可以鎖住全部檔案,又可以鎖住檔案的部分記錄,故檔案鎖又成為"記錄鎖".
     根據檔案鎖的訪問方式,可以區分讀鎖和寫鎖兩種。讀鎖又名共用鎖定,它用來防止進程讀取的檔案記錄被更改。檔案記錄可以同時設定多個讀鎖,但當有一個讀鎖存在時,就不能在該記錄出設定寫鎖。
     寫鎖又名互斥鎖,它用來保證檔案更改記錄時不被幹擾,確保檔案一致性和完整性,防止寫丟失或讀"髒"資料。檔案記錄一旦設定了寫鎖,就不能再設定任意鎖,除非寫鎖接觸。
    檔案記錄在同一時刻,可以設定多個讀鎖,單僅能設定一個寫鎖,並且讀、寫不能不能同時存在。
    當函數fntl專用於鎖操作時,其原型為:
    int fcntl(int fildes,int cmd,struct flock *arg);
    其中,結構flock用於描述檔案鎖的資訊,定義於"fcntl.h"中,如下表示:
 
1. struct flock 
2. { 
3.    short l_type;/*鎖類型,取值為F_RDLCK、F_WRLCK、或F_UNLCK之一,分別代表申請讀鎖、申請寫鎖和釋放鎖*/ 
4.    short l_whence;/*鎖地區開始地址的相對位置,類似於lseek中whence參數,取值是SEEK_SET SEEK_CUR SEEK_END之一,分別表示相對檔案起始位置、檔案當前位置、檔案結束位置*/ 
5.    long l_start;/*鎖地區開始地址位移量,同l_whence共同確定鎖地區*/ 
6.    long l_len;/*鎖的長度,0表示鎖至檔案末*/ 
7.    long l_pid;/*擁有鎖的進程ID號*/ 
8. }; 
當函數fcntl專用於鎖時,參數cmd的三種取值:
     F_GETLK
     F_SETLK
     F_SETLKW
     {檔案鎖最典型的應用於兩個方面:一個鎖定檔案中的臨界資料,比如並發投票時檔案記錄的投票數;二是利用具有互斥性質的寫鎖,實現進程的並發控制}
   2)檔案鎖操作
     在鎖機制的使用中,最常見的操作有鎖的請求、釋放和測試等,這些操作代買基本類似
以下函數都是作者自己做的封裝:
   (1)測試鎖
   設計函數SeeLock,它查詢檔案描述符fd對應檔案的鎖資訊,其原型為:
   void SeeLock(int fd,int start,int len);
   函數查詢描述符fd對應檔案從位移start出開始的len位元組中的鎖資訊
 1. /*----測試所源碼----lock1.c----*/ 
 2. void SeekLock(int fd,int start,int len) 
 3. { 
 4.   struct flock arg; 
 5.   arg.l_type=F_WRLCK; 
 6.   arg.l_whence=SEEK_SET; 
 7.   arg.l_start=start; 
 8.   arg.l_len=len; 
 9.   if(fcntl(fd,F_GETLK,&arg)==-1)  
10.      fprintf(stderr,"See Lock failed./n"); 
11.   else if(arg.l_type==F_UNLCK) 
12.      fprintf(stderr,"NO LOCK FROM %d TO %d,n",start, len); 
13.   else if(arg.l_type==F_WRLCK) 
14.      fprintf(stderr,"WRITE LOCK FROM %d TO %d ,id=%d/n",start,len,arg.l_pid); 
15.   else if(arg.l_type==F_RDLCK) 
16.      fprintf(stderr,"READ LOCK FROM %d To %d,id=%d/n",start,len,arg.l_pid); 
17. } 
(2)申請讀鎖
    共用鎖定申請函數GetReadLock,原型為:
    void GetReadLock(int fd,int start,int len);
    以阻塞模式在檔案描述符fd相應的檔案中申請共用讀鎖,鎖定的地區從位移start處開始的len位元組
 1. /*---阻塞申請共用讀鎖源碼---lockl.c*/ 
 2. void GetReadLock(int fd,int start,int len) 
 3. { 
 4.   struct flock arg; 
 5.   arg.l_type=F_RDLCK; 
 6.   arg.l_whence=SEEK_SET; 
 7.   arg.l_start=start; 
 8.   arg.l_len=len; 
 9.   if(fcntl(fd,F_SETLKW,&arg)==-1) 
10.     fprintf(stderr,"[%d] Set Read Lock failed./n",getpid()); 
11.   else  
12.     fprintf(stderr,"[%d] Set Read Lock From %d To %d",getpid(),start,len); 
13. } 
(3)申請寫鎖
    void GetWriteLock(int fd,int start,int len);
 1. /*---阻塞申請共用寫鎖源碼---lockl.c*/ 
 2. void GetReadLock(int fd,int start,int len) 
 3. { 
 4.   struct flock arg; 
 5.   arg.l_type=F_WRLCK; 
 6.   arg.l_whence=SEEK_SET; 
 7.   arg.l_start=start; 
 8.   arg.l_len=len; 
 9.   if(fcntl(fd,F_SETLKW,&arg)==-1) 
10.     fprintf(stderr,"[%d] Set Write Lock failed./n",getpid()); 
11.   else  
12.     fprintf(stderr,"[%d] Set Write Lock From %d To %d",getpid(),start,len); 
13. } 
(4)釋放鎖
    設計檔案鎖釋放函數ReleaseLock,原型為:
    void ReleaseLock(int fd,int start,int len);
 1. /*---釋放鎖源碼---lockl.c*/ 
 2. void GetReadLock(int fd,int start,int len) 
 3. { 
 4.   struct flock arg; 
 5.   arg.l_type=F_UNLCK; 
 6.   arg.l_whence=SEEK_SET; 
 7.   arg.l_start=start; 
 8.   arg.l_len=len; 
 9.   if(fcntl(fd,F_SETLKW,&arg)==-1) 
10.     fprintf(stderr,"[%d] UnLock failed./n",getpid()); 
11.   else  
12.     fprintf(stderr,"[%d] UnLock From %d To %d",getpid(),start,len); 
13. } 
以下是一個檔案鎖控制進程的執行個體,如下:
 1. #include<stdio.h> 
 2. #include<fcntl.h> 
 3. void main() 
 4. { 
 5.   int fd; 
 6.   struct flock arg; 
 7.   if((fd=open("/tmp/tlockl",O_RDWR|O_CREAT,0755))<0) 
 8.   { 
 9.     fprintf(stderr,"open file failed./n"); 
10.     retrun; 
11.   } 
12.   SeeLock(fd,0,10); 
13.   GetReadLock(fd,0,10);/*申請讀鎖*/ 
14.   SeeLock(fd,11,20); 
15.   GetWriteLock(fd,11,20);/*申請寫鎖*/ 
16.   sleep(30); 
17.   ReleaseLock(fd,0,10); 
18.   ReleaseLock(fd,11,20); 
19. } 
 
作者“pstary”