[ACCEPTED]-fcntl, lockf, which is better to use for file locking?-locking

Accepted answer
Score: 65

What is the difference between lockf and fcntl:

On many systems, the lockf() library routine is 51 just a wrapper around fcntl(). That is to say 50 lockf offers a subset of the functionality that 49 fcntl does.


But on some systems, fcntl and lockf locks are 48 completely independent.


Since it is implementation 47 dependent, make sure to always use the same 46 convention. So either always use lockf 45 from both your processes or always use fcntl. There 44 is a good chance that they will be interchangeable, but 43 it's safer to use the same one.

Which one 42 you chose doesn't matter.

Some notes on mandatory vs advisory locks:

Locking in unix/linux 41 is by default advisory, meaning other processes 40 don't need to follow the locking rules that 39 are set. So it doesn't matter which way 38 you lock, as long as your co-operating processes 37 also use the same convention.

Linux does 36 support mandatory locking, but only if your file 35 system is mounted with the option on and 34 the file special attributes set. You can 33 use mount -o mand to mount the file system and set the 32 file attributes g-x,g+s to enable mandatory locks, then 31 use fcntl or lockf. For more information on how 30 mandatory locks work see here.

Note that locks 29 are applied not to the individual file, but 28 to the inode. This means that 2 filenames 27 that point to the same file data will share 26 the same lock status.

In Windows on the 25 other hand, you can actively exclusively 24 open a file, and that will block other processes 23 from opening it completely. Even if they 22 want to. I.e., the locks are mandatory. The 21 same goes for Windows and file locks. Any 20 process with an open file handle with appropriate 19 access can lock a portion of the file and 18 no other process will be able to access 17 that portion.

How mandatory locks work in Linux:

Concerning mandatory locks, if 16 a process locks a region of a file with 15 a read lock, then other processes are permitted 14 to read but not write to that region. If 13 a process locks a region of a file with 12 a write lock, then other processes are not 11 permitted to read nor write to the file. What 10 happens when a process is not permitted 9 to access the part of the file depends on 8 if you specified O_NONBLOCK or not. If blocking is 7 set it will wait to perform the operation. If 6 no blocking is set you will get an error 5 code of EAGAIN.

NFS warning:

Be careful if you are using locking 4 commands on an NFS mount. The behavior 3 is undefined and the implementation widely 2 varies whether to use a local lock only 1 or to support remote locking.

Score: 10

Both interfaces are part of the POSIX standard, and 17 nowadays both interfaces are available on 16 most systems (I just checked Linux, FreeBSD, Mac 15 OS X, and Solaris). Therefore, choose the 14 one that fits better your requirements and 13 use it.

One word of caution: it is unspecified 12 what happens when one process locks a file 11 using fcntl and another using lockf. In 10 most systems these are equivalent operations 9 (in fact under Linux lockf is implemented 8 on top of fcntl), but POSIX says their interaction 7 is unspecified. So, if you are interoperating 6 with another process that uses one of the 5 two interfaces, choose the same one.

Others 4 have written that the locks are only advisory: you 3 are responsible for checking whether a region 2 is locked. Also, don't use stdio functions, if 1 you want the to use the locking functionality.

Score: 10

Your main concerns, in this case (i.e. when 33 "coding a Linux daemon and wondering which is better suited 32 to use for enforcing mutual exclusion"), should be:

  1. will the locked file be local or can it be on NFS?
    • e.g. can the user trick you into creating and locking your daemon's pid file on NFS?
  2. how will the lock behave when forking, or when the daemon process is terminated with extreme prejudice e.g. kill -9?

The flock and fcntl commands 31 behave differently in both cases.

My recommendation 30 would be to use fcntl. You may refer to the 29 File locking article on Wikipedia for an in-depth discussion of the problems 28 involved with both solutions:

Both flock 27 and fcntl have quirks which occasionally 26 puzzle programmers from other operating 25 systems. Whether flock locks work on network 24 filesystems, such as NFS, is implementation dependent. On 23 BSD systems flock calls are successful 22 no-ops. On Linux prior to 2.6.12 flock 21 calls on NFS files would only act locally. Kernel 20 2.6.12 and above implement flock calls 19 on NFS files using POSIX byte range locks. These 18 locks will be visible to other NFS clients 17 that implement fcntl()/POSIX locks.1 Lock 16 upgrades and downgrades release the old 15 lock before applying the new lock. If 14 an application downgrades an exclusive lock 13 to a shared lock while another application 12 is blocked waiting for an exclusive lock, the 11 latter application will get the exclusive 10 lock and the first application will be 9 locked out. All fcntl locks associated 8 with a file for a given process are removed 7 when any file descriptor for that file 6 is closed by that process, even if a lock was 5 never requested for that file descriptor. Also, fcntl 4 locks are not inherited by a child process. The fcntl 3 close semantics are particularly troublesome 2 for applications which call subroutine 1 libraries that may access files.

Score: 9

I came across an issue while using fcntl 24 and flock recently that I felt I should 23 report here as searching for either term 22 shows this page near the top on both.

Be 21 advised BSD locks, as mentioned above, are 20 advisory. For those who do not know OSX (darwin) is 19 BSD. This must be remembered when opening 18 a file to write into.

To use fcntl/flock 17 you must first open the file and get its 16 ID. However if you have opened the file 15 with "w" the file will instantly be zeroed out. If 14 your process then fails to get the lock 13 as the file is in use elsewhere, it will 12 most likely return, leaving the file as 11 0kb. The process which had the lock will 10 now find the file has vanished from underneath 9 it, catastrophic results normally follow.

To 8 remedy this situation, when using file locking, never open 7 the file "w", but instead open it "a", to 6 append. Then if the lock is successfully 5 acquired, you can then safely clear the 4 file as "w" would have, ie. :

fseek(fileHandle, 0, SEEK_SET);//move 3 to the start

ftruncate(fileno((FILE *) fileHandle), 0);//clear 2 it out

This was an unpleasant lesson for 1 me.

Score: 1

As you're only coding a daemon which uses 10 it for mutual exclusion, they are equivalent, after 9 all, your application only needs to be compatible 8 with itself.

The trick with the file locking 7 mechanisms is to be consistent - use one 6 and stick to it. Varying them is a bad idea.

I 5 am assuming here that the filesystem will 4 be a local one - if it isn't, then all bets 3 are off, NFS / other network filesystems 2 handle locking with varying degrees of effectiveness 1 (in some cases none)

More Related questions