110-建议性锁和强制性锁
来源:互联网 发布:python主要用来做什么 编辑:程序博客网 时间:2024/04/28 15:21
这两个名词非常陌生,如果你直接看 apue,可能会懵圈,不知道所云。没事,你已经找到了这一篇文章,相信你能学会。
1. 提出问题
假设有一个文件 b.txt,进程 A 对其进行了加锁。另外,还有一个进程 B,如果它打开了文件 b.txt,一上来就直接读写 b.txt,会不会出问题?
一般来说,如果进程 A 和进程 B 都是你自己写的,你肯定会遵守规则,两个进程你都会加上加锁和解锁的代码。
但是,如果进程 A 是你写的,进程 B 是另一个陌生人写的,它并不知道进程 A 会给 b.txt 加锁。索性就直接读写吧。
2. 建议性锁和强制性锁
- 建议性锁(Advisory Locking,注意这是形容词)
所谓的建议性锁,并不是一把真正的锁,而是文件系统本身具备的性质,一种属性。所以英文术语使用的是 Advisory Locking 而不是 Advisory Lock. 在中文里,真的是找不到对应的名词。。。
对遵守规则的人来说的。比方刚刚说进程 A 和进程 B 都是你自己的作品,你肯定是按规则办事的,如果进程 B 不是你写的,人家也不按规则办事,你完全没办法,即使再没有获得锁的情况下进程 B 也可以自由读写文件 b.txt.
- 强制性锁(Mandatory Locking)
如果文件系统开启了强制性锁属性,同时文件也开启了强制性锁机制,那么进程 B 试图在不获得锁的情况读写 b.txt,要么阻塞,要么返回 EAGAIN(看描述符是阻塞的还是非阻塞的).
根据上面的叙述,可以举个例子:
比如路口的红绿灯就是一种建议性设置,遵守还是不遵守完全在于个人。如果红绿灯是强制性的,就不在于个人意愿了,红灯情况下,强制把你拦住。
3. 打开强制性锁属性
3.1 打开文件强制性锁属性
默认情况下,文件系统的 Mandatory Locking 属性是关闭的,需要使用 mount -o mand 命令打开。
比如:
mount -o remount,mand /dev/sda1 /
表示重新将硬盘 /dev/sda1 以 Mandatory Locking 方式挂载到根文件系统。
如果你不知道你当前的文件系统上挂载的是哪个设备,可以通过 df -h
查看。
3.2 打开文件本身的强制性锁属性
即使你打开了文件系统的 Mandatory Locking 属性,你不打开文件本身的 Mandatory Locking 属性也是不行的。
有两种方法可以打开文件的 Mandatory Locking 属性:
- 打开文件前,给文件加上Mandatory Locking 属性。可以使用下面的命令:
chmod g+s b.txtchmod g-x b.txt
说的通俗点,就是去掉组执行属性,加上设置组 ID 属性。这种事情也完全可以在程序里去做,也就是第二种办法:
- 打开文件后,使用 fchmod 函数修改 x 和 s 属性:
struct stat statbuf;fstat(fd, &statbuf);fchmod(fd, (statbuf.st_mode & ~S_IXGRP) | S_ISGID);
千万不要问为什么这样做就可打开 Mandatory Locking 属性,这是设计者制定的规则,可能这看起来毫无根据……
4. 实验
程序 readfile 尝试在对文件加锁的情况下读取数据,该程序需要从命令行传入数,表示读取哪个文件。
./readfile <filename>
readfile 会在读取文件内容前对锁进行测试。
4.1 代码
// readfile.c#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#define PERR(err, msg) do { errno = err; perror(msg); exit(-1); } while(0);int testlock(int fd, int start, int len) { struct flock flk; int err; flk.l_type = F_WRLCK; flk.l_start = start; flk.l_whence = SEEK_SET; flk.l_len = len; err = fcntl(fd, F_GETLK, &flk); if (err < 0) PERR(errno, "getlock"); if (flk.l_type == F_UNLCK) return 0; return flk.l_pid;}int main(int argc, char *argv[]) { char *filename = argv[1]; char buf[64] = { 0 }; int err; int fd = open(filename, O_RDONLY | O_NONBLOCK); if (testlock(fd, 0, 0) != 0) printf("%s is locked\n", filename); err = read(fd, buf, 2); if (err < 0) printf("errno = %d, msg = %s\n", errno, strerror(errno)); else printf("content: %s\n", buf); close(fd); return 0;}
4.2 编译
$ gcc readfile.c -o readfile
4.3 运行
- 测试一
不开启 Mandatory Locking 属性。
图1 不开启 Mandatory Locking 属性时的运行结果
- 测试二
开启 Mandatory Locking 属性。
图2 开启 Mandatory Locking 属性时的运行结果
可以看到,在 Mandatory Locking 开启的情况下, readfile 进程尝试以 NONBLOCK 方式读取数据时产生错误。errno = 11 在这里实际上就是 EAGAIN.
5. 总结
- 理解 Advisory Locking 和 Mandatory Locking 的作用
- 掌握打开 Mandatory Locking 的方法
- 110-建议性锁和强制性锁
- 建议性锁和强制性锁
- 建议性锁和强制性锁
- 建议性锁和强制性锁
- 强制性锁和建议性锁
- 建议性锁和强制性锁
- 强制性锁建议性锁
- 强制性锁建议性锁
- 强制性锁建议性锁 .
- 强制性锁建议性锁
- 强制性锁建议性锁 .
- 强制性锁建议性锁 .
- 强制性锁建议性锁
- 建议性锁和强制性锁机制下的锁
- 建议性锁和强制性锁机制下的锁
- fcntl函数中的建议性锁和强制性锁
- 文件的建议性锁和强制性锁
- 建议性锁和强制性锁的区别
- httpclient使用详解(爬虫)
- 减邮票
- SQL transformation
- SQL集合函数中case when then 使用技巧
- 如何将图片导入到NiceLabel里?
- 110-建议性锁和强制性锁
- sql server数据库连接字符串大全
- Java多线程系列--“基础篇”10之 线程优先级和守护线程
- 隆重推荐 MWeb !
- Redis集群搭建与简单使用
- Java多线程系列--“基础篇”11之 生产消费者问题
- vue.js开发环境搭建(vue-cli脚手架)
- 农村致富新项目,攻坚脱贫乃国策,网络扶贫看好TPS云集品
- Ubuntu 14.04 安装PHP的redis扩展