簡介
文件鎖主要有三套函數(shù)背传,分別是flock(2),fcntl(2)和lockf(3)
函數(shù)名 | 實(shí)現(xiàn)類別 | 支持讀鎖 | 支持寫鎖 | 支持文件局部鎖 |
---|---|---|---|---|
flock | FLOCK | ∨ | Χ | Χ |
lockf | POSIX | Χ | ∨ | ∨ |
fcntl | POSIX | ∨ | ∨ | ∨ |
今天就來試一下fcntl,其實(shí)這個系統(tǒng)調(diào)用的功能很多肩杈,文件鎖只是一方面,鎖的控制細(xì)節(jié)主要用struct flock
來描述解寝,其主要member可含義如下扩然。
struct flock {
...
short l_type; /* Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock
(set by F_GETLK and F_OFD_GETLK) */
...
};
代碼演示
#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";
struct flock flock = {
.l_start = 0,
.l_len = 0,
.l_type = F_WRLCK,
.l_whence = SEEK_SET
};
pid_t pid = fork();
if (pid > 0){//父進(jìn)程先鎖文件,2s后放開
int fd = open(filename, O_CREAT|O_RDWR, 0666);
if (fd >= 0){
int ret = fcntl(fd, F_SETLK, &flock);
if (!ret){
printf("[%d] locked\n", getpid());
sleep(2);
printf("[%d] unlocked\n", getpid());
flock.l_type = F_UNLCK;
ret = fcntl(fd, F_SETLK, &flock);
}
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 = fcntl(fd, F_SETLK, &flock);
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 = fcntl(fd, F_SETLKW, &flock);
if (!ret){
printf("[%d] locked\n", getpid());
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));
printf("[%d] unlocked\n", getpid());
flock.l_type = F_UNLCK;
ret = fcntl(fd, F_SETLK, &flock);
}
close(fd);
}
exit(EXIT_SUCCESS);
}
return 0;
}
輸出
[65944] locked
[65945] opened
[65945] lockf fail, Resource temporarily unavailable
[65945] write success
[65944] unlocked
[65945] locked
[65945] write success
[65945] unlocked
在父進(jìn)程上鎖后聋伦,子進(jìn)程分別進(jìn)行了非阻塞申請鎖和阻塞申請鎖夫偶,非阻塞申請立刻返回錯誤,阻塞申請就一直等到父進(jìn)程釋放觉增。
為什么子進(jìn)程沒拿到鎖兵拢,也同樣寫入成功了?能體現(xiàn)寫鎖的環(huán)境還在尋找中S饨浮K盗濉!