fcntl

原文鏈接:http://blog.chinaunix.net/uid/20775448/cid-172636-list-1.html

http://blog.chinaunix.net/uid/20775448/cid-172636-list-1.html

https://blog.csdn.net/zhoulaowu/article/category/1718823/3

Unix系統允許多個進程同時對一個文件進行讀寫,雖然每一個read或write調用本身是原子的,但內核在兩個讀寫操作之間並沒有加以同步,因此當一個進程多次調用read來讀文件時,其它進程有可能在兩次read之間改變該文件,造成文件數據的隨機性衝突。爲解決此類併發進程對共享文件的訪問控制問題,Unix系統設計了文件鎖技術。

1.1 讀鎖與寫鎖

Unix系統對文件加鎖有兩種粒度:文件鎖和記錄鎖,文件鎖用來鎖定整個文件,而記錄鎖可以鎖定文件的部分區域甚至一個字節,進程通過爲文件設置多個記錄鎖,可以實現文件中不同區域的數據的讀寫同步,因此記錄鎖最爲常見。記錄鎖根據訪問方式的不同,又分爲讀鎖和寫鎖。讀鎖允許多個進程同時進行讀操作,也稱共享鎖。文件加了讀鎖就不能再設置寫鎖,但仍允許其他進程在同一區域再設置讀鎖。寫鎖的主要目的是隔離文件使所寫內容不被其他進程的讀寫干擾,以保證數據的完整性。寫鎖一旦加上,只有上鎖的人可以操作,其他進程無論讀還是寫只有等待寫鎖釋放後才能執行,故寫鎖又稱互斥鎖,寫鎖與任何鎖都必須互斥使用.

1.2 建議鎖和強制鎖

Unix文件鎖根據實現機制的不同,又可分爲建議鎖和強制鎖兩種類型。建議鎖由應用層實現,內核只爲用戶提供程序接口,並不參與鎖的控制和協調,也不對讀寫操作做內部檢查和強制保護,其工作原理類似於信號量機制,用戶首先定義並初始化特定的鎖,再根據進程間的的關係來調用相應的鎖操作,只有所有進程都嚴格遵循鎖的使用規則,纔能有效防止同步錯誤,否則,只要有一個例外,整個鎖的功能就會被破壞。

 

強制鎖則由內核強制實施,每當有進程調用read或write時,內核都要檢查讀寫操作是否與已加的鎖衝突,如果衝突,阻塞方式下該進程將被阻塞直到鎖被釋放,非阻塞方式下系統將立即以錯誤返回。顯然,使用強制鎖來控制對已鎖文件或文件區域的訪問,是更安全可靠的同步形式,適用於網絡連接、終端或串並行端口之類須獨佔使用的設備文件,因爲對用戶都可讀的文件加一把強制讀鎖,就能使其他人不能再寫該文件,從而保證了設備的獨佔使用。由於強制鎖運行在內核空間,處理機從用戶空間切換到內核空間,系統開銷大,影響性能,所以應用程序很少使用。建議鎖開銷小,可移植性好,符合POSIX標準的文件鎖實現,在數據庫系統中應用廣泛,特別是當多個進程交叉讀寫文件的不同部分時,建議鎖有更好的並行性和實時性

函數原型定義爲:int fcntl(int fd,int cmd,int arg),參數fd表示需要加鎖的文件的描述符;參數cmd指定要進行的鎖操作,如設置、解除及測試鎖等;參數arg是指向鎖結構flock的指針。

無論哪種類型的文件鎖,使用的流程是確定的:首先以匹配的方式打開文件,然後各進程調用上鎖操作同步對已鎖區域的讀寫,讀或寫完成時再調用解鎖操作,最後關閉文件。鎖操作代碼的編寫方法基本類似,首先形成適當的flock結構,然後調用fcntl完成實際的鎖操作。爲避免每次分配flock並填充各成員的重複工作,可以預先定義專門的函數來完成頻繁調用的上鎖和解鎖操作。下列代碼就是爲一個文件設置讀鎖的實例。

獲取文件的flags,即open函數的第二個參數:

       flags = fcntl(fd,F_GETFL,0);

2、設置文件的flags:

      fcntl(fd,F_SETFL,flags);

3、增加文件的某個flags,比如文件是阻塞的,想設置成非阻塞:

       flags = fcntl(fd,F_GETFL,0);

       flags |= O_NONBLOCK;

      fcntl(fd,F_SETFL,flags);

O_NONBLOCK和O_NDELAY所產生的結果都是使I/O變成非阻塞模式(non-blocking),在讀取不到數據或是寫入緩衝區已滿會馬上return,而不會阻塞等待。

它們的差別在於:在讀操作時,如果讀不到數據,O_NDELAY會使I/O函數馬上返回0,但這又衍生出一個問題,因爲讀取到文件末尾(EOF)時返回的也是0,這樣無法區分是哪種情況。因此,O_NONBLOCK就產生出來,它在讀取不到數據時會回傳-1,並且設置errno爲EAGAIN。

 

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