March 15, 2002, 12:00 AM — Record Locking
To avert the problems associated with the file locking mechanism
presented last week (http://www.itworld.com/nl/lnx_tip/03082002/),
POSIX introduced record locking via the fcntl() syscall (the pre-POSIX
lockf() and flock() syscalls provide the same functionality but under
Linux, they are implemented as wrappers of the fcntl() syscall).
Record locking differs from file locking in two aspects: first, two or
more processes can access the same file as long as they're updating
different parts of it. For example, process A can lock the first 100
bytes of a file while another process is updating bytes 200-300.
Secondly, the kernel holds record locks, not by a process. Therefore,
when a process terminates, all its locks are automatically released.
Record Lock Types
There are two types of record locks: read locks (also called "shared
locks") and write locks (also called "exclusive locks"). Multiple
processes can lock the same file portion for read without conflicting
with each other. However, only one process at a time can hold a write
lock to a certain file region (note that write locks held by the same
process never conflict, even if the regions they lock coincide).
fcntl() is declared in
int fcntl(int fd, int command, long arg);
The first argument is a descriptor of the file to be locked. The second
argument can be one of the following:
F_SETLK -- sets the lock. If the locking operation fails, EAGAIN is
F_SETLKW -- similar to F_SETLK except that it blocks until the lock
F_GETLK -- Checks if the lock would be granted, without actually
locking the record. If the lock cannot be obtained, the pid of the
locking process is returned.
The third argument is a pointer to the following struct:
The field l_type can be one of three values: F_RDLCK for a shared lock,
F_WRLCK for an exclusive lock, or F_UNLCK for releasing an existing
lock. l_whence indicates the position of the lock's start. It can be
one of the values: SEEK_SET, SEEK_CUR, and SEEK_END. l_start indicates
the offset relative to l_whence. l_len is the number of bytes to lock
and l_pid holds the process's pid. For example, the following function
attempts to get a write lock for the first 100 bytes of a file:
int getlock(int fd)
struct flock lock;
lock.l_whence=SEEK_SET; /*file's beginning*/
lock.l_start=0;/*start at offset 0 from SEEK_SET*/
if(stat=fcntl(fd, F_SETLK, &lock)==0)