UNIX环境高级编程:记录上锁(fcntl函数)以及死锁检测

一、记录锁 record locking

功能:当一个进程正在读或修改文件的某个部分时,它可以阻止其它进程修改同一文件区。

字节范围锁 byte-range locking

二、历史

flock函数,可以锁整个文件,不能锁文件中的一部分。

fcntl函数,增加了记录锁的功能。

lockf函数,在fcntl基础上构造了lockf函数,提供一个简化的接口。可以锁文件中任意字节数的区域

三、fcntl 记录锁

函数原型:

int fcntl(int fd, int cmd, struct flock *flockptr);  

/*
cmd = F_GETLK,测试能否建立一把锁
cmd = F_SETLK,设置锁
cmd = F_SETLKW, 阻塞设置一把锁 

*/
//POSIX只定义fock结构中必须有以下的数据成员,具体实现可以增加
struct flock {
      short l_type;    /* 锁的类型: F_RDLCK, F_WRLCK, F_UNLCK */
      short l_whence;  /* 加锁的起始位置:SEEK_SET, SEEK_CUR, SEEK_END */
      off_t l_start;   /* 加锁的起始偏移,相对于l_whence */
      off_t l_len;     /* 上锁的字节数*/
      pid_t l_pid;     /* 已经占用锁的PID(只对F_GETLK 命令有效) */
      /*...*/
};

(1)所希望的锁类型:F_RDLCK(共享读锁)、F_WRLCK(独占性写锁)、F_UNLCK(解锁一个区域)。

(2)要加锁或解锁区域的起始字节偏移量由l_start和l_whence两者决定。

(3)注意:该区域可以在当前文件尾端开始或越过其尾端处开始,但是不能在文件起始位置之前开始。

(4)如若l_len为0,则表示锁的区域从其起点(由l_start和l_whence决定)开始直至最大可能偏移量为止。

(5)为了锁住整个文件,我们设置l_start和l_whence,使锁的起点在文件起始处,并说明长度(l_len)为0。

上面提到了两种类型的锁:共享读锁(F_RDLCK)和独占写锁(F_WRLCK),基本规则是:

多个进程在一个给定的字节上可以有一把共享的读锁,但是在一个给定字节上只能有一个进程独用的一把写锁。进一步而言,如果在一个给定字节上已经有一把或多把读锁,则不能再该字节上再加写锁;如果在一个字节上已经有一把独占性的写锁,则不能再对它加任何读锁。    

不同进程锁请求的读写锁规则:

-------------------                   加读锁         加写锁

无锁                                      允许             允许

一个或多个读锁                    允许             拒绝

一个写锁                              拒绝             拒绝

注意:上面这个规则适用于不同进程提出的锁请求,并不适用于单个进程提出的多个锁请求。单个进程提出多个锁请求的时候,以最后一次锁作为标准,即新锁替换旧锁对于同一文件,如果一直有不同的进程连续的对其添加读锁,则其它欲对其添加阻塞写锁的进程有可能延长等待时间(这样的情况,对于添加写锁的进程会出现饿死情况)。

在读锁时,该描述符必须是读打开;加写锁时,该描述符必须是写打开。

F_GETLK: 判断由flockptr所描述的锁是否会被另外一把锁所排斥(阻塞)。如果存在一把锁,它阻止创建由flockptr所描述的锁,则把该现存锁的信息写到flockptr指向的结构中。如果不存在这种情况,则除了将l_type设置为F_UNLCK之外,flockptr所指向结构中的其他信息保持不变。

F_SETLK : 获取(l_type为F_RDLCK或F_WRLCK)或释放由flockptr指向flock结构所描述的锁,如果无法获取锁时,该函数会立即返回一个EACCESS或EAGAIN错误,而不会阻塞。

F_SETLKW:  F_SETLKW和F_SETLK的区别是,无法设置锁的时候,调用线程会阻塞到该锁能够授权位置。

这里需要注意的是,用F_GETLK测试能否建立一把锁,然后接着用F_SETLK或F_SETLKW企图建立一把锁,由于这两者不是一个原子操作,所以不能保证两次fcntl之间不会有另外一个进程插入并建立一把相关的锁,从而使一开始的测试情况无效。所以一般不希望上锁时阻塞,会直接通过调用F_SETLK,并对返回结果进行测试,以判断是否成功建立所要求的锁。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索文件
, 函数
, 阻塞
, 进程
, 字节
, 文件锁
, fcntl
, 锁记录
, 记录锁
, 读锁
, 一个
, flock命令
, lockf
fcntl函数
,以便于您获取更多的相关知识。

