文件锁

为了解决并发对文件IO操作的影响,这样就出现了文件锁,多个进程如果在没有设置文件锁的情况下是可以访问同一个文件的,比如我一个进程已经开始写这个文件了,那么另外一个进程也可以写,那这样不就乱套了吗,文件锁就像是我们家的门锁一样,当一个人进入了家门口以后那么就会对门锁进行一些设置

    用法:man 2 fcntl

    包含头文件:#include <unistd.h>
            #include <fcntl.h>

    函数定义:int fcntl(int fd, int cmd, ... /* arg */ );
       参数: cmd 取值  F_GETLK,   F_SETLK 和 F_SETLKW ,分别表示获取锁、设置锁和同步设置锁.

struct 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:  第一个成员是加锁的类型:读锁(我在读别人也可以读,但是不能写),写锁(我在写,别人不可以写),或是解锁。
l_start和l_whence: 用来指明加锁部分的开始位置:SEEK_SET是相对于起始位置,CUR为当前,END为相对于尾部
l_len: 是加锁的长度:(0”意味着从头锁到尾)
l_pid: 是加锁进程的进程id。

代码中会涉及到的一些函数

getpid();  //获取当前进程

代码案例,可以运行一下试试(注释都在代码里面了)👇

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#define FILE_NAME 	"test.txt"
	   
int flock_set(int fd, int type)
{
	printf("pid=%d into...\n", getpid());
	
	struct flock fflock;
	//清除脏数据
	memset(&fflock,0,sizeof(fflock));
	
	//F_GETLK获取当前文件的锁情况
	fcntl(fd, F_GETLK, &fflock);
	
	//如果存在锁
	if (fflock.l_type != F_UNLCK) {
		if (fflock.l_type == F_RDLCK) {
			printf("flock has been set to read lock by %d\n", flock.l_pid);
		} else if (fflock.l_type == F_WRLCK) {
			printf("flock has been set to write lock by %d\n", flock.l_pid);
		}
	}
	//-------如果有锁执行完上面的if语句进程就会阻塞在这里不会再进行下去-------
	
	fflock.l_type = type;
	fflock.l_whence = SEEK_SET;
	fflock.l_start = 0;
	fflock.l_len = 0;   
	
	// F_SETLKW设置锁
	if (fcntl(fd, F_SETLKW, &fflock) < 0) {
		printf("set lock failed!\n");
		return -1;
	}	
	
	//打印锁的类型
	switch (fflock.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("lock is released by %d\n", getpid());
		break;
	default:
		break;
	}

	printf("pid=%d out.\n", getpid());
	return 0;
}

int main(void)
{
	int fd;

	fd = open(FILE_NAME, O_RDWR|O_CREAT, 0666);
	if (fd < 0) {
		printf("open file %s failed!\n", FILE_NAME);
	}

	//设置读锁
	flock_set(fd, F_RDLCK);
	getchar();  //当键盘输入一个字符继续
	flock_set(fd, F_UNLCK);
	getchar();

	close(fd);
	return 0;
}

结论:写锁是互斥锁,同一时刻只能存在一个写锁,读锁是共享锁,同一时刻可以存在多个读锁

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