fcntl文件锁操作

文件锁经常应用于两个方面:
1.一是锁定文件中的临界数据,比如并发投票时文件记录的投票数2.二是利用具有互斥性质的写锁,实现进程的并发控制。

/*使用文件锁*/<F5>
#include <fcntl.h>

fcntl(int fildes,int cmd,struct flock* arg);
cmd:F_GETLK,F_SETLK,F_SETLKW
获得或设置记录锁。
如果出错,所有命令都返回-1.

在fcntl.h中的锁信息结构
struct flock
{
    /*锁类型*/
    short l_type;//取值为读锁F_RDLCK,写锁F_WRLCK,释放锁F_UNLCK
    /*锁区域的开始位置*/
    short l_whence;//锁区域开始地址的相对位置,取值为SEEK_SET,SEEK_CUR,SEEK_END
    long l_start;//锁区域万开始地址的偏移量,与l_whence共同确定锁区域的绝对开始位置
    /*锁区域的长度*/
    long l_len;//如果为0,则表示锁至文件末
    /*拥有锁的进程的ID号*/
    short l_pid;
}

F_GETLK: 在申请文件锁之前查找锁信息。
当制定区域中存在多个文件锁时,fcntl只返回其一。
调用成功返回任意非负整数,否则返回-1
用户提交申请的锁类型,函数返回与该锁类型不兼容的锁信息。
如果提交读锁,fcntl只返回该区域内的写锁而忽略读写。因为读锁只与写锁不兼容
如果提交写锁,fcntl只返回区域内的全部锁信息。因为写锁与其他任意锁都不兼容
如果区域内无文件锁时,arg指向的flock结构的成员l_type将被置为F_UNLCK。

所以使用写锁来测试判断文件某块区域内是否已经有现存锁。

F_SETLK:设置读锁,写锁,清除锁。
调用失败返回-1,否则返回其他值。
如果本进程在该区域已经申请锁,则新锁取代该区域的老锁
如果该区域已被其他进程加锁,而且与新锁不兼容,则函数会调用失败。

F_SETLKW:
为F_SETLK的阻塞版,设置读锁,写锁,清除锁,但是会此阻塞版会导致进程阻塞直到请求被完成为止。而F_SETLK会在执行失败时会立刻返回。

使用流程:将测试锁,申请锁,释放锁三块儿封装成三个函数调用,,封装为库函数会使得以后的使用简单方便许多。
测试锁:查询文件描述符对应文件的锁信息,判断是否有不兼容已存锁

1.封装测试锁函数:void SeekLock(int fd,int start,int len);
功能:判断文件描述符对应的文件从文件开始处偏移start处开始的len字节区域中的锁信息:
void SeekLock(int fd,int start,int len)
{
    struct flock arg;
    arg.l_type = F_WRLCK;
    arg.l_whence = SEEK_SET;
    arg.l_start = start;
    arg.l_len = len;
    if(fcntl(fd,F_GETLK,&arg) == -1)
    {
        fprintf(stderr,"See Lock failed.\n");
    }
    else if(arg.l_type == F_UNLCK)
    {
        fprintf(stderr,"No lock from %d to %d\n",start,len);
    }
    else if(arg.l_type == F_WRLCK)
    {
        fprintf(stderr,"Write Lock From %d to %d,id = %d\n",start,len,arg.l_pid);
    }
    else if(arg.l_type == F_RDLCK)
    {
        fprintf(stderr,"Read Lock From %d To %d,id = %d\n",start,len,arg.l_pid);
    }
}

2.封装申请读锁函数
void GetReadLock(int fd,int start,int len);
已阻塞模式在文件描述符对应的文件中申请共享读锁,锁定的区域为从偏移start处开始的len字节长度大小的区域

void GetReadLock(int fd,int start,int len)
{
    struct flock arg;
    arg.l_type = F_RDLCK;
    arg.l_whence = SEEK_SET;
    arg.l_start = start;
    arg.l_len = len;
    if(fcntl(fd,F_SETLKW,&arg) == -1)
    {
        fprintf(stderr,"[%d] Set Read Lock failed.\n",getpid());
    }
    else
        fprintf(stderr,"[%d] Set Read Lock From %d To %d\n",getpid(),start,len);
}

3.封装申请设置写锁函数
互斥写锁申请函数GetWriteLock,原型为:
void GetWriteLock(int fd,int start,int len)
功能:已阻塞模式在文件描述符对应的文件中申请互斥写锁,锁定的区域为从偏移start处开始的len字节长度大小的区域。

void GetWriteLock(int fd,int start,int len)
{
    struct flock arg;
    arg.l_type = F_WRLCK;
    arg.l_whence = SEEK_SET;
    arg.l_start = start;
    arg.l_len = len;
    if(fcntl(fd,F_SETLKW,&arg) == -1)
    {
        fprintf(srderr,"[%d] Set Write Lock failed.\n",getpid());
    }
    else
        fprintf(stderr,"[%d] Set Write Lock %d To %d\n",getpid(),start,len);
}

}
}

