#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include"lock.c"
/* *
* 文件锁fcntl()函数
* fcntl()不仅可以施加建议性锁,还可以施加强制锁(内核)
* fcntl()还能对文件的某一记录上锁,也就是记录锁
* 记录锁又可分为读取锁和写入锁
* int fcntl(int fd,int cmd,...) [第三个参数为结构指针]
* 若成功则返回0,失败返回-1
* */
int main(void)
{
int fd;
fd = open("text.txt",O_RDWR | O_CREAT,0644);
if(fd < 0)
{
printf("Open File error\n");
exit(1);
}
lock_set(fd,F_RDLCK);
//调用函数lock_set(),给文件上读取锁
getchar();
//由用户键入一任意键使程序继续运行
lock_set(fd,F_UNLCK);
//调用函数lock_set(),给文件解锁
getchar();
close(fd);
exit(0);
}
调用函数:
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);
//判断文件是否可以上锁,若成功,则反回lock.l_type = F_GETLK;若失败,返回原值
if(lock.l_type != F_UNLCK)
//判断当前的lock.l_type 的类型,F_UNLCK、F_WRLCK、F_RDLCK
{
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);
}
}
lock.l_type = type;
//lock.l_type可能已被F_GETLK修改过,需要重新赋值
if((fcntl(fd,F_SETLKW,&lock)) < 0)
//根据cmd来进行上锁或解锁
{
printf("Lock error:type = %d\n",lock.l_type);
return 1;
}
switch(lock.l_type)
{
case F_RDLCK:
{
printf("Read lock already set by %d\n",getpid());
}
break;
case F_WRLCK:
{
printf("Write lock already set by %d\n",getpid());
}
break;
case F_UNLCK:
{
printf("Release lock by %d\n",getpid());
return 1;
}
break;
default:
break;
}
return 0;
}
/* *
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))。在无法获取锁时,会进入睡眠状态;如果可以获取锁或者捕捉到信号则会返回
struct flock
{
short l_type;
off_t l_start;
short l_whence;
off_t l_len;
pid_t l_pid
}
l_type
F_RDLCK:读取锁(共享锁)
F_WRLCK:写入锁(排斥锁)
F_UNLCK:解锁
l_stat :相对位移量(字节)
l_whence:相对位移量的起点(同lseek的whence)
SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小
SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量
SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小
l_len:加锁区域的长度
* */