Linux IO系统编程系列课程笔记之文件锁

概念

  1. 目标
    解决多个进程对同一个文件操作产生的竞争状态
  2. 解决方案:
    文件锁
    按功能分可分为:读锁和写锁
  • 读锁
    文件描述符必须以读的方式打开。
    一个进程对这个文件设置读锁,其他进程也可以设置读锁,在不改变文件内容的情况下各个进程不存在竞争状态

  • 写锁
    文件描述符必须写打开。
    一个进程对这个文件设置了写锁,其他进程不能在这个文件上设置读锁和写锁,直至给文件设置写锁的进程解锁,其他进程才可以进行设置锁

    按类型分可分为:建议锁和强制锁

  • 强制锁
    SVR4的一种锁机制。如果文件设置了调整组ID位,当对这个文件调用fcntl函数设置锁时,则称这种情况下的锁为强制锁。在强制锁的机制下,内核会拒绝一切与锁有冲突的文件操作

  • 建议锁
    建议锁由fcntl函数提供所有的POSIX兼容的系统都支持建议锁。正如其名这种锁是建议性的,不管文件是否上了锁,程序都可以忽略直接进行读写数据;是由用户进程自愿执行的,进程可以设置锁,但只有当协同工作的进程自愿地查看锁时才对文件有保护作用,内核并不对建议锁内部的强制保护或者检查。在建议锁的机制下文件的互斥访问都是通过fcntl函数来进行置锁,而read()和write()函数并不检查所读写的文件部分是否存在锁

  1. 实现
    fcntl函数
    在这里插入图片描述
    注:F_SETLKW为F_SETLK的一个阻塞版本;即前面两种为非阻塞版本,后面那种为阻塞版本。

    flock结构体
    在这里插入图片描述
    注:
    在这里插入图片描述

实践代码

主函数:

 #include "io.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc, char *argv[])
{
	if(argc<4)
	{
		printf("usage :%s content file locktype\n",argv[0]);
		exit(1);
	}
		ssize_t size=strlen(argv[1])*sizeof(char);
		int fd=open(argv[2],O_WRONLY | O_CREAT, 0777);
		if(fd <0)
		{
			perror("open file error");
			exit(1);
		}
		sleep(5);
		if(!strcmp("lock",argv[3]))
		{
			WRITE_LCKW(fd,0,SEEK_SET,0);
		}
		printf("lock success!\n");
	 	printf("lock pid: %d\n",getpid());
//以单个字符写入文件
		char *p=argv[1];
        int i;
		for(int i=0;i<size;i++)
		{
			if(write(fd,p+i,1)!=1)
			{
				perror("write error");
				exit(1);
			}
		printf(" successfully write one character\n");
		sleep(1);
		}

//解锁
   if(!strcmp("lock",argv[3]))
   {
     UNLOCK(fd,0,SEEK_SET,0);//解锁参数和 上锁参数一致
   }	   
   printf("unlock successfully\n");
   printf("unlock pid:%d\n",getpid());
   close(fd);
return 0;
}

注: WRITE_LCKW是我定义的一个宏:

 //io.h文件内容:
 extern int lock_reg(int fd, int cmd, short type,long int  offset,short whence,long int  length);
//宏定义:
//阻塞读锁
#define READ_LOCKW(fd, offset,whence,length) lock_reg(fd, F_SETLKW, F_RDLCK,offset , whence,length)
//非阻塞读锁
#define READ_LOCK(fd, offset,whence,length) lock_reg(fd, F_SETLK, F_RDLCK,offset , whence,length)
 //阻塞写锁
#define WRITE_LCKW(fd, offset, whence,length) lock_reg(fd, F_SETLKW, F_WRLCK,offset, whence,length)
//非阻塞写锁
#define WRITE_LCK(fd, offset, whence,length) lock_reg(fd, F_SETLK, F_WRLCK,offset, whence,length)
//解锁
#define UNLOCK(fd, offset, whence, length) lock_reg(fd, F_SETLK, F_UNLCK,offset,whence, length)
//io.c的文件内容
 int lock_reg(int fd, int cmd, short type,off_t offset,short whence,off_t length)
{
	struct flock  flock;
	flock.l_type=type;
	flock.l_start=offset;
	flock.l_whence=whence;
	flock.l_len=length;
	//flock.l_pid=getpid();获得加锁的进程编号
	if(fcntl(fd, cmd,&flock)<0)
	{
		perror("fcntl error");
		return 0;//数字随便
	}
	return 1;//数字随便
}

结果:

执行:用脚本文件来自动开两个进程进行验证
在这里插入图片描述
结果
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值