通过之前的open()/close()/read()/write()/lseek()函数已经可以实现文件的打开、关闭、读写等基本操作,但是这些基本操作是不够的。

对于文件的操作而言,“锁定”操作是对文件(尤其是对共享文件)的一种高级的文件操作。当某进程在更新文件内数据时,期望某种机制能防止多个进程同时更新文件从而导致数据丢失,或者防止文件内容在未更新完毕时被读取并引发后续问题,这种机制就是“文件锁”。

对于共享文件而言,不同的进程对同一个文件进行同时读写操作将极有可能出现读写错误、数据乱码等情况。在Linux系统中,通常采用“文件锁”的方式,当某个进程独占资源的时候,该资源被锁定,其他进程无法访问,这样就解决了共享资源的竞争问题。

文件锁包括建议性锁(又名“协同锁”)和强制性锁两种。建议性锁要求每个相关进程访问文件的时候检查是否已经有锁存在并尊重当前的锁。一般情况下不建议使用建议性锁,因为无法保证每个进程都能自动检测是否有锁,Linux内核与系统总体上都坚持不使用建议性锁。而强制性锁是由内核指定的锁,当一个文件被加强制性锁的过程中,直至该所被释放之前,内核将阻止其他任何进程对该文件进行读或写操作,每次读或写操作都得检测锁是否存在。当然,采用强制性锁对内核的性能影响较大,每次内核在操作文件的时候都需要检查是否有强制性锁。

在Linux内核提供的系统调用中,实现文件上锁的函数有lockf()fcntl(),其中lockf()用于对文件加建议性锁,这里不再讲解。fcntl()函数既可以加建议性锁,也可以加强制性锁。同时,fcntl()还能对文件某部分上记录锁。所谓记录锁,其实就是字节范围锁,它能锁定文件内某个特定区域,当然也可锁定整个文件。

记录锁又分为读锁和写锁两种。其中读锁又称为共享锁,它用来防止进程读取的文件记录被更改。记录内可设置多个读锁,但当有一个读锁存在的时候就不能在该记录区域设置写锁。写锁又称为排斥锁,在任何时刻只能有一个程序对文件的记录加写锁,它用来保证文件记录被某一进程更新数据的时候不被其他进程干扰,确保文件数据的正确性,同时也避免其他进程“弄脏”数据。文件记录一旦被设置写锁,就不能再设置任何锁直至该写锁解锁。

函数fcntl()
需要头文件:#include< unistd.h>
#include< sys/types.h>
#include< fcntl.h>
函数原型:int fcntl(int fd,int cmd,struct flock *lock_set);
函数参数:fd:文件描述符
cmd:检测锁或设置锁
lock_set:结构体类型指针,结构体struct flock需要事先设置,与第二个参数连用
函数返回值:成功:0
失败:-1
第二个参数cmd表示该操作对文件的命令,若该命令是对文件检测锁或施加锁,则需要第三个参数:
F_GETLK:检测文件锁状态,检测结果存放在第三个参数的结构体的l_type内
F_SETLK:对文件进行锁操作,锁操作类型存放在第三个参数的结构体的l_type内
F_SETLKW:同F_SETLK,不过使用该参数时若不能对文件进行锁操作则会阻塞直至可以进行锁操作为止(W即wait,等待)
(更多参数请参阅fcntl()函数的使用手册)
第三个参数是对文件施加锁操作的相关参数设置的结构体
注意:必须定义struct flock类型结构体并初始化结构体内的数据,然后使用地址传递的方式传递参数,不允许直接定义struct flock* 类型指针直接传参

关于struct flock的成员如下:

struct flock
{short l_type;short l_whence;off_t l_start;off_t l_len;pid_t l_pid;
}

结构体成员说明:
l_type:有三个参数
F_RDLCK:读锁(共享锁)
F_WRLCK:写锁(排斥锁)
F_UNLCK:无锁/解锁
l_whence:相对于偏移量的起点,参数等同于fseek()与lseek()中的whence参数
SEEK_SET:位置为文件开头位置
SEEK_CUR:位置为文件当前读写位置
SEEK_END:位置为文件结尾位置
l_start:加锁区域在文件中的相对位移量,与l_whence的值共同决定加锁区域的起始位置
l_len:加锁区域的长度,若为0则表示直至文件结尾EOF
l_pid:具有阻塞当前进程的锁,其持有的进程号会存放在l_pid中,仅由F_GETLK返回

示例:使用fcntl()函数对文件进行锁操作。
首先初始化结构体flock中的值,然后调用两次fcntl()函数。第一次参数设定为F_GETLK判断是否可以执行flock内所描述的锁操作;第二次参数设定为F_SETLK或F_SETLKW对该文件进行锁操作。
注意:需要至少两个终端运行该程序才能看到效果

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
int lock_set(int fd,int type)
{struct flock lock;lock.l_whence = SEEK_SET;lock.l_start = 0;lock.l_len = 0;//三个参数设置锁的范围是全文件lock.l_type = type;//type的参数由主调函数传参而来lock.l_pid = -1;//第一次操作,判断该文件是否可以上锁fcntl(fd,F_GETLK,&lock);if(lock.l_type!=F_UNLCK)//如果l_type得到的返回值不是F_UNLCK则证明不能加锁,需判断原因{if(lock.l_type==F_RDLCK){printf("This is a ReadLock set by %d\n",lock.l_pid);}else if(lock.l_type==F_WRLCK){printf("This is a WriteLock set by %d\n",lock.l_pid);}}//第二次操作,对文件进行相应锁操作lock.l_type = type;if((fcntl(fd,F_SETLKW,&lock))<0){printf("Lock Failed:type = %d\n",lock.l_type);return -1;}switch(lock.l_type){case F_RDLCK:printf("ReadLock set by %d\n",getpid());break;case F_WRLCK:printf("WriteLock set by %d\n",getpid());break;case F_UNLCK:printf("ReleaseLock by %d\n",getpid());return 1;break;}return 0;
}
int main(int argc, const char *argv[])
{int fd;if((fd=open("hello.txt",O_RDWR))<0){perror("fail to open hello.txt");exit(0);}printf("This pid_no is %d\n",getpid());//给文件上锁lock_set(fd,F_WRLCK);printf("Press ENTER to continue...\n");getchar();//给文件解锁lock_set(fd,F_UNLCK);close(fd);return 0;
}

