扫码关注官方订阅号
首先锁信息是不是文件的一部分?其次断电重启后会自动消失还是永远存在无法解除(因为设置锁的进程已经不复存在了)?
欢迎选择我的课程,让我们一起见证您的进步~~
Linux下有两种不同的文件锁机制,一种是通过 flock 系统调用锁定整个文件,另一种是通过 fcntl 系统调用完成更细粒度的记录锁(锁定文件中的一个区间)
flock
fcntl
Linux下,在最初打开一个文件的时候,最终都是落到 open 这个系统调用上。
open
open系统调用 (@./fs/open.c) 里头做了很多事情,跟文件锁有关的主要是分配了一个 struct file 对象,并且给该对象的 struct inode *inode 和 struct file_operations *f_op 成员赋值。
struct file
struct inode *inode
struct file_operations *f_op
其中 inode 是对应文件系统分配的(比如 ext4 文件系统的分配函数是 fs/ext4/inode.c 中的 ext4_iget),其中也包含了一个 struct file_operations * 类型的成员 i_fop,即针对该文件系统文件操作的函数指针集合。
ext4_iget
struct file_operations *
i_fop
以上提到的两次 struct file_operations 对象包含 flock 和 lock 两个函数指针,分别用于上述的两种不同锁机制。
struct file_operations
lock
内核在内存中只会给一个文件分配一个 struct inode 对象,不同进程打开同一个文件时,都会单独分配一个 struct file 对象,且 file->inode 指向该文件对应的 inode 对象。其中 file->f_op 实际上就是在 open 系统调用过程中,从 inode->i_fop 拷贝过来的。(open -> do_sys_open -> do_filp_open -> path_openat -> do_last -> vfs_open -> do_dentry_open: f->f_op = fops_get(inode->i_fop))
struct inode
file->inode
file->f_op
inode->i_fop
f->f_op = fops_get(inode->i_fop)
内核首先根据第一个参数 fd 找到内核中的 struct file 对象,判断 file->f_op->flock 指针是否有效,如果有效(说明是文件系统指定了加锁机制,例如 fs/fuse/file.c 中指定了 fuse_file_flock 函数,而ext2/3/4都没有指定),就调用该指针指向的函数来执行加锁操作;如果不存在,则执行flock_lock_file_wait -> flock_lock_inode (@ fs/locks.c)。
file->f_op->flock
fuse_file_flock
flock_lock_file_wait
flock_lock_inode
如果文件系统没有指定加锁机制,那么 flock_lock_inode 会尝试给该文件对应的 inode 加文件锁(加锁机制比较琐碎,我没看得太细,大致是获取 inode->i_flctx->flc_lock 这个spinlock,然后增删改查 inode->i_flctx->flc_flock 这个链表,但是可以看出全是内存操作)。
inode->i_flctx->flc_lock
inode->i_flctx->flc_flock
如果文件系统指定了加锁机制,那么就要具体考察对应的加锁机制是否是持久化在磁盘上了;不过从加锁这个需求本身去考察,大多数情况下应当是期望能够快速完成,除了特殊情况,可以认为只是在内存中操作,并没有持久化到磁盘。
与 flock 类似,区别在于判断的函数指针是 file->f_op->lock ,如果不存在的话,则调用 posix_lock_file 尝试对该 inode 加记录锁,也是在 inode->i_flctx 上面倒腾,不过用的是 inode->i_flctx->flc_lock 这个链表,具体操作更复杂一些,还要考虑记录锁区间的交叉等问题。
file->f_op->lock
posix_lock_file
inode->i_flctx
具体情况取决于文件系统是否使用了指定的加锁机制,如果有,要单独分析。
如果没有,所有的锁都是在内存中维护的,如果断电,锁自动失效。这样也比较符合通常的理解。
另外,针对文件的加锁行为一般都是进程执行的,进程退出(包括意外退出)时,exit 系统调用会调用 exit_files 函数清理该进程打开的所有文件。
exit_files
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部
Linux下的文件锁
Linux下有两种不同的文件锁机制,一种是通过
flock系统调用锁定整个文件,另一种是通过fcntl系统调用完成更细粒度的记录锁(锁定文件中的一个区间)open 系统调用
Linux下,在最初打开一个文件的时候,最终都是落到
open这个系统调用上。open系统调用 (@./fs/open.c) 里头做了很多事情,跟文件锁有关的主要是分配了一个
struct file对象,并且给该对象的struct inode *inode和struct file_operations *f_op成员赋值。其中 inode 是对应文件系统分配的(比如 ext4 文件系统的分配函数是 fs/ext4/inode.c 中的
ext4_iget),其中也包含了一个struct file_operations *类型的成员i_fop,即针对该文件系统文件操作的函数指针集合。以上提到的两次
struct file_operations对象包含flock和lock两个函数指针,分别用于上述的两种不同锁机制。内核在内存中只会给一个文件分配一个
struct inode对象,不同进程打开同一个文件时,都会单独分配一个struct file对象,且file->inode指向该文件对应的 inode 对象。其中file->f_op实际上就是在 open 系统调用过程中,从inode->i_fop拷贝过来的。(open -> do_sys_open -> do_filp_open -> path_openat -> do_last -> vfs_open -> do_dentry_open:f->f_op = fops_get(inode->i_fop))flock 加锁
内核首先根据第一个参数 fd 找到内核中的
struct file对象,判断file->f_op->flock指针是否有效,如果有效(说明是文件系统指定了加锁机制,例如 fs/fuse/file.c 中指定了fuse_file_flock函数,而ext2/3/4都没有指定),就调用该指针指向的函数来执行加锁操作;如果不存在,则执行flock_lock_file_wait->flock_lock_inode(@ fs/locks.c)。如果文件系统没有指定加锁机制,那么
flock_lock_inode会尝试给该文件对应的 inode 加文件锁(加锁机制比较琐碎,我没看得太细,大致是获取inode->i_flctx->flc_lock这个spinlock,然后增删改查inode->i_flctx->flc_flock这个链表,但是可以看出全是内存操作)。如果文件系统指定了加锁机制,那么就要具体考察对应的加锁机制是否是持久化在磁盘上了;不过从加锁这个需求本身去考察,大多数情况下应当是期望能够快速完成,除了特殊情况,可以认为只是在内存中操作,并没有持久化到磁盘。
fcntl 加锁
与
flock类似,区别在于判断的函数指针是file->f_op->lock,如果不存在的话,则调用posix_lock_file尝试对该 inode 加记录锁,也是在inode->i_flctx上面倒腾,不过用的是inode->i_flctx->flc_lock这个链表,具体操作更复杂一些,还要考虑记录锁区间的交叉等问题。结论
具体情况取决于文件系统是否使用了指定的加锁机制,如果有,要单独分析。
如果没有,所有的锁都是在内存中维护的,如果断电,锁自动失效。这样也比较符合通常的理解。
另外,针对文件的加锁行为一般都是进程执行的,进程退出(包括意外退出)时,exit 系统调用会调用
exit_files函数清理该进程打开的所有文件。