lockf
system call applies or removes a lock on a specific portion of the file. Also called record locking.
The prototype is below,
int lockf(int fd, int cmd, off_t len);
the fd
is a file descriptor of the file. The cmd
has one of the following options.
F_LOCK
: exclusive lock on the specified section of the file. Other user of the same lock on the file may hang indefnitely. Lock is released when the file descriptor is closed.
F_TLOCK
: try for lock and fails if lock does not acquire.
F_ULOCK
: unlock a particular section of the file.
the len
argument can give the portion of the file the lock needs to be held for. If the len
is set to 0, then the lock extends from beginning to the end of the file.
Below is an example of the lockf
system call. Download here
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
off_t filesize(char *file)
{
struct stat s;
int ret;
ret = stat(file, &s);
if (ret < 0) {
return -1;
}
return s.st_size;
}
int main(int argc, char **argv)
{
pid_t pid;
int fd;
off_t size;
int ret;
if (argc != 2) {
fprintf(stderr, "<%s> filename\n", argv[0]);
return -1;
}
size = filesize(argv[1]);
fd = open(argv[1], O_RDWR);
if (fd < 0) {
return -1;
}
pid = fork();
if (pid == 0) {
ret = lockf(fd, F_LOCK, size);
if (ret < 0) {
printf("cannot lock.. %s\n", strerror(errno));
return -1;
}
printf("lock acquired.. now set to sleep\n");
sleep(4);
printf("unlock..\n");
ret = lockf(fd, F_ULOCK, size);
} else {
sleep(1);
ret = lockf(fd, F_LOCK, size);
if (ret < 0) {
printf("cannto loock.. %s\n", strerror(errno));
return -1;
}
printf("lock acquired by parent..\n");
lockf(fd, F_ULOCK, size);
}
return 0;
}
sometimes, the usual case of the lockf
system call is to use it as a lock for creating the pid file. Pid files are usually created by the deamons to advertise that they have started.
Below is one example of such class. Download here
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
class pidFile {
public:
pidFile() { }
~pidFile() { }
int setPidFile(std::string fileName)
{
int ret;
fd_ = open(fileName.c_str(), O_RDWR);
if (fd_ < 0) {
return -1;
}
ret = lockf(fd_, F_TLOCK, 0);
if (ret< 0) {
return -1;
}
return 0;
}
int removePidFile()
{
lockf(fd_, F_ULOCK, 0);
close(fd_);
return 0;
}
private:
int fd_;
};
int main(int argc, char **argv)
{
pidFile p;
int ret;
if (argc != 2) {
std::cerr << argv[0] << " filename" << std::endl;
return -1;
}
ret = p.setPidFile(std::string(argv[1]));
if (ret < 0) {
std::cerr << "failed to acquire lock " << std::endl;
return -1;
}
std::cout << "lock acquired successfully" << std::endl;
// run another process and test locking..
while (1);
return 0;
}