当程序猿向程序媛表白时,可能会出现一个糟糕的对话:
猿:“我不喜欢你”
媛:“我知道了”(拉黑)
猿:“还能喜欢谁呢?”——提示:!消息已发出,但被对方拒收了。
可以看出,这个猿犯了两个错误,一是第一句话没有标点,如果加个逗号,则被误解概率会降低(大概万分之一吧),二是没有给对话加锁,下面我们来加个锁。
猿:******表白开始(表白结束前请勿打断!)******
猿:“我不喜欢你,”
媛:“我知道了”(拉黑)——提示:对方表白未结束,请结束后再操作
猿:“还能喜欢谁呢?”
猿:******表白结束******
媛:“我知道了”(拉黑)
这样就完美了,双方都没有误解:)
简介
文件锁就像上面表白开始和结束的声明,在这个声明中间,其它人不可以动这个文件。
Linux文件锁有两种,分别是读锁(劝告/建议性锁)和写锁(排它/独占性锁),顾名思义,其他文件访问者可以知道是否有别人锁了文件,但是读锁不能阻止他修改文件。
Linux文件锁有两套实现,分别是FLOCK和POSIX,两套锁互相无影响。
文件锁主要有三套函数,分别是flock(2),fcntl(2)和lockf(3)
函数名 | 实现类别 | 支持读锁 | 支持写锁 | 支持文件局部锁 |
---|---|---|---|---|
flock | FLOCK | ∨ | Χ | Χ |
lockf | POSIX | Χ | ∨ | ∨ |
fcntl | POSIX | ∨ | ∨ | ∨ |
从表中大概可以猜出来,lockf是用fcntl实现的库函数。
代码演示
只演示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){//父进程先锁文件,2s后放开
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){//子进程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为父进程(简称小三),55144为子进程(简称小四)。小三抢先上了锁,小四顺利地打开了文件,然后小四非阻塞上锁失败后,成功地写入了文件。最后小三解锁后,小四才成功获得了锁。
在上述过程中,小四虽然没有获得锁,但是也能成功地写入文件,这印证了它只是个劝告性锁。
关于另外两个函数,未完待续......