淺嘗輒止17-Linux基礎(chǔ)-文件鎖0

當(dāng)程序猿向程序媛表白時(shí),可能會(huì)出現(xiàn)一個(gè)糟糕的對(duì)話:
猿:“我不喜歡你”
媛:“我知道了”(拉黑)
猿:“還能喜歡誰(shuí)呢?”——提示:!消息已發(fā)出,但被對(duì)方拒收了。

可以看出,這個(gè)猿犯了兩個(gè)錯(cuò)誤,一是第一句話沒(méi)有標(biāo)點(diǎn),如果加個(gè)逗號(hào),則被誤解概率會(huì)降低(大概萬(wàn)分之一吧),二是沒(méi)有給對(duì)話加鎖,下面我們來(lái)加個(gè)鎖。

猿:******表白開(kāi)始(表白結(jié)束前請(qǐng)勿打斷!)******
猿:“我不喜歡你,”
媛:“我知道了”(拉黑)——提示:對(duì)方表白未結(jié)束,請(qǐng)結(jié)束后再操作
猿:“還能喜歡誰(shuí)呢?”
猿:******表白結(jié)束******
媛:“我知道了”(拉黑)

這樣就完美了,雙方都沒(méi)有誤解:)

簡(jiǎn)介

文件鎖就像上面表白開(kāi)始和結(jié)束的聲明,在這個(gè)聲明中間,其它人不可以動(dòng)這個(gè)文件。
Linux文件鎖有兩種,分別是讀鎖(勸告/建議性鎖)和寫鎖(排它/獨(dú)占性鎖),顧名思義,其他文件訪問(wèn)者可以知道是否有別人鎖了文件,但是讀鎖不能阻止他修改文件。
Linux文件鎖有兩套實(shí)現(xiàn),分別是FLOCK和POSIX,兩套鎖互相無(wú)影響。
文件鎖主要有三套函數(shù),分別是flock(2),fcntl(2)lockf(3)

函數(shù)名 實(shí)現(xiàn)類別 支持讀鎖 支持寫鎖 支持文件局部鎖
flock FLOCK Χ Χ
lockf POSIX Χ
fcntl POSIX

從表中大概可以猜出來(lái),lockf是用fcntl實(shí)現(xiàn)的庫(kù)函數(shù)。

代碼演示

只演示flock的使用

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv){
    char *filename = "tmp";
    pid_t pid = fork();
    if (pid > 0){//父進(jìn)程先鎖文件,2s后放開(kāi)
        int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC, 0666);
        if (fd >= 0){
            int ret = flock(fd, LOCK_EX);
            if (!ret){
                printf("[%d] locked\n", getpid());
                sleep(2);
                printf("[%d] unlocked\n", getpid());
                ret = flock(fd,LOCK_UN);
            }
            sleep(1);
            close(fd);
        }
        waitpid(pid,NULL,0);
    }
    else if (pid == 0){//子進(jìn)程1s后嘗試鎖文件
        int fd;
        sleep(1);
        fd = open(filename, O_WRONLY);
        if (fd >= 0){
            int ret;
            printf("[%d] opened\n", getpid());
            ret = flock(fd,LOCK_EX|LOCK_NB);
            if (ret) printf("[%d] lockf fail, %s\n", getpid(), strerror(errno));
            ret = write(fd, filename, sizeof(filename));
            if (ret == sizeof(filename)) printf("[%d] write success\n", getpid());
            else printf("[%d] lockf fail, %s\n", getpid(), strerror(errno));
            ret = flock(fd,LOCK_EX);
            if (!ret){
                printf("[%d] locked\n", getpid());
                printf("[%d] unlocked\n", getpid());
                ret = flock(fd,LOCK_UN);
            }
            close(fd);
        }
        exit(EXIT_SUCCESS);
    }
    return 0;
}

輸出

[55143] locked
[55144] opened
[55144] lockf fail, Resource temporarily unavailable
[55144] write success
[55143] unlocked
[55144] locked
[55144] unlocked

演示分析

55143為父進(jìn)程(簡(jiǎn)稱小三),55144為子進(jìn)程(簡(jiǎn)稱小四)。小三搶先上了鎖,小四順利地打開(kāi)了文件,然后小四非阻塞上鎖失敗后,成功地寫入了文件。最后小三解鎖后,小四才成功獲得了鎖。
在上述過(guò)程中,小四雖然沒(méi)有獲得鎖,但是也能成功地寫入文件,這印證了它只是個(gè)勸告性鎖。

關(guān)于另外兩個(gè)函數(shù),未完待續(xù)......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容