1. 程式人生 > >linux C語言實現檔案鎖之flock

linux C語言實現檔案鎖之flock

一:flock函式特點:
1.flock只能加全域性鎖。
2.當一個程序用flock給一個檔案加鎖時,用另一個程序再給這個檔案加鎖,它會阻塞或者也可以返回加鎖失敗(可以自己設定)。
3.當給一個檔案加fcntl的獨佔鎖後,再給這個檔案加flock的獨佔鎖,其會進入阻塞狀態。
4.當給一個檔案加flock的獨佔鎖後,用fcntl去獲取這個鎖資訊獲取不到,再用fcntl仍然可以給檔案加鎖。
5.用flock之前需要使用者自己去檢查一下是否已經上了鎖,在進行操作,否則直接寫入檔案,鎖為不起作用。
二:遇到的問題:
一個程序去開啟檔案,輸入一個整數,然後上一把寫鎖(LOCK_EX),再輸入一個整數將解鎖(LOCK_UN),
另一個程序開啟同樣一個檔案,直接向檔案中寫資料,發現鎖不起作用,能正常寫入(我此時用的是超級使用者)。
解決問題,發現flock不提供鎖檢查,也就是說在用flock之前需要使用者自己去檢查一下是否已經上了鎖,
說明白點就是讀寫檔案之前用一下flock檢查一下檔案有沒有上鎖,如果上鎖了flock將會阻塞在那裡
(An attempt to lock the file using one of these file descriptors may be denied by a lock
that the calling process has already placed via another descriptor ).
三:函式詳解


表頭檔案 #include<sys/file.h>
定義函式 int flock(int fd,int operation);
函式說明 flock()會依引數operation所指定的方式對引數fd所指的檔案做各種鎖定或解除鎖定的動作。此函式只能鎖定整個檔案,無法鎖定檔案的某一區域。
引數 operation有下列四種情況:
LOCK_SH 建立共享鎖定。多個程序可同時對同一個檔案作共享鎖定。
LOCK_EX 建立互斥鎖定。一個檔案同時只有一個互斥鎖定。
LOCK_UN 解除檔案鎖定狀態。
LOCK_NB 無法建立鎖定時,此操作可不被阻斷,馬上返回程序。通常與LOCK_SH或LOCK_EX 做OR(|)組合。
單一檔案無法同時建立共享鎖定和互斥鎖定,而當使用dup()或fork()時檔案描述詞不會繼承此種鎖定。
返回值 返回0表示成功,若有錯誤則返回-1,錯誤程式碼存於errno。
flock只要在開啟檔案後,需要對檔案讀寫之前flock一下就可以了,用完之後再flock一下,前面加鎖,後面解鎖。
四:程式碼

file1.c

#include <sys/file.h>
#include <stdio.h>

int main (void)
{
    FILE *fp = NULL;

    int i = 20;

    if ((fp = fopen("./file_lock.test", "r+b")) == NULL) //開啟檔案

        printf("file open error!\n");

    if (flock(fp->_fileno, LOCK_EX) != 0) //給該檔案加鎖

        printf("file lock by others\n");

    while(1) //進入迴圈,加鎖時間為20秒,列印倒計時

    {

        printf("%d\n", i--);

        sleep(1);

        if (i == 0)

            break;

    }

    fclose(fp); //20秒後退出,關閉檔案

    flock(fp->_fileno, LOCK_UN); //檔案解鎖

    return 0;

}

file2.c

#include <sys/file.h>
#include <stdio.h>
int main(void)

{

    FILE *fp = NULL;

    int i = 0;

    if ((fp = fopen("./file_lock.test", "r+b")) == NULL) //開啟檔案

        printf("file open error!\n");

    flock(fp->_fileno, LOCK_EX); //檔案加鎖

    while(1) //進入迴圈

    {

        printf("%d\n", i++);
        sleep(1);

    }

    fclose(fp); //關閉檔案

    flock(fp->_fileno, LOCK_UN); //釋放檔案鎖

    return 0;



}
首先執行file1.c,緊接著執行file2.c(執行file1.c後20秒內要執行file2.c否則看不到現象)

現象是:file1.c執行起來以後,開始倒計時。此時執行file2.c會阻塞在加鎖處。當file1.c執行20秒後關閉檔案,並釋放檔案鎖後,file2.c會開始執行。