4.释放锁
void ReleaseLock(int fd,int start,int len)
{
    struct flock arg;
    arg.l_type = F_UNLCK;
    arg.l_whence = SEEK_SET;
    arg.l_start = start;
    arg.l_len = len;
    if(fcntl(fd,F_SETLKW,&arg) == -1)
    {
        fprintf(stderr,"[%d] Unlock failed.\n",getpid());
    }
    else
        fprintf(stderr,"[%d]Unlock From %d To %d\n",getpid(),start,len);
}

时间: 2024-08-30 14:11:43

fcntl文件锁操作的相关文章

python fcntl 文件锁

此模块只有在 unix 系统上才有,windows 没有. 文档地址: https://docs.python.org/3.7/library/fcntl.html https://www.docs4dev.com/docs/zh/python/3.7.2rc1/all/library-fcntl.html 多进程示例程序 import fcntl import os import time from multiprocessing import Pool def worker(): print

每天进步一点点——Linux编程中的文件锁之flock

转载请说明出处:http://blog.csdn.net/cywosp/article/details/30083015 1. 场景概述 在多线程开发中,互斥锁可以用于对临界资源的保护,防止数据的不一致,这是最为普遍的使用方法.那在多进程中如何处理文件之间的同步呢?我们看看下面的图: 图中所示的是两个进程在无同步的情况下同时更新同一个文件的过程,其主要的操作是: 1. 从文件中读取序号. 2. 使用这个序号完成应用程序定义的任务. 3. 递增这个序号并将其写回文件中. 从图中可得知两个进程读取分

linux fcntl函数详解

转自:http://www.cnblogs.com/lonelycatcher/archive/2011/12/22/2297349.html 功能描述:根据文件描述词来操作文件的特性. #include <unistd.h>#include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock

linux fcntl函数

linux fcntl函数 #include <unistd.h>#include <fcntl.h>int fcntl(int fd, int cmd);int fcntl(int fd, int cmd, long arg);int fcntl(int fd, int cmd, struct flock *lock); [描述]fcntl()针对(文件)描述符提供控制.参数fd是被参数cmd操作(如下面的描述)的描述符.针对cmd的值,fcntl能够接受第三个参数int arg

喜羊羊系列之fcntl

功能描述:根据文件描述词来操作文件的特性. #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); int fcntl(int fd, int cmd, long arg); int fcntl(int fd, int cmd, struct flock *lock); [描述] fcntl()针对(文件)描述符提供控制.参数fd是被参数cmd操作(如下面的描述)的描述符.针对cmd的值,fcntl能够接

unix/linux 进程间文件锁

转自 http://www.cnblogs.com/hjslovewcl/archive/2011/03/14/2314333.html 有三种不同的文件锁,这三种都是“咨询性”的,也就是说它们依靠程序之间的合作,所以一个项目中的所有程序封锁政策的一致是非常重要的,当你的程序需要和第三方软件共享文件时应该格外地小心. 有 些程序利用诸如 FIlENAME.lock 的文件锁文件,然后简单地测试此类文件是否存在.这种方法显然不太好,因为当产生文件的进程被杀后,锁文件依然存在,这样文件也许会被永久锁

SQLite语法

一.建立数据库 sqlite3.exe test.db 二.双击sqlite-3_6_16目录下的程序sqlite3.exe,即可运行 三.退出 .exit 或者 .quit 四.SQLite支持如下5种数据类型 1.NULL:空值.2.INTEGER:带符号的整型,具体取决有存入数字的范围大小.3.REAL:浮点数字,存储为8-byte IEEE浮点数.4.TEXT:字符串文本.5.BLOB:二进制对象. 五.联系人表格结构如下 create table contact(id integer

Linux文件(区域)锁函数 -- open(), fctnl()

一.什么是文件锁定 对于锁这个字,大家一定不会陌生,因为我们生活中就存在着大量的锁,它们各个方面发挥着它的作用,现在世界中的锁的功能都可归结为一句话,就是阻止某些人做某些事,例如,门锁就是阻止除了屋主之外的人进入这个房子,你进入不到这个房子,也就不能使用房子里面的东西. 而因为程序经常需要共享数据,而这通常又是通过文件来实现的,试想一个情况,A进程正在对一个文件进行写操作,而另一个程序B需要对同一个文件进行读操作,并以读取到的数据作为自己程序运行时所需要的数据,这会发生什么情况呢?进程B可能会读

sqlite3常用指令

一.建立数据库 sqlite3.exe test.db 二.双击sqlite-3_6_16目录下的程序sqlite3.exe,即可运行 三.退出 .exit 或者 .quit 四.SQLite支持如下5种数据类型 1.NULL:空值.2.INTEGER:带符号的整型,具体取决有存入数字的范围大小.3.REAL:浮点数字,存储为8-byte IEEE浮点数.4.TEXT:字符串文本.5.BLOB:二进制对象. 五.联系人表格结构如下 create table contact(id integer