File lock:
File lock using fcntl()
NAME
fcntl - manipulate file descriptorSYNOPSIS
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
DESCRIPTION
- fcntl() performs one of the operations described below on the open file descriptor fd. The operation is determined by cmd.
- fcntl() can take an optional third argument. Whether or not this argument is required is determined by cmd. The required argument type is indicated in parentheses after each cmd name (in most cases, the required type is int, and we identify the argument using the name arg), or void is specified if the argument is not required.
struct flock {
...
short l_type; /* Type of lock: F_RDLCK,
F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start:
SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock
(F_GETLK only) */
...
};
- The l_whence, l_start, and l_len fields of this structure specify the range of bytes we wish to lock. Bytes past the end of the file may be locked, but not bytes before the start of the file.
- F_SETLK (struct flock *)
- Acquire a lock (when l_type is F_RDLCK or F_WRLCK) or release a lock (when l_type is F_UNLCK) on the bytes specified by the l_whence, l_start, and l_len fields of lock.
- If a conflicting lock is held by another process, this call returns -1 and sets errno to EACCES or EAGAIN.
- F_SETLKW (struct flock *)
- As for F_SETLK, but if a conflicting lock is held on the file, then wait for that lock to be released. If a signal is caught while waiting, then the call is interrupted and (after the signal handler has returned) returns immediately (with return value -1 and errno set to EINTR;
- Note: currently we are using F_SETLKW
- F_GETLK (struct flock *)
- On input to this call, lock describes a lock we would like to place on the file. If the lock could be placed, fcntl() does not actually place it, but returns F_UNLCK in the l_type field of lock and leaves the other fields of the structure unchanged.
- If one or more incompatible locks would prevent this lock being placed, then fcntl() returns details about one of these locks in the l_type, l_whence, l_start, and l_len fields of lock and sets l_pid to be the PID of the process holding that lock.
RETURN VALUE
On Success return 0, otherwise retun -1 and errno is set appropriately.My Understand:
- Read lock:
- Read lock will be blocked if already this file is locked.
- After unlock it won't reeceive value, but next call it will get
- Write lock:
- Write lock will be blocked if already this file is locked with write lock on another process.
- After unlock, it exeepcted to overwrite the old value, but reality it won't overwrite the value the output file file contain both value, need to handle this if 2 differect process take the write lock.
Program:
/* File lock using fcntl()
* Check : http://velrajcoding.blogspot.in
*/
#include <stdio.h>
#include <unistd.h> // For fcntl
#include <fcntl.h> // For struct flock, F_WRLCK & F_SETLKW
#include <errno.h> // For errno
enum {
FILE_LOCK,
FILE_UNLOCK,
};
int file_lock_and_ulock(int fd, const char *path, int is_lock, char ch)
{
char str[128] = {0};
struct flock lock;
lock.l_type = (is_lock == FILE_LOCK) ? ((ch == 'r') ? F_RDLCK : F_WRLCK) : F_UNLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
lock.l_pid = getpid();
/*
* Read lock: read lock will be blocked if already this file is locked.
* After unlock it won't reeceive value, but next call it will get
* Write lock: Write lock will be blocked if already this file is locked with write lock on another process.
* After unlock, it exeepcted to overwrite the old value, but reality it won't overwrite the value
* the output file file contain both value, need to handle this if 2 differect process take the write lock
*/
if (fcntl(fd, F_SETLKW, &lock) < 0) {
strerror_r(errno, str, sizeof(str));
printf("Error to lock the file errno:%d err des:%s \n", errno, str);
return 0;
}
printf("File %s is %s \n", path, (is_lock == FILE_LOCK) ? "Locked" : "Unlocked");
return 1;
}
int file_read()
{
FILE *fp = NULL;
int ret = 0, value = 0;
unsigned long value_l = 0;
char str[128] = {0};
char str_2[128] = {0};
fp = fopen("test.txt", "r");
if (!fp) {
printf("File open is failed errno:%d ENOENT:<%d>\n", errno, ENOENT);
return 1;
}
ret = file_lock_and_ulock(fileno(fp), "test.txt", FILE_LOCK, 'r');
if (ret == 0) {
printf("Error in locking \n");
return 1;
}
fgets(str, sizeof(str), fp);
fseek(fp, 0, SEEK_SET);
fscanf(fp, "%s %d", str, &value);
file_lock_and_ulock(fileno(fp), "test.txt", FILE_UNLOCK, 'r');
printf("File content on filst line:<%s> & fscan read:%d \n", str, value);
fseek(fp, 0, SEEK_SET);
if (fgets(str, sizeof(str), fp) == NULL) {
printf("Error in retrienve \n");
}
memset(str_2, 0, sizeof(str));
value_l = 0;
if ((ret = sscanf(str, "%s %lu", str_2, &value_l)) != 2) {
printf("Error in sscanf: %d \n", ret);
}
printf("File content using fgets & sscanf line:<%s> & fscan read:%d ret:%d \n", str, value_l, ret);
return 0;
}
int main()
{
FILE *fp = NULL;
int ret = 0, choose = 0;
printf("Option for file operation: \n\t\t 1. Read \n\t\t 2.Write \n Choose your option: ");
scanf("%d", &choose);
switch (choose) {
case 1:
file_read();
break;
case 2:
fp = fopen("test.txt", "w");
ret = file_lock_and_ulock(fileno(fp), "test.txt", FILE_LOCK, 'w');
#if defined (AVOID_OVERRIGHT)
fflush(fp);
fsync(fileno(fp));
#endif
if (ret == 0) {
printf("Error in locking \n");
return 1;
}
//sleep(5);
fprintf(fp, "file_w_lock_b.c 2nd\n");
fflush(fp);
fsync(fileno(fp));
file_lock_and_ulock(fileno(fp), "test.txt", FILE_UNLOCK, 'w');
fclose(fp);
break;
default:
printf("Wrong option \n");
}
return 0;
}
Program 2:
/* File lock using fcntl()
* Check : http://velrajcoding.blogspot.in
*/
#include <stdio.h>
#include <unistd.h> // For fcntl
#include <fcntl.h> // For struct flock, F_WRLCK & F_SETLKW
#include <errno.h> // For errno
enum {
FILE_LOCK,
FILE_UNLOCK,
};
int file_lock_and_ulock(int fd, const char *path, int is_lock)
{
char str[128] = {0};
struct flock lock;
lock.l_type = (is_lock == FILE_LOCK) ? F_WRLCK : F_UNLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
lock.l_pid = getpid();
if (fcntl(fd, F_SETLKW, &lock) < 0) {
strerror_r(errno, str, sizeof(str));
printf("Error to lock the file errno:%d err des:%s \n", errno, str);
return 0;
}
printf("File %s is %s \n", path, (is_lock == FILE_LOCK) ? "Locked" : "Unlocked");
return 1;
}
int file_check_back_slan_n()
{
FILE *fp = NULL;
int temp = 0;
char str[128] = {0};
if (!(fp = fopen("test_2.txt", "w+"))) {
printf("Error in open a file \n");
return 1;
}
fprintf(fp, "velraj \n serte %d", 100);
fflush(fp);
fsync(fileno(fp));
fseek(fp, 0, SEEK_SET);
fscanf(fp, "%d", &temp);
fseek(fp, 0, SEEK_SET);
fgets(str, sizeof(str), fp);
printf("Vel fscanf int:<%d> fgets:<%s> \n", temp, str);
fclose(fp);
return 0;
}
int main()
{
FILE *fp;
char str[128] = {0};
/*
* w Truncate file to zero length or create text file for writing. The stream is positioned at the beginning of the file.
* w+ Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.
*/
if ((fp = fopen("test.txt", "w"))) {
file_lock_and_ulock(fileno(fp), "test.txt", FILE_LOCK);
} else {
strerror_r(errno, str, sizeof(str));
printf("Error to open a file errno:%d err des:%s \n", errno, str);
return 1;
}
fprintf(fp, "file_w_lock.c: 1 This is testing for fprintf...\n");
// fputs("This is testing for fputs...\n", fp);
#if defined (FLUSH_SYNC_AFTER_SLEEP)
printf("Going to sleep and flush flush & sync after sleep");
sleep(10);
#endif
fflush(fp);
fsync(fileno(fp));
#if !defined (FLUSH_SYNC_AFTER_SLEEP)
printf("flush & sync donw now gonig to sleep ");
/* After flush & sync the file */
sleep(10);
#endif
file_lock_and_ulock(fileno(fp), "test.txt", FILE_UNLOCK);
fclose(fp);
return 0;
if ((fp = fopen("test.txt", "w"))) {
file_lock_and_ulock(fileno(fp), "test.txt", FILE_LOCK);
} else {
strerror_r(errno, str, sizeof(str));
printf("Error to open a file errno:%d err des:%s \n", errno, str);
return 1;
}
fflush(fp);
fsync(fileno(fp));
file_lock_and_ulock(fileno(fp), "test.txt", FILE_UNLOCK);
fclose(fp);
file_check_back_slan_n();
return 0;
}
Output:
Lock & lock from first terminal 1st terminal:
abuser@labuser-virtual-machine:~/velrajk/sample$ ./a.out
File test.txt is Locked
File test.txt is Unlocked
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
Not using lock on second file 2nd terminal:
abuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$ cat test.txt
from_2
labuser@labuser-virtual-machine:~/velrajk/sample$ === now antoher progr is still inlocking ======
===: command not found
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$ ==== that is over unlcoked here not used lock ====
====: command not found
labuser@labuser-virtual-machine:~/velrajk/sample$ cat test.txt
This is testing for fprintf...
This is testing for fputs...
labuser@labuser-virtual-machine:~/velrajk/sample$
issue:
------
Lock on process 1 process 2 is got hanged due to process 1 lock, after process 1 release, process 2 write on first still process 1 data also present.
labuser@labuser-virtual-machine:~/velrajk/sample$ cat test.txt
from_2
testing for fprintf...
This is testing for fputs...
labuser@labuser-virtual-machine:~/velrajk/sample$
abuser@labuser-virtual-machine:~/velrajk/sample$ ./a.out
File test.txt is Locked
File test.txt is Unlocked
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
Not using lock on second file 2nd terminal:
abuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$ cat test.txt
from_2
labuser@labuser-virtual-machine:~/velrajk/sample$ === now antoher progr is still inlocking ======
===: command not found
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$
labuser@labuser-virtual-machine:~/velrajk/sample$ ==== that is over unlcoked here not used lock ====
====: command not found
labuser@labuser-virtual-machine:~/velrajk/sample$ cat test.txt
This is testing for fprintf...
This is testing for fputs...
labuser@labuser-virtual-machine:~/velrajk/sample$
issue:
------
Lock on process 1 process 2 is got hanged due to process 1 lock, after process 1 release, process 2 write on first still process 1 data also present.
labuser@labuser-virtual-machine:~/velrajk/sample$ cat test.txt
from_2
testing for fprintf...
This is testing for fputs...
labuser@labuser-virtual-machine:~/velrajk/sample$
No comments:
Post a Comment