|
|
There are several ways for us to set a lock on a file. In part, these methods depend on how the lock interacts with the rest of the program. There are also questions of performance as well as portability. Two methods will be given here, one using the fcntl system call, the other using the /usr/group standards compatible lockf library function call.
Locking an entire file is just a special case of record locking. For both these methods the concept and the effect of the lock are the same. The file is locked starting at a byte offset of zero (0) until the end of the maximum file size. This point extends beyond any real end of the file so that no lock can be placed on this file beyond this point. To do this the value of the size of the lock is set to zero. The code using the fcntl system call is as follows:
#include <fcntl.h> #define MAX_TRY 10 int try; struct flock lck;try = 0;
/* set up the record locking structure, the address of which * is passed to the fcntl system call. */ lck.l_type = F_WRLCK; /* setting a write lock */ lck.l_whence = 0; /* offset l_start from beginning of file */ lck.l_start = 0L; lck.l_len = 0L; /* until the end of the file address space */
/* Attempt locking MAX_TRY times before giving up. */ while (fcntl(fd, F_SETLK, &lck) < 0) { if (errno == EAGAIN || errno == EACCES) { /* there might be other errors cases in which * you might try again. */ if (++try < MAX_TRY) { (void) sleep(2); continue; } (void) fprintf(stderr,"File busy try again later!\n"); return; } perror("fcntl"); exit(2); } . . .
This portion of code tries to lock a file. This is attempted several times until one of the following things happens:
To perform the same task using the lockf function, the code is as follows:
#include <unistd.h> #define MAX_TRY 10 int try; try = 0;/* make sure the file pointer * is at the beginning of the file. */ lseek(fd, 0L, 0); /* Attempt locking MAX_TRY times before giving up. */ while (lockf(fd, F_TLOCK, 0L) < 0) { if (errno == EAGAIN || errno == EACCES) { /* there might be other errors cases in which * you might try again. */ if (++try < MAX_TRY) { sleep(2); continue; } (void) fprintf(stderr,"File busy try again later!\n"); return; } perror("lockf"); exit(2); } . . .
It should be noted that the lockf example appears to be simpler, but the fcntl example exhibits additional flexibility. Using the fcntl method, it is possible to set the type and start of the lock request simply by setting a few structure variables. lockf merely sets write (exclusive) locks; an additional system call, lseek, is required to specify the start of the lock.