天天看點

檔案鎖-flock和fcntl

檔案級的鎖:對整個檔案加鎖,flock系統調用

檔案内範圍的鎖:對檔案的某個範圍加鎖,fcntl庫函數

1. flock

flock是系統調用,加的建議鎖

https://man7.org/linux/man-pages/man2/flock.2.html

tips:

flock的鎖的語義:擷取到的鎖是與打開的檔案描述符,而不是檔案描述符或者inode相關聯

(1)對于open同一個檔案多次,擷取到的不同fd,flock會認為是不同的,是以再加flock會block

(2)flock建立的鎖是和fd相關的,是以複制dup(fd)和fork産生的fd,都是同一把鎖

demo:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h>
int main (int argc, char ** argv)
{
    int ret;
    int fd1 = open("tmp.txt",O_RDWR);
    int fd2 = open("tmp.txt",O_RDWR);
    //int fd2 = dup(fd1);
    printf("fd1: %d, fd2: %d\n", fd1, fd2);
    ret = flock(fd1,LOCK_EX);
    printf("get lock1, ret: %d\n", ret);
    ret = flock(fd2,LOCK_EX|LOCK_NB);
    printf("get lock2, ret: %d\n", ret);
    return 0;
}
           

2. fcntl

是GNU C庫函數,既可以加建議鎖和強制性鎖

https://man7.org/linux/man-pages/man2/fcntl.2.html

#include <fcntl.h>
struct flock {
	short l_type; // F_RDLCK,F_WRLCK,F_UNLCK
	short l_whence;	// SEEK_SET,SEEK_CUR,SEEK_END,起始位置,檔案的目前偏移量,結尾位置
	off_t l_start; // offset where the lock begins
	off_t l_len; // number of bytes to lock
	pid_t l_pid; // process preventing our lock(only F_GETLK only)
};
struct flock flockinfo;
fcntl(fd, F_SETLK, &flockinfo)
           

F_GETLK:檢測是否可以擷取指定區域的鎖,實際并不擷取這把鎖,如果可以傳回的l_type是F_UNLCK

F_SETLK:更新鎖,如果有沖突傳回EAGAIN

F_SETLKW:更新鎖,如果有沖突,則阻塞直到鎖的請求被滿足

demo:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int main() {
    struct flock lock;
    lock.l_whence = SEEK_SET;
    lock.l_type = F_WRLCK;
    lock.l_start = 0;
    lock.l_len = 100;
    lock.l_pid = getpid();

    const char* fname = "test.txt";
    int fd = open(fname, O_RDWR);
    if (fd < 0) {
        printf("open err: fname %s\n", fname);
        return -1;
    }
    int ret = fcntl(fd, F_SETLK, &lock);
    if (ret == 0) {
        printf("ltyp %d range(%d:%d)\n", lock.l_type, lock.l_start, lock.l_len);
    } else {
        printf("error: ltyp %d range(%d:%d)\n", lock.l_type, lock.l_start, lock.l_len);
    }
    close(fd);
    return 0;
}
           

3. flock和fcntl的差別和聯系

結論1:

兩者判斷鎖是否沖突的差別:

flock的owner是核心态的open fd,判斷是否沖突也是根據owner,如果owner相同則可以遞歸申請。

這樣解釋:多次open同一個檔案核心有兩個fd,是以owner不同,再加flock會鎖住,dup則在核心态還是一個owner,不會沖突

Fcntl的owner是程序,不是fd也不是inode

結論2:

兩者的聯系:

flock建立的鎖和fcntl建立的鎖之間的互動是未定義的行為,是以應用程式應該隻使用其中一種檔案加鎖方法。——《linux-unix系統程式設計手冊》

reference:

[1] https://www.jianshu.com/p/8b355893f709

[2] https://yxkemiya.github.io/2019/08/19/file-lock/

[3] 《linux-unix系統程式設計手冊》55.2和55.3章節

[4] 《unix環境進階程式設計》14.3章節