使用 `fcntl` 和 `flock` 锁定有什么区别?

What is the difference between locking with `fcntl` and `flock`?

我读了好几个小时,但不明白这两种锁之间的区别是什么。我唯一理解的是 fcntl() lock 提供了一个可以锁定特定字节的粒度锁,并且只有 fcntl() 支持 NFS 锁定。

据说区别在于它们的语义,当被 dup() 或 while fork() 复制时它们的行为如何,但我不明白在实践中有什么区别。

我的情况是,我正在写入基于 fork() 的服务器中的日志文件,当 某事 发生时,每个分叉进程都写入同一个文件.为什么我要使用 flock() 以及为什么我要使用 fcntl() 锁?

我试图根据现有文档找出差异并得出以下结论(如果我错了请纠正我):

使用 fcntl() (POSIX):

  • 您在文件系统级别创建了一个锁定记录,包括进程 ID。

  • 如果进程终止或关闭此文件的任何文件描述符,锁定记录将被系统删除。

  • 如果文件描述符不是用写访问打开的,则排他锁请求将失败。

  • 简单地说:fnctl 锁作为 Process <--> File 关系工作,忽略 filedescriptors

flock() (BSD) 不同(Linux:自内核 2.0 以来,flock() 本身作为系统调用实现,而不是在 GNU C 库中模拟为对fcntl):

  • flock() 在系统的 "Open file descriptions" 上创建锁。 "Open file descriptions" 由 open() 调用生成。

  • 文件描述符 (FD) 是对 "Open file description" 的引用。 dup()fork() 生成的 FD 引用相同的 "Open file description".

  • 一个进程可能会通过多次打开()文件为一个文件生成多个"Open file descriptions"

  • flock() 通过 FD 在 "Open file description"

  • 上放置它的锁
  • 因此 flock() 可用于在进程和线程(在一个或多个进程中)之间同步文件访问。

  • 有关 "Open file descriptions" 的详细信息,请参阅 flock(2) and especially open(2) 手册页。

在您的场景中,您可能希望使用基于 fcntl() 的锁,因为您的分叉进程将自行打开 () 日志文件,并且不希望继承带有可能放置的锁的文件描述符。

如果您需要多个线程之间的同步,可能在多个进程中,您应该使用基于 flock() 的锁,前提是您的系统支持它们而无需 fcntl() 模拟。然后每个线程都需要打开()文件而不是使用 dup()ed 或 fork()ed 句柄。