The Linux Programming Interface

(nextflipdebug5) #1

1146 Chapter 55


If the link() call succeeds, we have obtained the lock. If it fails (EEXIST), then
another process has the lock and we must try again later. This technique suffers the
same limitations as the open(file, O_CREAT | O_EXCL,...) technique described above.

open(file, O_CREAT | O_TRUNC | O_WRONLY, 0) plus unlink(file)
The fact that calling open() on an existing file fails if O_TRUNC is specified and write
permission is denied on the file can be used as the basis of a locking technique. To
obtain a lock, we use the following code (which omits error checking) to create a
new file:

fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, (mode_t) 0);
close(fd);

For an explanation of why we use the (mode_t) cast in the open() call above, see
Appendix C.

If the open() call succeeds (i.e., the file didn’t previously exist), we have the lock. If it
fails with EACCES (i.e., the file exists and has no permissions for anyone), then
another process has the lock, and we must try again later. This technique suffers
the same limitations as the previous techniques, with the added caveat that we can’t
employ it in a program with superuser privileges, since the open() call will always
succeed, regardless of the permissions that are set on the file.

55.8 Summary


File locks allow processes to synchronize access to a file. Linux provides two file
locking system calls: the BSD-derived flock() and the System V–derived fcntl().
Although both system calls are available on most UNIX implementations, only
fcntl() locking is standardized in SUSv3.
The flock() system call locks an entire file. Two types of locks may be placed:
shared locks, which are compatible with shared locks held by other processes, and
exclusive locks, which prevent other processes from placing any type of lock.
The fcntl() system call places locks (“record locks”) on any region of a file, rang-
ing from a single byte to the entire file. Two types of locks may be placed: read
locks and write locks, which have similar compatibility semantics to the shared and
exclusive locks placed via flock(). If a blocking (F_SETLKW) lock request would bring
about a deadlock situation, then the kernel causes fcntl() to fail (with the error
EDEADLK) in one of the affected processes.
Locks placed using flock() and fcntl() are invisible to one another (except on sys-
tems that implement flock() using fcntl()). The locks placed via flock() and fcntl() have
different semantics with respect to inheritance across fork() and release when file
descriptors are closed.
The Linux-specific /proc/locks file displays the file locks currently held by all
processes on the system.

Further information
An extensive discussion of fcntl() record locking can be found in [Stevens & Rago,
2005] and [Stevens, 1999]. Some details of the implementation of flock() and fcntl()
Free download pdf