UNIX环境高级编程:记录上锁(fcntl函数)以及死锁检测
副标题[/!--empirenews.page--]
一、记录锁 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,并对返回结果进行测试,以判断是否成功建立所要求的锁。 (编辑:云计算网_泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |