Chinaunix首页 | 论坛 | 博客
  • 博客访问: 144179
  • 博文数量: 69
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 595
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-16 00:00
个人简介

宁可逆流而上与众不同,也不顺风顺水随波逐流

文章分类

全部博文(69)

文章存档

2020年(1)

2018年(9)

2017年(43)

2016年(16)

我的朋友

分类: C/C++

2017-03-19 22:21:43

情景假设:假如多个进程同时编辑一个文件,则文件的内容由最后一个编辑的进程决定。所以为了确保某一时刻只有单个进程写一个文件,记录锁由此而生。
记录锁功能:当某个进程正在读或修改文件的某个部分时,它可以阻止其它进程修改同一文件区,//它锁定的只是文件的一个区域或整个文件
各种记录锁形式早期的伯克利版本只支持flock函数,SVR3构造了lockf函数,POSIX标准的基础是fcntl,SUS在其XSI扩展中包括了lockf。这几种形式linux全部支持,另外linux也支持建议性锁和强制性锁。下文只介绍fcntl记录锁和强制性锁和建议性锁的区别
  1. #include<fcntl.h>
  2. int fcntl(int filedes,int cmd,/*struct flock *flockptr */)


  1. struct flock{
  2.     short l_type; /*F_RDLCK,F_WRLCK,F_UNLCK*/
  3.     off_t l_start; /*offset in bytes,relative to l_whence*/
  4.     short l_whence; /*SEEK_SET,SEEK_CUR,SEEK_END*/
  5.     off_t l_len; /*length in bytes;0 means lock to EOF*/
  6.     pid_t l_pid; /*returned with F_GETLK*/
  7. };
加读锁时,描述符必须是读打开,加写锁时必须是写打开
cmd的三种值
    F_GETLK:若文件存在一把锁与flockptr中的锁冲突,则把文件的锁信息存在flockptr中,否则flockptr中的l_type被设为F_UNLCK,其它信息不变。
    F_SETLK:按flockptr中的信息为文件设置锁,兼容性规则就是读锁可共存,写锁必须唯一。若不符合兼容性规则,fcntl立即出错返回,errno设为EACCES或EAGAIN,把l_type设为F_UNLCK可清除文件的锁。
    F_SETLKW:上一个的阻塞版本,不符合兼容性规则就阻塞直到符合时被唤醒。

锁的隐含继承和释放
    锁与进程和文件有关:1、当一个进程终止时,他所建立的锁全部释放。2、任何时候关闭一个描述符时,则该进程通过这一描述符可以引用的文件上的任何一把锁都被释放,就算对描述符使用dup函数也是如此(在同一个进程的情况锁只和具体的文件有关,而不是和描述符有关,只要你关闭的是这个文件,那么此文件上的所有锁都失效,与你关闭时使用的哪个文件描述符无关)
    fork产生的子进程不继承父进程设置的锁
    exec后,新程序可以继承原执行程序的锁,如果文件有close_on_exec标志,那么exec后文件会关闭,锁自然也不在了。
建议性锁和强制性锁
    强制性锁使内核对每个open,write,read系统调用都进行检查,检查调用进程对正在访问的文件是否违背了某一把锁的作用,若违背了,则禁止调用(要么阻塞直到允许调用,要么错误返回)。而建议性锁只是提出建议,所以并没有什么卵用。但是Linux默认就是建议性锁。建议性锁网上有个很好的例子:红灯提示人们该停车了,但是你也完全可以不停,取决于你,这红灯就是建议性锁。

参考自《UNIX环境高级编程》,书上对记录锁的使用进行了封装,但是我个人觉得不封装也没有多复杂,封装了虽然调用简单,但是屏蔽了一些细节,过于抽象反而觉得不太好。当然了,萝卜青菜、各有所爱嘛

注意点:
    一个进程永远不可能知道它自己加在此文件上的锁。当一个进程先加一个锁后,无论这个进程本身把l_type的类型设置成什么,在调用fcntl获取锁状态时得到的永远是F_UNLCK状态。注意是在同一进程中。为方便理解,你可以把它想象成在你使用F_GETLK参数调用fcntl时其实是先看看将文件锁状态设置成调用参数里的状态是否可行,若可行则返回F_UNLCK,否则相反。而一个进程设置他设置的文件是永远可行的,所以返回的也就永远是F_UNLCK状态
阅读(644) | 评论(0) | 转发(0) |
0

上一篇:非阻塞I/O

下一篇:创建守护进程

给主人留下些什么吧!~~