|  | |||||||||||||||||||||||||||||||||||
| linux 文件鎖的實現及其應用 | |||||||||||||||||||||||||||||||||||
| 文件鎖 1.fcntl()函數(shu)說明 前面講(jiang)述(shu)的(de)(de)5個基(ji)本(ben)函(han)數實(shi)現(xian)了(le)文件的(de)(de)打開、讀(du)/寫等(deng)基(ji)本(ben)操(cao)作,本(ben)節將討論(lun)在文件已經共享(xiang)的(de)(de)情(qing)況下如(ru)何操(cao)作,也就是(shi)當多個用(yong)戶共同(tong)使用(yong)、操(cao)作一(yi)個文件的(de)(de)情(qing)況。這(zhe)時,Linux通(tong)常采用(yong)的(de)(de)方法是(shi)給文件上鎖,來(lai)避免共享(xiang)的(de)(de)資源產生競爭(zheng)的(de)(de)狀態。 文(wen)件(jian)鎖(suo)(suo)包括建(jian)議(yi)性(xing)鎖(suo)(suo)和(he)強(qiang)制性(xing)鎖(suo)(suo)。建(jian)議(yi)性(xing)鎖(suo)(suo)要求(qiu)每(mei)個上(shang)鎖(suo)(suo)文(wen)件(jian)的進程(cheng)都要檢(jian)查(cha)是(shi)(shi)否有(you)鎖(suo)(suo)存(cun)(cun)在(zai)(zai),并(bing)且尊重已有(you)的鎖(suo)(suo)。在(zai)(zai)一般(ban)情況下,內(nei)核(he)(he)和(he)系統都不使用建(jian)議(yi)性(xing)鎖(suo)(suo)。強(qiang)制性(xing)鎖(suo)(suo)是(shi)(shi)由(you)內(nei)核(he)(he)執行(xing)(xing)的鎖(suo)(suo),當一個文(wen)件(jian)被上(shang)鎖(suo)(suo)進行(xing)(xing)寫(xie)入操(cao)作(zuo)時,內(nei)核(he)(he)將(jiang)阻止其(qi)他任何文(wen)件(jian)對其(qi)進行(xing)(xing)讀寫(xie)操(cao)作(zuo)。采用強(qiang)制性(xing)鎖(suo)(suo)對性(xing)能(neng)的影響很大,每(mei)次讀寫(xie)操(cao)作(zuo)都必須(xu)檢(jian)查(cha)是(shi)(shi)否有(you)鎖(suo)(suo)存(cun)(cun)在(zai)(zai)。 在(zai)Linux中,實(shi)現文(wen)件上鎖(suo)(suo)的函數有lockf()和fcntl(),其中lockf()用于對文(wen)件施(shi)加建議性鎖(suo)(suo),而fcntl()不僅(jin)可(ke)以施(shi)加建議性鎖(suo)(suo),還(huan)可(ke)以施(shi)加強(qiang)制性鎖(suo)(suo)。同(tong)時,fcntl()還(huan)能對文(wen)件的某一(yi)記(ji)錄上鎖(suo)(suo),也就(jiu)是(shi)記(ji)錄鎖(suo)(suo)。 記錄鎖(suo)(suo)(suo)(suo)又(you)可分(fen)為(wei)讀(du)取(qu)鎖(suo)(suo)(suo)(suo)和(he)寫入鎖(suo)(suo)(suo)(suo),其中讀(du)取(qu)鎖(suo)(suo)(suo)(suo)又(you)稱為(wei)共享(xiang)鎖(suo)(suo)(suo)(suo),它能(neng)(neng)夠使多個(ge)(ge)進(jin)程(cheng)(cheng)都能(neng)(neng)在文(wen)(wen)件(jian)(jian)的同一(yi)(yi)部分(fen)建立讀(du)取(qu)鎖(suo)(suo)(suo)(suo)。而寫入鎖(suo)(suo)(suo)(suo)又(you)稱為(wei)排(pai)斥鎖(suo)(suo)(suo)(suo),在任何時刻只能(neng)(neng)有一(yi)(yi)個(ge)(ge)進(jin)程(cheng)(cheng)在文(wen)(wen)件(jian)(jian)的某個(ge)(ge)部分(fen)建立寫入鎖(suo)(suo)(suo)(suo)。當然(ran),在文(wen)(wen)件(jian)(jian)的同一(yi)(yi)部分(fen)不能(neng)(neng)同時建立讀(du)取(qu)鎖(suo)(suo)(suo)(suo)和(he)寫入鎖(suo)(suo)(suo)(suo)。 fcntl()函(han)數(shu)具有(you)很(hen)豐(feng)富的(de)功(gong)能,它可以對(dui)已打開的(de)文件描述符(fu)進行各種操作,不僅包括管理(li)文件鎖(suo)(suo),還包括獲得設置(zhi)文件描述符(fu)和文件描述符(fu)標志、文件描述符(fu)的(de)復制等(deng)很(hen)多功(gong)能。本節主要介紹fcntl()函(han)數(shu)建立記錄(lu)鎖(suo)(suo)的(de)方法,關(guan)于它的(de)其(qi)他操作,感興趣的(de)讀者可以參看fcntl手冊。 2.fcntl()函(han)數格式(shi)  用于建立記(ji)錄鎖的fcntl()函數語法要(yao)點如表2.6所示。 表2.6 fcntl()函數語法要(yao)點 
 這里,lock的結構如下所示(shi):     struct flock   lock結構中(zhong)每個變(bian)量(liang)的取(qu)值含義(yi)如表2.7所示。 表(biao)2.7 lock結(jie)構變量取值 
 為(wei)(wei)加鎖整個文件(jian),通常(chang)的方法是將l_start設(she)置(zhi)(zhi)為(wei)(wei)0,l_whence設(she)置(zhi)(zhi)為(wei)(wei)SEEK_SET,l_len設(she)置(zhi)(zhi)為(wei)(wei)0。   3.fcntl()使(shi)用(yong)實(shi)例 下面首先(xian)給出了使(shi)用fcntl()函數(shu)的(de)(de)文件記(ji)錄鎖功(gong)能的(de)(de)代(dai)碼實(shi)現。在(zai)該代(dai)碼中(zhong),首先(xian)給flock結構體的(de)(de)對應位(wei)賦予相應的(de)(de)值。 接著(zhu)調用兩次fcntl()函數。用F_GETLK命令判(pan)斷(duan)是(shi)否(fou)可以進行(xing)flock結構所描述的(de)鎖(suo)操(cao)作:若(ruo)可以進行(xing),則flock結構的(de)l_type會被設(she)置為F_UNLCK,其他域(yu)不(bu)變;若(ruo)不(bu)可進行(xing),則l_pid被設(she)置為擁有文件鎖(suo)的(de)進程號,其他域(yu)不(bu)變。   用F_SETLK和F_SETLKW命令設置flock結構所(suo)描(miao)述(shu)的(de)鎖操(cao)作(zuo),后(hou)者是前者的(de)阻塞版。 當(dang)第(di)一次調用fcntl()時(shi),使(shi)用F_GETLK命(ming)令(ling)獲得(de)當(dang)前文件被上(shang)鎖(suo)的情況,由此可以判斷能(neng)不(bu)能(neng)進(jin)(jin)行(xing)(xing)上(shang)鎖(suo)操(cao)作(zuo);當(dang)第(di)二次調用fcntl()時(shi),使(shi)用F_SETLKW命(ming)令(ling)對(dui)指(zhi)定(ding)文件進(jin)(jin)行(xing)(xing)上(shang)鎖(suo)/解鎖(suo)操(cao)作(zuo)。因(yin)為F_SETLKW命(ming)令(ling)是(shi)阻塞(sai)式操(cao)作(zuo),所以,當(dang)不(bu)能(neng)把上(shang)鎖(suo)/解鎖(suo)操(cao)作(zuo)進(jin)(jin)行(xing)(xing)下(xia)去(qu)時(shi),運行(xing)(xing)會被阻塞(sai),直到(dao)能(neng)夠(gou)進(jin)(jin)行(xing)(xing)操(cao)作(zuo)為止。 文件(jian)記錄鎖(suo)的功能代碼(ma)具(ju)體如(ru)下所示:     /* lock_set.c */ 下面(mian)的實例是文件寫入(ru)(ru)鎖的測試用(yong)例,這(zhe)里首先創建了一個hello文件,之(zhi)后(hou)(hou)對其(qi)上寫入(ru)(ru)鎖,后(hou)(hou)釋放寫入(ru)(ru)鎖。代碼如下所示(shi):     /* write_lock.c */ 為(wei)了(le)能(neng)夠使(shi)用多(duo)個終(zhong)端(duan)(duan),更好地(di)顯示寫入(ru)鎖的(de)作用,本實例主要在(zai)PC上測試,讀者(zhe)可將(jiang)其交(jiao)叉編譯,下載到目標板上運(yun)行。下面是在(zai)PC上的(de)運(yun)行結(jie)果(guo)。為(wei)了(le)使(shi)程(cheng)序(xu)有較大(da)的(de)靈活性,筆者(zhe)采用文件上鎖后由(you)用戶輸(shu)入(ru)任意鍵使(shi)程(cheng)序(xu)繼續運(yun)行。建(jian)議讀者(zhe)開啟(qi)兩(liang)個終(zhong)端(duan)(duan),并(bing)且(qie)在(zai)兩(liang)個終(zhong)端(duan)(duan)上同時運(yun)行該程(cheng)序(xu),以達到多(duo)個進程(cheng)操作一(yi)個文件的(de)效果(guo)。在(zai)這里,筆者(zhe)首先(xian)運(yun)行終(zhong)端(duan)(duan)一(yi),請讀者(zhe)注意終(zhong)端(duan)(duan)二(er)中的(de)第一(yi)句。 終(zhong)端一:     $ ./write_lock 終端二:     $ ./write_lock   由此(ci)可見,寫入鎖(suo)為互(hu)斥鎖(suo),同一時刻只能有一個(ge)寫入鎖(suo)存在。 接下來的(de)程序是文件讀(du)取鎖的(de)測(ce)試(shi)用例,原理與上面的(de)程序一樣。     /* fcntl_read.c */   同樣開啟(qi)(qi)兩(liang)個終(zhong)端,并首先啟(qi)(qi)動終(zhong)端一上的(de)程序,其(qi)運行(xing)結果如下所示。 終端一:     $ ./read_lock 終端二:     $ ./read_lock 讀(du)者可(ke)以將此結(jie)果與寫入(ru)鎖(suo)的運(yun)行(xing)結(jie)果相比較,可(ke)以看出,讀(du)取鎖(suo)為共(gong)享鎖(suo),當進程5009已設置(zhi)讀(du)取鎖(suo)后,進程5010仍然可(ke)以設置(zhi)讀(du)取鎖(suo)。 本文選自華清遠見嵌入式培訓教材《從實踐中學嵌入式Linux應用程序開發》 熱點(dian)鏈接:       
         1、底層文件I/O操作的系統調用 | |||||||||||||||||||||||||||||||||||