函数声明
/*
* flock - apply or remove an advisory lock on an open file
* @fd:被打开文件的文件描述符
* @operation:操作标志位
* LOCK_SH 共享锁,某一时刻多个进程可以同时持有文件锁
* LOCK_EX 独占锁,某一时刻只能有一个进程持有锁
* LOCK_UN 移除当前进程持有的文件锁
* LOCK_NB,当被锁定时,进程获取文件锁时不阻塞
*
* 成功获取文件锁时返回0,出现错误返回-1,还有可能返回以下错误
* EBADF fd is not an open file descriptor.
* EINTR While waiting to acquire a lock, the call was interrupted by delivery of a signal caught by a handler;
* EINVAL operation is invalid.
* ENOLCK The kernel ran out of memory for allocating lock records.
* he file is locked and the LOCK_NB flag was selected.
*/
int flock(int fd, int operation);
// 如果使用fopen打开的文件,可以用下面这个函数获取FILE指针对应的文件描述符
int fileno(FILE *stream);
测试程序
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#define TEST_FILE_PATH "./test.txt"
#define DATA_LEN 20
int main(void)
{
int fd = 0;
int ret = -1;
char buff[DATA_LEN] = {0};
fd = open(TEST_FILE_PATH, O_RDONLY);
if (fd == 0) {
printf("Open file %s failed\n", TEST_FILE_PATH);
return -1;
}
ret = flock(fd, LOCK_EX);
if (ret < 0) {
perror("Error: ");
close(fd);
return -1;
}
ret = read(fd, buff, sizeof(buff));
if (ret < 0) {
perror("Error: ");
close(fd);
return -1;
} else {
printf("Read data -> %s\n", buff);
}
flock(fd, LOCK_UN);
return 0;
}
// gcc flock.c -o flock
当没有其他进程持有文件锁时,可以获取到文件锁,并读取文件数据。
$ ./flock
Read data -> this is test file
把上面程序改一改,让某个进程一直持有文件锁。
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#define TEST_FILE_PATH "./test.txt"
#define DATA_LEN 20
int main(void)
{
int fd = 0;
int ret = -1;
char buff[DATA_LEN] = {0};
fd = open(TEST_FILE_PATH, O_RDONLY);
if (fd == 0) {
printf("Open file %s failed\n", TEST_FILE_PATH);
return -1;
}
ret = flock(fd, LOCK_EX);
if (ret < 0) {
perror("Error: ");
close(fd);
return -1;
}
printf("Get flock!\n");
while(1);
flock(fd, LOCK_UN);
return 0;
}
// gcc hold_flock.c -o hold_flock
当A进程一直持有文件锁时,B进程无法获取到文件锁,如果标志位为LOCK_EX
,则B进程一直处于阻塞状态,如果想要让B进程处于非阻塞状态需要添加标志为LOCK_NB
。
# A进程获取锁并一直持有
$ ./hold_flock
Get flock!
# B进程处于阻塞状态,一直在等待获取到文件锁
$ ./flock
# 添加标志位LOCK_NB
$ ./flock
Error: : Resource temporarily unavailable