檔案級的鎖:對整個檔案加鎖,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章節