关于fcntl函数的深入讨论
简介:fcntl函数的主要功能主要有以下几点:
1.复制文件描述符
2.记录锁
3.获得/设置文件描述符标志
4.获得/设置文件状态标志
5.获得异步I/O的所有权
在本篇文章中,我主要分析fcntl的记录锁的功能.
1.什么是记录锁?
官方一点来说,记录锁就是当一个进程正在读或修改文件A部分的时候,可以阻止其他进程去修改这个文件的A部分.通常一点来说,记录锁也是一种锁,但是它锁的是文件中的部分区域.(在APUE上,我觉得他给记录锁起的另外一个名字--"字节范围锁"挺好的).
2.操作记录锁的函数
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; // 锁的区域长度,当为0的时候,表示锁住整个文件(不管文件是否会变长)
pid_t l_pid; // 持有现存的锁的进程的pid(只有在F_GETLK)
};
int fcntl(int fd, int cmd, struct flock *lock);
//fd 这里就是文件描述符
//cmd 这里是对记录锁的具体操作,它有三个值可供选择:a.F_GETLK b.F_SETLK c.F_SETLKW,稍后会对这三个命令进行一些说明
//lock 记录锁的属性
ok,来分别解释一下,cmd的三个值
a.F_GETLK
该值表示,获得是否有与即将加的B锁的类型互斥的A锁存在.如果存在的话,就将A锁的信息放到B锁得结构中,如果不存在的话,就将B锁结构体中的,l_type字段变成F_UNLCK,其他不变.
b.F_SETLK
该值表示,设置lock,如果在不同进程中已经有与lock互斥的锁存在的话,那么fcntl函数立即返回,并将errno变为EAGAIN(或者是EACESS)
c.F_SETLKW
该值是F_SETLK的阻塞版本,也就是说有互斥的锁存在的话,fcntl函数就会堵塞,在锁的可以加上之后或者由信号中断,该进程才会被唤醒
3.例子
void lock_file(int choice)<span style="font-size:14px;">//这个函数在下面会多次用到</span>
{
struct flock read_flock;
if(choice == 1)
{
read_flock.l_type = F_RDLCK;
}
else
{
read_flock.l_type = F_WRLCK;
}
read_flock.l_start = 0; //偏移量
read_flock.l_whence = SEEK_SET;
read_flock.l_len = 0; //为0的时候,可以锁住整个文件
fcntl(getpid(),F_SETLK,&read_flock);
}