fcntl函數的應用詳解。本站提示廣大學習愛好者:(fcntl函數的應用詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是fcntl函數的應用詳解正文
(1)fcntl函數解釋
後面的這5個根本函數完成了文件的翻開、讀寫等根本操作,這一節將評論辯論的是,在文 件曾經同享的情形下若何操作,也就是當多個用戶配合應用、操作一個文件的情形,這時候,Linux 平日采取的辦法是給文件上鎖,來防止同享的資本發生競爭的狀況。
文件鎖包含建議性鎖和強迫性鎖。
建議性鎖請求每一個上鎖文件的過程都要檢討能否有鎖存,而且尊敬已有的鎖。在普通情形下,內核和體系都不應用建議性鎖。強迫性鎖是由內 核履行的鎖,當一個文件被上鎖停止寫入操作的時刻,內核將阻攔其他任何文件對其停止讀寫操作。采取強迫性鎖對機能的影響很年夜,每次讀寫操作都必需檢討能否有鎖存在。
在 Linux 中,完成文件上鎖的函數有lock和fcntl,個中flock用於對文件施加建議性鎖,而fcntl不只可以施加建議性鎖,還可以施增強制鎖。同時,fcntl還能對文件的某一記載停止上鎖,也就是記載鎖。
記載鎖又可分為讀取鎖和寫入鎖,個中讀取鎖又稱為同享鎖,它可以或許使多個過程都能在文件的統一部門樹立讀取鎖。而寫入鎖又稱為排擠鎖,在任什麼時候刻只能有一個過程在文件的某個部門上樹立寫入鎖。固然,在文件的統一部門不克不及同時樹立讀取鎖和寫入鎖。
留意:
fcntl是一個異常通用的函數,它還可以轉變文件過程各方面的屬性,在本節中,重要引見它樹立記載鎖的辦法,關於它其他用戶感興致的讀者可以參看fcntl手冊。
(2)fcntl函數格局
用於樹立記載鎖的fcntl函數格局如表6.6 所示。
表6.6 fcntl函數語法要點所需頭文件
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
函數原型int fcnt1(int fd, int cmd, struct flock *lock)
fd:文件描寫符
F_DUPFD:復制文件描寫符
F_GETFD:取得fd的close-on-exec標記,若標記未設置,則文件經由exec函數以後仍堅持翻開狀況
F_SETFD:設置close-on-exec標記,該標記以參數arg的FD_CLOEXEC位決議
F_GETFL:獲得open設置的標記
函數傳入值
cmd
F_SETFL:轉變open設置的標記
F_GETFK:依據lock描寫,決議能否上文件鎖
F_SETFK:設置lock描寫的文件鎖
F_SETLKW:這是F_SETLK的壅塞版本(敕令名中的W表現期待(wait))。
假如存在其他鎖,則挪用過程睡眠;假如捕獲到旌旗燈號則睡眠中止
F_GETOWN:檢索將收到SIGIO和SIGURG旌旗燈號的過程號或過程組號
F_SETOWN:設置過程號或過程組號
函數前往值
Lock:構造為flock,設置記載鎖的詳細狀況,前面會具體解釋
勝利:0
-1:失足
這裡,lock的構造以下所示:
Struct flock{
short l_type;
off_t l_start;
short l_whence;
off_t l_len;
pid_t l_pid;
}
lock構造中每一個變量的取值寄義如表6.7 所示。
表6.7 lock構造變量取值
F_RDLCK:讀取鎖(同享鎖)
l_type F_WRLCK:寫入鎖(排擠鎖)
F_UNLCK:解鎖
l_stat 絕對位移量(字節)
SEEK_SET:以後地位為文件的開首,新地位為偏移量的年夜小
SEEK_CUR:以後地位為文件指針的地位,新地位為以後地位加上偏移量
l_whence:絕對位移量的終點(同lseek 的whence)。
SEEK_END:以後地位為文件的開頭,新地位為文件的年夜小加上偏移量的年夜小
l_len 加鎖區域的長度
小技能:
為加鎖全部文件,平日的辦法是將l_start 解釋為0,l_whence 解釋為SEEK_SET,l_len 解釋為0。
(3)fcntl應用實例
上面起首給出了應用fcntl 函數的文件記載鎖函數。在該函數中,起首給flock 構造體的對應位付與響應的值。接著應用兩次fcntl函數分離用於給相干文件上鎖和斷定文件能否可以上鎖,這裡用到的cmd值分離為F_SETLK 和F_GETLK。
這個函數的源代碼以下所示:
/*lock_set函數*/
void lock_set(int fd, int type)
{
struct flock lock;
lock.l_whence = SEEK_SET;//賦值lock構造體
lock.l_start = 0;
lock.l_len =0;
while(1){
lock.l_type = type;
/*依據分歧的type值給文件上鎖或解鎖*/
if((fcntl(fd, F_SETLK, &lock)) == 0){
if( lock.l_type == F_RDLCK )
printf("read lock set by %d\n",getpid());
else if( lock.l_type == F_WRLCK )
printf("write lock set by %d\n",getpid());
else if( lock.l_type == F_UNLCK )
printf("release lock by %d\n",getpid());
return;
}
/*斷定文件能否可以上鎖*/
fcntl(fd, F_GETLK,&lock);
/*斷定文件不克不及上鎖的緣由*/
if(lock.l_type != F_UNLCK){
/*/該文件已有寫入鎖*/
if( lock.l_type == F_RDLCK )
printf("read lock already set by %d\n",lock.l_pid);
/*該文件已有讀取鎖*/
else if( lock.l_type == F_WRLCK )
printf("write lock already set by %d\n",lock.l_pid);
getchar();
}
}
}
上面的實例是測試文件的寫入鎖,這裡起首創立了一個hello文件,以後對其上寫入鎖,最初釋放寫入鎖。代碼以下所示:
/*fcntl_write.c測試文件寫入鎖主函數部門*/
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int fd;
/*起首翻開文件*/
fd=open("hello",O_RDWR | O_CREAT, 0666);
if(fd < 0){
perror("open");
exit(1);
}
/*給文件上寫入鎖*/
lock_set(fd, F_WRLCK);
getchar();
/*給文件接鎖*/
lock_set(fd, F_UNLCK);
getchar();
close(fd);
exit(0);
}
為了可以或許應用多個終端,更好地顯示寫入鎖的感化,本實例重要在PC 機上測試,讀者可將其穿插編譯,下載到目的板上運轉。上面是在PC 機上的運轉成果。為了使法式有較年夜的靈巧性,筆者采取文件上鎖後由用戶鍵入一隨意率性鍵使法式持續運轉。建議讀者開啟兩個終端,而且在兩個終端上同時運轉該法式,以到達多個過程操作一個文件的後果。在這裡,筆者起首運轉終端一,請讀者留意終端二中的第一句。
終端一:
[root@localhost file]# ./fcntl_write
write lock set by 4994
release lock by 4994
終端二:
[root@localhost file]# ./fcntl_write
write lock already set by 4994
write lock set by 4997
release lock by 4997
因而可知,寫入鎖為互斥鎖,一個時辰只能有一個寫入鎖存在。
接上去的法式是測試文件的讀取鎖,道理同下面的法式一樣。
/*fcntl_read.c測試文件讀取鎖主函數部門*/
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int fd;
fd=open("hello",O_RDWR | O_CREAT, 0666);
if(fd < 0){
perror("open");
exit(1);
}
/*給文件上讀取鎖*/
lock_set(fd, F_RDLCK);
getchar();
/*給文件接鎖*/
lock_set(fd, F_UNLCK);
getchar();
close(fd);
exit(0);
}
異樣開啟兩個終端,並起首啟動終端一上的法式,其運轉成果以下所示:
終端一:
[root@localhost file]# ./fcntl2
read lock set by 5009
release lock by 5009
終端二:
[root@localhost file]# ./fcntl2
read lock set by 5010
release lock by 5010
讀者可以將此成果與寫入鎖的運轉成果比擬較,可以看出,讀取鎖為同享鎖,當過程5009已設定讀取鎖後,過程5010 還可以設置讀取鎖。
思慮:
假如在一個終端上運轉設置讀取鎖,則在另外一個終端上運轉設置寫入鎖,會有甚麼成果呢?