108-记录锁(继承与释放)
2017-03-20 12:22
120 查看
1. 释放
如果进程关闭,所有的记录锁都被释放任何一个描述符关闭,该描述符引用的文件上的任何记录都被释放。
有关上面两点,实际上在上一篇文章就已经解释过了,对于同一个文件来说,无论你是 open 还是 dup 多少次,vnode 节点始终只有一份,而锁的信息是在 vnode 节点中保存。
2. 继承
fork 产生的子进程不继承父进程所设置的锁。这种约束是有依据的:因为记录锁的作用就是阻止多个进程同时写同一个文件。如果 fork 继承了父进程的锁,那么父进程和子进程相当于同时获得了锁,这是错误的。
执行 exec 系列函数后,如果描述符没有设置 O_CLOEXEC(执行时关闭),新程序仍然可以使用原来的锁。
3. 实验
程序 closelock 对文件 test.txt 的 [2,4) 字节进行加写锁,然后 dup 了一份新的描述符,然后立即 close,此时对文件锁进行测试,看是否能够获得写锁。3.1 代码
// closelock.c #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #define PERR(err, msg) do { errno = err; perror(msg); exit(-1); } while(0) int lock(int fd) { puts("locking..."); struct flock flk; int err; flk.l_type = F_WRLCK; flk.l_start = SEEK_SET; flk.l_whence = 2; flk.l_len = 2; err = fcntl(fd, F_SETLKW, &flk); if (err < 0) PERR(errno, "lock"); puts("locked..."); return err; } int unlock(int fd) { puts("unlocking..."); struct flock flk; int err; flk.l_type = F_UNLCK; flk.l_start = SEEK_SET; flk.l_whence = 2; flk.l_len = 2; err = fcntl(fd, F_SETLKW, &flk); if (err < 0) PERR(errno, "unlock"); puts("unlocked..."); return err; } int main() { printf("pid: %d\n", getpid()); int fd = open("test.txt", O_WRONLY); lock(fd); sleep(10); puts("close fd2"); int fd2 = dup(fd); close(fd2); sleep(10); unlock(fd); close(fd); return 0; }
3.2 编译和运行
编译$ gcc closelock.c -o closelock
运行
图1 运行结果
图 1 中,左侧是上面的代码运行的结果,右侧使用我们之前写的 testlock 程序《记录锁(测试命令)》 进行测试是否能加写锁。第一次运行是在 close fd2 前进行,第二次是在 close fd2 后运行的结果。
可以看到,第二次测试结果是 0,表示该文件已经没有锁了,尽管 closelock 此时还没有执行解锁函数。
4. 总结
关闭描述符会关闭锁,无论该文件描述符被 dup 几次或者文件被打开几次子进程不继承锁状态
相关文章推荐
- 带有头指针的链表的 创建 输出 查找 删除 释放 排序(冒泡排序)功能实现(尾插法(自动记录最后一个节点))
- C++builder项目记录【互斥体】【桌面快捷方式】【form禁止拉伸与释放】【屏蔽WebBrowser右击】最简单实用
- 将数据库常用的操作(连接数据库,获得所有数据,获得一条记录,获得一列记录,获得一条索引数组,获得一条关联数组)都给封装到db.class.php里面,谁需要谁继承这个类 注意:提交封装的类文件
- [C/C++][经典探讨]类继承中,通过基类指针delete释放,是否会造成内存泄漏
- Java学习记录(8)——继承
- Oracle 删除表中记录 如何释放表及表空间大小
- 1115学习记录 拖拽继承与封装
- extjs 继承记录
- 互斥锁 记录锁 继承
- 一个 Qt 显示图片的控件(继承QWidget,使用QPixmap记录图像,最后在paintEvent进行绘制,可缩放)
- leetcode刷题,总结,记录,备忘 108
- kotlin 学习记录 基本语法 (4 类和继承)
- Lua学习记录 — (10)面向对象-类(公有私有属性/静态,重写,运算符重载,继承等等)
- Oracle 删除表中记录 如何释放表及表空间大小
- c++函数指针、虚继承大小、类型转换、C特殊情况记录
- MVC 通过继承HandleErrorAttribute,使用log4net或ELMAH组件记录异常等
- java学习记录笔记--继承,super,Object类
- Oracle 删除表中记录 如何释放表及表空间大小
- 删除文件后,磁盘空间没有释放的处理记录
- JAVA学习记录(三)面向对象编程三大特性之继承