时间: 2024-10-31 03:10:02

UNIX环境高级编程:记录上锁(fcntl函数)以及死锁检测的相关文章

UNIX环境高级编程---标准I/O库

前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压根不是一码事.Unix I/O也叫低级I/O,也叫Unbuffered I/O,是操作系统内核部分,也是系统调用:而C标准I/O函数相对也成Buffered I/O,高级I/O,一般是为了效率考虑对这些系统调用的封装.以前使用getchar()经常为输入完后的回车而出错.那是不理解标准I/O实现时的

UNIX环境高级编程中的apue.h

/************** * *apueerror.h * *************/ #include <apue.h> #include <stdio.h> #include <errno.h> /* for definition of errno */ #include <stdarg.h> /* ISO C variable aruments */ static void err_doit(int, int, const char *, va

unix高级编程-UNIX环境高级编程 times() 疑问

问题描述 UNIX环境高级编程 times() 疑问 例程 int main(int argc, char *argv[]) { clock_t s_clk,e_clk; struct tms s_tms,e_tms; s_clk = times(&s_tms); system("ls /dev"); system("date"); sleep(1); e_clk = times(&e_tms); printf("e_clk %ld - s

ubuntu-最近在学习Unix 环境高级编程,配置环境时遇到了些问题

问题描述 最近在学习Unix 环境高级编程,配置环境时遇到了些问题 最近再看APUE(UNix 环境高级编程)的第三版,照着教程在中配置环境.也就是想要运行书中的源码,则要安装 libbsd-dev包,而每次安装这个包时,都如上报错,请问各位大虾,该怎么解决呢? 解决方案 你好, 类似的问题我也遇到过 ubuntu下apt-get install安装软件, 报"无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系",今天终于找到解决方法了. 一般出现这种情况的原

unix环境高级编程-UNIX环境高级编程源代码对应

问题描述 UNIX环境高级编程源代码对应 今天开始学习UNIX环境高级编程,书中的源代码下载到了,但是发现根本不是按章节来的,找起来是相当的费时间,有哪位大神用过后知道他们的对应关系么,比如1-1对应ls1.c这样,真是万分感激,造福大家啊!

Mac OS X 10.8 中编译APUE(Unix环境高级编程)的源代码过程_C 语言

最近在温习APUE(<unix环境高级编程>),以前都是在linux下搞,现在打算在自己机器弄下,于是google了下,把编译的事情搞定了,修改了一些教程的一些错误,比如下载链接之类的. 1.下载源文件,我这里是第二版,貌似第三版的英文版出来了... 复制代码 代码如下: wget http://www.apuebook.com/src.2e.tar.gz 2.解压 复制代码 代码如下: tar zxf src.2e.tar.gz 3.修改些东西 复制代码 代码如下: cd apue.2e/

UNIX环境高级编程:线程同步之互斥量

互斥量(也称为互斥锁)出自POSIX线程标准,可以用来同步同一进程中的各个线程.当然如果一个互斥量存放在多个进程共享的某个内存区中,那么还可以通过互斥量来进行进程间的同步. 互斥量,从字面上就可以知道是相互排斥的意思,它是最基本的同步工具,用于保护临界区(共享资源),以保证在任何时刻只有一个线程能够访问共享的资源. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 1互斥量初始化和销毁 #include <pthread

UNIX环境高级编程:线程同步之互斥锁、读写锁和条件变量

一.使用互斥锁 1.初始化互斥量 pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥量 int pthread_mutex_init(pthread_mutex_t*mutex,pthread_mutexattr_t*attr);//动态初始化互斥量 int pthread_mutex_destory(pthread_mutex_t*mutex);//撤销互斥量 不能拷贝互斥量变量,但可以拷贝指向互斥量的指针,这样就可以使多个函数

UNIX环境高级编程:线程属性之并发度

并发度控制着用户级线程可以映射的内核线程或进程的数目.如果操作系统的实现在内核级的线程和用户级的线程之间保持一对一的映射,那么改变并发度并不会有什么效果,因为所有的用户级线程都可能被调度到.但是,如果操作系统的实现让用户级线程到内核级线程或进程之间的映射关系是多对一的话,那么在给定时间内增加可运行的用户级线程数,可能会改善性能. pthread_setconcurrency函数可以用于提示系统,表明希望的并发度. #include <pthread.h> int pthread_getconc