1118 Chapter 55
Figure 55-1: Two processes updating a file at the same time without synchronization
The problem is clear: at the end of these steps, the file contains the value 1001,
when it should contain the value 1002. (This is an example of a race condition.) To
prevent such possibilities, we need some form of interprocess synchronization.
Although we could use (say) semaphores to perform the required synchronization,
using file locks is usually preferable, because the kernel automatically associates
locks with files.
[Stevens & Rago, 2005] dates the first UNIX file locking implementation to
1980, and notes that fcntl() locking, upon which we primarily focus in this
chapter, appeared in System V Release 2 in 1984.
In this chapter, we describe two different APIs for placing file locks:
z flock(), which places locks on entire files; and
z fcntl(), which places locks on regions of a file.
The flock() system call originated on BSD; fcntl() originated on System V.
The general method of using flock() and fcntl() is as follows:
- Place a lock on the file.
- Perform file I/O.
- Unlock the file so that another process can lock it.
Read seq. # (obtains 1000)
Process A Process B
time slice
expires
time slice
begins
time slice
begins
time slice
ends
Read seq. # (obtains 1000)
Use seq. #
Increment seq. # (to 1001)
and write back to file
Use seq. #
Increment seq. # (to 1001)
and write back to file
Executing
on CPU
Waiting
for CPU
Key