当前位置: 首页 > 工具软件 > Flock > 使用案例 >

flock给文件加锁

翟黎明
2023-12-01

函数声明

/*
 * 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
 类似资料: