22

I'm reading for hours but can't understand what is the difference between the two locks. The only thing I understand is that fcntl() lock is offering a granular lock that can lock specific bytes and that only fcntl() supports NFS locking.

It's said that the difference is in their semantics, how do they behave when being duplicated by dup() or while fork(), but I can't understand what is the difference in practice.

My scenario is that I'm writing to a log file in a fork() based server, where every forked process is writing to the same file when something happens. Why would I want to use flock() and why would I want to use fcntl() locks?

Quaker
  • 1,483
  • 3
  • 20
  • 36
  • 1
    Previous question found for Linux. The interesting answer mentions Posix too. http://stackoverflow.com/questions/22409780/flock-vs-lockf-on-linux – Weather Vane Apr 13 '15 at 17:30
  • `flock()` and `lockf()` are two different things, `lockf()` usually wraps `fcntl()`, and I was asking what exactly are the semantics (behaviour with respect to closing and passing). – Quaker Apr 13 '15 at 17:32
  • The answer I linked starts *"The practical difference between flock() and lockf() is in the semantics (behaviour with respect to closing and passing)"* and as `lockf()` can wrap `fcntl()` maybe that answer is relevant. – Weather Vane Apr 13 '15 at 17:43
  • Weather, I copied the end of my last comment from the answer you've posted. I'm sorry if I haven't explained myself well (English isn't my mother tongue), I want to know what is the difference between the behaviors of both when closing and passing. – Quaker Apr 13 '15 at 17:46

1 Answers1

19

I have tried to figure out the differences based on available documentation and took the following conclusions (please correct me if I am wrong):

With fcntl() (POSIX):

  • you create a lock record on the file at filesystem level including process id.

  • If the process dies or closes any filedescriptor to this file, the lock record gets removed by the system.

  • A request for an exclusive lock shall fail if the file descriptor was not opened with write access.

  • simply: fnctl locks work as a Process <--> File relationship, ignoring filedescriptors

flock() (BSD) is different (Linux: since kernel 2.0, flock() is implemented as a system call in its own right rather than being emulated in the GNU C library as a call to fcntl):

  • flock() creates locks on systems's "Open file descriptions". "Open file descriptions" are generated by open() calls.

  • a filedescriptor (FD) is a reference to a "Open file description". FDs generated by dup() or fork() refer to the same "Open file description".

  • a process may generate multiple "Open file descriptions" for one file by opening() the file multiple times

  • flock() places it's locks via a FD on a "Open file description"

  • therefore flock() may be used to synchronize file access among processes as well as threads (in one ore more processes).

  • see flock(2) and especially open(2) man pages for details on "Open file descriptions".

In Your scenario you probably want to use fcntl() based locks, because your forked processes will open() the logfile on their own and do not expect to inherit a filedescriptor with a possibly placed lock.

If you need synchronisation among multiple threads, possibly in more than one process, you should use flock() based locks if your system supports them without emulation by fcntl(). Then every thread needs to open() the file rather than using dup()ed or fork()ed handles.

Edit 2022: An excellent write-up and additional thoughts here: https://lwn.net/Articles/586904/

NorbertM
  • 1,226
  • 12
  • 22