glibc 中的 flock() 与 fcntl() 语义

flock() vs. fcntl() semantics in glibc

相关:one,

据说 flock()(BSD 锁)和 fcntl()(POSIX 记录级锁)给用户不兼容的语义,特别是在锁释放方面。

然而,在glibcflock()是根据POSIXfcntl()实现的。 (我在官方 git repo 上查过这个,这里只是一个可见的 link)

https://code.woboq.org/userspace/glibc/sysdeps/posix/flock.c.html#18

/* This file implements the flock' function in terms of the POSIX.1fcntl' locking mechanism. In 4BSD, these are two incompatible locking mechanisms, perhaps with different semantics? */

这些事实如何结合在一起?

注意。这是完全错误的,请参阅已接受的答案。由于它有一些有用的链接,所以仍然保持活跃

好吧,这很无聊 -- fcntl 使用相同的 flock 结构作为参数并区分 打开文件锁 (BSD 锁在我的符号中上面)来自进程相关文件锁(POSIX我上面的符号中的记录级锁)基于l_pid字段值。

glibc docs on Open File Description Locks:

Open file description locks use the same struct flock as process-associated locks as an argument (see File Locks) and the macros for the command values are also declared in the header file fcntl.h. To use them, the macro _GNU_SOURCE must be defined prior to including any header file.

...

In contrast to process-associated locks, any struct flock used as an argument to open file description lock commands must have the l_pid value set to 0. Also, when returning information about an open file description lock in a F_GETLK or F_OFD_GETLK request, the l_pid field in struct flock will be set to -1 to indicate that the lock is not associated with a process.

另外,参见 glibc doc on process-associated file locks

在 Linux、flock is a system callflock 锁和 fcntl 锁是独立的,不会相互干扰(至少在本地文件系统上)。

glibc 源文件 sysdeps/posix/flock.c 实际上并未在 Linux 上使用。真正的实现是从 sysdeps/unix/sysv/linux/syscalls.list:

中的这一行生成的系统调用包装器
flock             -       flock           i:ii    __flock         flock

OFD 锁是另一种锁,但它们确实与 POSIX 记录锁交互。但是,它们在多线程时有更合理的行为,关闭一个描述符不会释放同一进程持有的同一底层文件的所有锁(这使得 POSIX 记录锁定很难在多线程进程中使用) .