您的位置:首页 > 运维架构 > Linux

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 几次或者文件被打开几次

子进程不继承锁状态
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