文件锁
https://gavv.github.io/articles/file-locks/
----------------------------------
File locking in Linux
Table of contents
Introduction
File locking is a mutual-exclusion mechanism for files. Linux supports two major kinds of file locks:
- advisory locks
- mandatory locks
Below we discuss all lock types available in POSIX and Linux and provide usage examples.
Advisory locking
Traditionally, locks are advisory in Unix. They work only when a process explicitly acquires and releases locks, and are ignored if a process is not aware of locks.
There are several types of advisory locks available in Linux:
- BSD locks (flock)
- POSIX record locks (fcntl, lockf)
- Open file description locks (fcntl)
All locks except the lockf
function are reader-writer locks, i.e. support exclusive and shared modes.
Note that flockfile
and friends have nothing to do with the file locks. They manage internal mutex of the FILE
object from stdio.
Reference:
- File Locks, GNU libc manual
- Open File Description Locks, GNU libc manual
- File-private POSIX locks, an LWN article about the predecessor of open file description locks
Common features
The following features are common for locks of all types:
- All locks support blocking and non-blocking operations.
- Locks are allowed only on files, but not directories.
- Locks are automatically removed when the process exits or terminates. It’s guaranteed that if a lock is acquired, the process acquiring the lock is still alive.
Differing features
This table summarizes the difference between the lock types. A more detailed description and usage examples are provided below.
BSD locks | lockf function | POSIX record locks | Open file description locks | |
---|---|---|---|---|
Portability | widely available | POSIX (XSI) | POSIX (base standard) | Linux 3.15+ |
Associated with | File object | [i-node, pid] pair | [i-node, pid] pair | File object |
Applying to byte range | no | yes | yes | yes |
Support exclusive and shared modes | yes | no | yes | yes |
Atomic mode switch | no | - | yes | yes |
Works on NFS (Linux) | Linux 2.6.12+ | yes | yes | yes |
File descriptors and i-nodes
A file descriptor is an index in the per-process file descriptor table (in the left of the picture). Each file descriptor table entry contains a reference to a file object, stored in the file table (in the middle of the picture). Each file object contains a reference to an i-node, stored in the i-node table (in the right of the picture).
A file descriptor is just a number that is used to refer a file object from the user space. A file object represents an opened file. It contains things likes current read/write offset, non-blocking flag and another non-persistent state. An i-node represents a filesystem object. It contains things like file meta-information (e.g. owner and permissions) and references to data blocks.
File descriptors created by several open()
calls for the same file path point to different file objects, but these file objects point to the same i-node. Duplicated file descriptors created by dup2()
or fork()
point to the same file object.
A BSD lock and an Open file description lock is associated with a file object, while a POSIX record lock is associated with an [i-node, pid]
pair. We’ll discuss it below.
BSD locks (flock)
The simplest and most common file locks are provided by flock(2)
.
Features:
- not specified in POSIX, but widely available on various Unix systems
- always lock the entire file
- associated with a file object
- do not guarantee atomic switch between the locking modes (exclusive and shared)
- up to Linux 2.6.11, didn’t work on NFS; since Linux 2.6.12, flock() locks on NFS are emulated using fcntl() POSIX record byte-range locks on the entire file (unless the emulation is disabled in the NFS mount options)
The lock acquisition is associated with a file object, i.e.:
- duplicated file descriptors, e.g. created using
dup2
orfork
, share the lock acquisition; - independent file descriptors, e.g. created using two
open
calls (even for the same file), don’t share the lock acquisition;
This means that with BSD locks, threads or processes can’t be synchronized on the same or duplicated file descriptor, but nevertheless, both can be synchronized on independent file descriptors.
flock()
doesn’t guarantee atomic mode switch. From the man page:
Converting a lock (shared to exclusive, or vice versa) is not guaranteed to be atomic: the existing lock is first removed, and then a new lock is established. Between these two steps, a pending lock request by another process may be granted, with the result that the conversion either blocks, or fails if LOCK_NB was specified. (This is the original BSD behaviour, and occurs on many other implementations.)
This problem is solved by POSIX record locks and Open file description locks.
Usage example:
#include <sys/file.h>
// acquire shared lock
if (flock(fd, LOCK_SH) == -1) {
exit(1);
}
// non-atomically upgrade to exclusive lock
// do it in non-blocking mode, i.e. fail if can't upgrade immediately
if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
exit(1);
}
// release lock
// lock is also released automatically when close() is called or process exits
if (flock(fd, LOCK_UN) == -1) {
exit(1);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2020-04-26 【转】上传进度----PHP大文件分割上传(分片上传)
2018-04-26 【转】supervisord使用
2018-04-26 手动安装pip
2017-04-26 ubuntu 中 iptables 和 ufw 的关系
2016-04-26 javascript 函数 add(1)(2)(3)(4)实现无限极累加 —— 一步一步原理解析
2016-04-26 不动笔墨不读书
2016-04-26 html5 canvas 实现简单的画图