ptg10805159
492 Advanced I/O Chapter 14
Implied Inheritance and Release of Locks
Three rules govern the automatic inheritance and release of recordlocks.
- Locks areassociated with a process and a file. This has two implications. The first is
obvious: when a process terminates, all its locks arereleased. The second is far from
obvious: whenever a descriptor is closed, any locks on the file referenced by that
descriptor for that process arereleased. This means that if we make the calls
fd1 = open(pathname, ...);
read_lock(fd1, ...);
fd2 = dup(fd1);
close(fd2);
after theclose(fd2),the lock that was obtained onfd1is released. The same
thing would happen if we replaced thedupwithopen, as in
fd1 = open(pathname, ...);
read_lock(fd1, ...);
fd2 = open(pathname, ...)
close(fd2);
to open the same file on another descriptor. - Locks arenever inherited by the child across afork.This means that if a process
obtains a lock and then callsfork,the child is considered another process with
regard to the lock that was obtained by the parent. The child has to callfcntlto
obtain its own locks on any descriptors that wereinherited across thefork.This
constraint makes sense because locks aremeant to prevent multiple processes from
writing to the same file at the same time. If the child inherited locks across afork,
both the parent and the child could write to the same file at the same time. - Locks areinherited by a new program across anexec.Note, however,that if the
close-on-exec flag is set for a file descriptor,all locks for the underlying file are
released when the descriptor is closed as part of anexec.
FreeBSD Implementation
Let’s take a brief look at the data structures used in the FreeBSD implementation. This
should help clarify rule 1, which states that locks areassociated with a process and a
file.
Consider a process that executes the following statements (ignoring error returns):
fd1 = open(pathname, ...);
write_lock(fd1, 0, SEEK_SET, 1); /* parent write locks byte 0 */
if ((pid = fork()) > 0) { /* parent */
fd2 = dup(fd1);
fd3 = open(pathname, ...);
}else if (pid == 0) {
read_lock(fd1, 1, SEEK_SET, 1); /* child read locks byte 1 */
}
pause();