文件操作二(fcntl文件锁)

1、在文件已经共享的情况下如何操作,也就是当多个用户共同使用、操作一个文件的情况,这时,Linux 通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。

2、fcntl()是一个非常通用的函数,它可以对已打开的文件描述符进行各种操作,不仅包括管理文件锁,还包括获得和设置文件描述符和文件描述符标志、文件描述符的复制等很多功能

3、fcntl()函数格式

所需头文件:#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
函数原型:int fcnt1(int fd, int cmd, struct flock *lock)

函数传入值:fd:文件描述符
cmd:

F_DUPFD:复制文件描述符
F_GETFD:获得fd 的close-on-exec 标志,若标志未设置,则文件经过exec()函数之后仍保持打开状态
F_SETFD:设置close-on-exec 标志,该标志由参数arg 的FD_CLOEXEC 位决定
F_GETFL:得到open 设置的标志
F_SETFL:改变open 设置的标志
F_GETLK:根据lock 参数值,决定是否上文件锁
F_SETLK:设置lock 参数值的文件锁
F_SETLKW:这是F_SETLK 的阻塞版本(命令名中的W 表示等待(wait))。在无法获取锁时,会进入睡眠状态;如果可以获取锁或者捕捉到信号则会返回
lock:结构为flock,设置记录锁的具体状态
函数返回值 :0:成功
-1:出错


4、lock 的结构:

struct flock
{
short l_type;
off_t l_start;

short l_whence;
off_t l_len;
pid_t l_pid;
}

lock 结构中每个变量的取值含义

l_type:F_RDLCK:读取锁(共享锁)
F_WRLCK:写入锁(排斥锁)
F_UNLCK:解锁
l_stat: 相对位移量(字节)
l_whence:相对位移量的起点(同lseek的whence)
SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小
SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量
SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小
l_len :加锁区域的长度


5、使用举例:

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>


int lock_set(int fd, int type)
{
struct flock old_lock, lock;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
lock.l_type = type;
lock.l_pid = -1;

/* 判断文件是否可以上锁 */
fcntl(fd, F_GETLK, &lock);
if (lock.l_type != F_UNLCK)
{
/* 判断文件不能上锁的原因 */
if (lock.l_type == F_RDLCK) /* 该文件已有读取锁 */
{
printf("Read lock already set by %d\n", lock.l_pid);
}
else if (lock.l_type == F_WRLCK) /* 该文件已有写入锁 */
{
printf("Write lock already set by %d\n", lock.l_pid);
}
}
/* l_type 可能已被F_GETLK 修改过 */
lock.l_type = type;
/* 根据不同的type 值进行阻塞式上锁或解锁 */
if ((fcntl(fd, F_SETLKW, &lock)) < 0)
{
printf("Lock failed:type = %d\n", lock.l_type);
return 1;
}
switch(lock.l_type)
{
case F_RDLCK:
{
printf("Read lock set by %d\n", getpid());
}
break;
case F_WRLCK:
{
printf("Write lock set by %d\n", getpid());
}
break;
case F_UNLCK:
{
printf("Release lock by %d\n", getpid());
return 1;
}
break;
default:
break;
}
return 0;
}


int main(void)
{
int fd;

/* 首先打开文件 */
fd = open("hello",O_RDWR | O_CREAT, 0644);
if(fd < 0)
{
printf("Open file error\n");
exit(1);
}

/* 给文件上写入锁 */
lock_set(fd, F_WRLCK);

getchar();

/* 给文件解锁 */
lock_set(fd, F_UNLCK);

getchar();
close(fd);

exit(0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值