简介
文件锁主要有三套函数,分别是flock(2),fcntl(2)和lockf(3)
函数名 | 实现类别 | 支持读锁 | 支持写锁 | 支持文件局部锁 |
---|---|---|---|---|
flock | FLOCK | ∨ | Χ | Χ |
lockf | POSIX | Χ | ∨ | ∨ |
fcntl | POSIX | ∨ | ∨ | ∨ |
今天就来试一下fcntl,其实这个系统调用的功能很多,文件锁只是一方面,锁的控制细节主要用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){//父进程先锁文件,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){//子进程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
在父进程上锁后,子进程分别进行了非阻塞申请锁和阻塞申请锁,非阻塞申请立刻返回错误,阻塞申请就一直等到父进程释放。
为什么子进程没拿到锁,也同样写入成功了?能体现写锁的环境还在寻找中!!!