Linux 文件锁
函数原型:int fcntl(int fd, int cmd, … /* arg */ );
参数说明:
参数 | 说明 |
---|---|
fd | 文件描述符 |
cmd | 取值(仅说明文件锁相关):F_GETLK, F_SETLK, F_SETLKW 分别表示 获取锁、设置锁和同步设置锁 |
arg | 可变长参数 |
struck flock 数据结构 说明
struct flock {
short l_type; /*F_RDLCK, F_WRLCK, or F_UNLCK */
off_t l_start; /*offset in bytes, relative to l_whence */
short l_whence; /*SEEK_SET, SEEK_CUR, or SEEK_END */
off_t l_len; /*length, in bytes; 0 means lock to EOF */
pid_t l_pid; /*returned with F_GETLK */
};
成员 | 说明 |
---|---|
l_type | 加锁的类型,可为读锁<F_RDLCK>、写锁<F_WRLCK>、解锁<F_UNLCK> |
l_start | 锁相对于l_whence的起始偏移量 |
l_whence | 取值:SEEK_SET、SEELK_CUR、SEEK_END 分别表示 开头、当前、结尾。说明:后两项若不是在文件头部 l_start 可取负数 |
l_len | 要锁定的字节数。若为正数,则表示从l_start开始,到l_start + l_len - 1为止;当取0时,则表示从l_start或l_whence开始,直到文件结尾。 |
l_pid | 获取对目标文件上锁的进场ID,仅在cmd取F_GETLK时生效 |
注意 | 写锁为排他锁,读锁为共享锁 |
实例代码
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define FILE_NAME "./file/lock.txt"
/*********************************************************
* 对fd进行加锁或解锁
*********************************************************/
int file_lock_set(int fd, int type) {
if (fd < 0) {
printf("file_lock_set() - fd(%d) < 0!\n", fd);
return -1;
}
printf("pid = %d into!\n", getpid());
// Query whether the file is locked.
struct flock lock;
memset(&lock, 0, sizeof(struct flock));
fcntl(fd, F_GETLK, &lock);
if (lock.l_type == F_RDLCK) {
printf("fd(%d) has been read locked, locking process ID: %d!\n", fd, lock.l_pid);
}
else if (lock.l_type == F_WRLCK) {
printf("fd(%d) has been write locked, locking process ID: %d!\n", fd, lock.l_pid);
}
lock.l_type = type;
// F_SETLKW:若被加锁文件正在被其他进程加锁中,则阻塞等待。
// F_SETLK:若被加锁文件正在被其他进程加锁中,则直接返回。
if (fcntl(fd, F_SETLKW, &lock) < 0) {
printf("set lock failed!\n");
return -1;
}
switch (lock.l_type)
{
case F_RDLCK:
printf("read lock is set by %d\n", getpid());
break;
case F_WRLCK:
printf("write lock is set by %d\n", getpid());
break;
case F_UNLCK:
printf("read lock is released by %d\n", getpid());
break;
default:
break;
}
printf("pid = %d out!\n", getpid());
return 0;
}
int main(void) {
int fd = open(FILE_NAME, O_RDWR | O_CREAT, 0777);
if (fd < 0) {
printf("file(%s) open failed! reason: %s\n", FILE_NAME, strerror(errno));
exit(-1);
}
// set lock.
file_lock_set(fd, F_WRLCK);
getchar();
// unlock.
file_lock_set(fd, F_UNLCK);
getchar();
return 0;
}