Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

492 Advanced I/O Chapter 14


Implied Inheritance and Release of Locks


Three rules govern the automatic inheritance and release of recordlocks.


  1. 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.

  2. 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.

  3. 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();
Free download pdf