Linux文件---文件锁相关推荐

  1. Linux文件中的stat结构

    结构体stat Linux文件系统以块为单位存储信息,为了找到某一个文件所在的存储空间的位置用一个数据结构来对每个文件进行索引,而stat显示的就是该结构体信息,下面我们可以来看下这个结构体. str ...

  2. linux文件权限详解

    linux文件权限详解 一.文件和目录权限概述 在linux中的每一个文件或目录都包含有访问权限,这些访问权限决定了谁能访问和如何访问这些文件和目录. 通过设定权限可以从以下三种访问方式限制访问权限: ...

  3. Linux中的文件寻址,Linux文件寻址算法:逻辑地址到物理地址的转换

    题目描述: 编写一个函数实现Linux文件寻址的算法,即读取文件当前位置到物理存储位置的转换函数,需要给出运行的测试数据,可以假设和模拟需要的数据和结构.即编写一个函数unsigned long lt ...

  4. linux文件时间属性的详解

    linux文件会有三个时间. stat file 可以查看三个时间 如: Access: 2019-01-26 19:11:10.482357682 +0800 Modify: 2019-01-26 ...

  5. 查看linux文件的权限:ls -l 文件名称

    查看linux文件的权限:ls -l 文件名称 查看linux文件夹的权限:ls -ld 文件夹名称(所在目录) 修改文件及文件夹权限: sudo chmod -(代表类型)×××(所有者)×××(组 ...

  6. [转]Linux文件搜索

    简述Linux文件搜索 1 .关于搜索: 在Linux文件系统中,搜索概念有两种,一种是搜索文件名,另一种是在一个文件中搜索指定的内容:这两种搜索,我们都简要的介绍一下,但不一定极为专业.想到哪写到哪 ...

  7. linux文件的权限模式,Linux文件权限和访问模式

    为了更加安全的存储文件,Linux为不同的文件赋予了不同的权限,每个文件都拥有下面三种权限: 所有者权限:文件所有者能够进行的操作 组权限:文件所属用户组能够进行的操作 外部权限(其他权限):其他用户 ...

  8. linux学习随笔——linux文件权限管理和网络配置

    一.linux文件权限管理 查看某个文件的权限命令:ls -l linux文件权限有4种:读(r).写(w).执行(x)和无权限(-) 一般用10个字符表示其权限,按照(1-3-3-3)来分组划分 1 ...

  9. [转帖]linux文件描述符文件/etc/security/limits.conf

    linux文件描述符文件/etc/security/limits.conf https://blog.csdn.net/fanren224/article/details/79971359 需要多学习 ...

最新文章

  1. 做了一个系列的Android开发教程列表
  2. 基于JSP实现OA办公系统
  3. 模块化编程AMDCommonJS
  4. volatile修饰变量
  5. c语言回文字符串原理,回文串(c语言)注意字符串比较和字符比较的区别
  6. vtk删除一个actor_如何构建一个基于actor的简单区块链
  7. 17 WM配置-策略-激活存储区搜索(Storage Section Search)
  8. java面试题_208道Java面试题,
  9. oracle的exp程序,数据库expimp迁移的整个过程,及注意事项
  10. Redis单台的安装部署及集群部署
  11. java处理excel的读写
  12. HTML5活动目的,完美活动策划方案指南(教你做有意思的H5方案)
  13. 求生之路4的联机方法和秘籍
  14. 带农历的html日历插件,魔镜日历插件-可生成带农历的日历月历年历-CDR插件
  15. 含有使字的诗句_带有使字的诗-带有使字的诗句
  16. 【大数据分析毕设之基于python爬虫的旅游大数据分析可视化系统】
  17. 小米3(联通/电信)解BL锁教程 申请BootLoader解锁教程
  18. python气象绘图速成_Python气象绘图Day-By-Day
  19. 【微信小程序】点击复制功能的实现(常用于分享码,兑换码)
  20. 解决 Python bug:make_moons() takes from 0 to 1 positional arguments but 3 were given

热门文章

  1. jQuery的事件冒泡,事件对象和图片跟随
  2. GAMES101复习:光线追踪(Ray Tracing)
  3. 深夜街头被偷拍的扎心瞬间:成年人的体面,都是易碎品
  4. 阿里云服务器 云监控 API 调用示例
  5. h5 nan_易企秀资深前端架构师袁飞:移动H5开发如何避坑
  6. Metso定位器的参数及调试步骤
  7. 星星之火-28:什么是CDMA的远近效应与功率控制?
  8. 计算机网络的简单实验
  9. python无法打开微信登录_如何让你的微信登录界面地球转起来(利用python实现)...
  10. CCRC信息安全服务资质。