Chapter 55. File Locking

Previous chapters have covered various techniques that processes can use to synchronize their actions, including signals (Chapter 20 to Chapter 22) and semaphores (Chapter 47 and Chapter 53). In this chapter, we look at further synchronization techniques designed specifically for use with files.

A frequent application requirement is to read data from a file, make some change to that data, and then write it back to the file. As long as just one process at a time ever uses a file in this way, then there are no problems. However, problems can arise if multiple processes are simultaneously updating a file. Suppose, for example, that each process performs the following steps to update a file containing a sequence number:

The problem here is that, in the absence of any synchronization technique, two processes could perform the above steps at the same time with (for example) the consequences shown in Figure 55-1 (here, we assume that the initial value of the sequence number is 1000).

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.

In this chapter, we describe two different APIs for placing file locks:

The flock() system call originated on BSD; fcntl() originated on System V.

The general method of using flock() and fcntl() is as follows:

Although file locking is normally used in conjunction with file I/O, we can also use it as a more general synchronization technique. Cooperating processes can follow a convention that locking all or part of a file indicates access by a process to some shared resource other than the file itself (e.g., a shared memory region).