File Locking and Unlocking With Fcntl
/**************************** FILE LOCKING DEMO **************************/
#include <sys/types.h> /*********** Write Lock Setter *******/
#include <unistd.h>
#include <fcntl.h>
main()
{
int fd;
struct flock lock, savelock;
fd = open("book.dat", O_RDWR);
lock.l_type = F_WRLCK; /* Test for any lock on any part of file. */
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
savelock = lock;
fcntl(fd, F_GETLK, &lock); /* Overwrites lock structure with preventors. */
if (lock.l_type == F_WRLCK)
{
printf("Process %ld has a write lock already!\n", lock.l_pid);
exit(1);
}
else if (lock.l_type == F_RDLCK)
{
printf("Process %ld has a read lock already!\n", lock.l_pid);
exit(1);
}
else
fcntl(fd, F_SETLK, &savelock);
pause();
}
/*****************************************************************************/
#include <stdio.h> /************* Read Lock Setter *************/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
main()
{
struct flock lock, savelock;
int fd;
fd = open("book.dat", O_RDONLY);
lock.l_type = F_RDLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 50;
savelock = lock;
fcntl(fd, F_GETLK, &lock);
if (lock.l_type == F_WRLCK)
{
printf("File is write-locked by process %ld.\n", lock.l_pid);
exit(1);
}
fcntl(fd, F_SETLK, &savelock);
pause();
}
/********************** SAMPLE PROGRAM EXECUTIONS ***************************/
$ wl &
[1] 20866
$ rl
File is write-locked by process 20866.
$ rl &
[1] 20868
$ wl
Process 20868 has a read lock already!
/******************** Critical Points About File Locking *******************/
1. A write lock on any region prevents ANY kind of lock on even a single
byte of that region.
2. A read lock on any region prevents a write lock on even a single byte
of that region.
3. Fcntl with F_GETLK or F_SETLK return -1 on an "error". However, an
error with F_GETLK means that it cannot obtain the desired lock
information. With F_SETLK it means that the desired lock cannot be
obtained.
3. When using fcntl with F_GETLK, the l_type component of the flock
struct is overwritten by any existing lock which would prevent the
lock whose attributes are in the struct flock * third argument.
If nothing will prevent the lock given in this struct, the l_type
component will have the value F_UNLCK.
4. If the value of the l_len component of a struct flock is 0 then the
length of the region to be tested/locked is the rest of the file
starting at the value given in the l_start component.
5. The l_start component's meaning is relative to the l_whence component
of the flock struct. The l_whence component can be SEEK_SET (beginning
of file), SEEK_CUR (current position of file pointer), or SEEK_END
(end of file). Thus, l_start must be zero or positive if l_whence is
SEEK_SET and zero or negative if l_whence is SEEK_END.
6. Read locks do not prevent other read locks on the same region.
7. You must remember to F_UNLCK a region after your need for a read or
write lock has expired.
8. With descriptors, there is no fseek/ftell. There is only lseek which
returns the same value as ftell and whose prototype is:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
Lseek's return value is the offset after the move of the file pointer.
Lseek(fd, 0, SEEK_CUR) is like ftell.
9. If you want to create a lock, do NOT call fcntl with F_GETLK first.
Just try for the lock with F_SETLK and if fcntl returns a negative
value then you couldn't get the lock. F_GETLK is an "info only please"
request.