一: linux记录锁更恰当的称呼应该是范围锁,它是对文件某个范围的锁定。
关于记录锁的功能就是fcntl提供的第五个功能,具体使用如下:
int fcntl(int fd, int cmd, struct flock *lock);
cmd = F_GETLK, 主要用来检测是否有某个已存在锁会妨碍将新锁授予调用进程,
如果没有这样的锁,lock所指向的flock结构的l_type成员就会被置成F_UNLCK,
否则已存在的锁的信息将会写入lock所指向的flock结构中cmd = F_SETLK,设置锁
cmd = F_SETLK, 设置(l_type为F_RDLCK或F_WRLCK)或释放由lock指向flock结构所描述的锁,
如果无法设置锁时,该函数会立即返回一个EACCESS或EAGAIN错误,而不会阻塞。
cmd = F_SETLKW, F_SETLKW和F_SETLK的区别是,无法设置锁的时候,调用进程程会阻塞到该锁
能够授权位置。
这里需要注意的是,用F_GETLK测试能否建立一把锁,然后接着用F_SETLK或F_SETLKW企图建立一把锁,
由于这两者不是一个原子操作,所以不能保证两次fcntl之间不会有另外一个进程插入并建立一把相关的锁,
从而使一开始的测试情况无效。所以一般不希望上锁时阻塞,会直接通过调用F_SETLK,并对返回结果进行
测试,以判断是否成功建立所要求的锁。
//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 命令有效) */
/*...*/
};
文件记录锁操作规范图:
二: 文件记录锁位于V-node table这个结构中,使用PID作为锁拥有者的标识。这使其拥有如下特点:
1) 记录锁采用(PID, start,end)三元组作为锁标识,一个文件可拥有多个记录锁,同一区域只允许有一个记录锁。
2) 当进程终止(正常/不正常),该进程拥有的所有记录锁都将释放。
3) 同一个进程中,指向同一文件(i-node)的fd都可以操作该文件上的记录锁:如释放、修改等。显式调用F_UNLCK和close(fd)都将释放锁,close将释放整个文件中该进程拥有的所有记录锁。
4) 记录锁不被fork的子进程继承(PID不同)。
5) 记录锁的类型转换、改变锁范围等操作均为原子的。
6) 未设置FD_CLOEXEC时,记录锁将被exec后的进程继承(PID相同)。
7) 记录锁对文件打开mode有要求:加读锁要求fd有读权限;加写锁要求fd有写权限。