linux fcntl 修改文件大小到0,fcntl 文件锁 详解

fcntl函数说明

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

文件锁包括建议性锁和强制性锁。

建议性锁要求每个上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁。在一般情况下,内核和系统都不使用建议性锁。

强制性锁是由内核执行的锁,当一个文件被上锁进行写入操作的时候,内核将阻止其它任何文件对其进行读写操作。采用强制性锁对性能的影响很大,每次读写操作都必须检查是否有锁存在。

在Linux中,实现文件上锁的函数有lock和fcntl,其中flock用于对文件施加建议性锁,而fcntl不仅可以施加建议性锁,还可以施加强制性锁,还能对文件的某一记录进行上锁,也就是记录锁。

记录锁又分为读取锁和写入锁。

读取锁又称共享锁,能使多个进程都在文件的同一部分建立读取锁。

写入锁又称为排斥锁,在任何时刻只能有一个进程在文件的某个部分建立写入锁。

在文件的同一部分不能同时建立读取锁和写入锁。

(2)fcntl函数格式  具体的知识可以参看unix环境高级编程

Fcntl函数语法要点:

所需头文件:#include

#include

#include

函数原型:int fcntl(int fd,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_GETFK:根据lock描述,决定是否上文件锁

F_SETFK:设置lock描述的文件锁

F_SETLKW:这是F_SETLK的阻塞版本(命令名中的W表示等待(wait))。如果存在其它锁,则调用进程睡眠;如果捕捉到信号则睡眠中断

这三种是在文件锁时cmd 使用的三种命令

F_GETOWN:检索将收到SIGIO和SIGURG信号的进程号或进程组号

F_SETOWN:设置进程号或进程组号

Lock:结构为flock,设置记录锁的具体状态

函数返回值:成功:0

-1:出错

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:加锁区域长度

l_pid:具有阻塞当前进程的锁,其持有进程的进程号存放在l_pid中,仅由F_GETLK  返回

3.fcntl 使用实例

下面首先给出了使用fcnt函数的文件记录锁功能的代码实现。在该代码中,首先给flock结构体的对应

赋予相应的值。

接着调用两次fcntl函数。用F_GETLK命令判断是否可以进行flock所描述的锁操作:若可以进行,则flock

结构体的l_type会被设置为F_UNLCK,其他域不变;若不行,则l_pid被设置为拥有文件锁的进程号,其他域不变。

用F_SETLK和F_SETLKW命令设置flock结构所描述的锁操作,后者是前者的阻塞版。

当第一次调用fcntl时,使用F_GETLK命令获得当前文件被上锁的情况,由此可以判断能不能上锁操作;当第二次调用fcntl时,使用F_SETLKW命令对指定文件进行上锁/解锁操作。因为F_SETLKW命令是阻塞式操作,因此当不能把上锁/解锁操作进行下去时,运行被阻塞,直到能够进行操作为止。

实例说明

开启两个终端,在两个终端上同时运行./write_lock 程序,

当为写入锁,同一时刻只能有一个写入锁存在,

同一时刻只能一个进程对同一个文件写

注意运行的结果

1.首先运行右边终端中的程序,提示 write lock set by 3638  进程号

2.容纳后运行左边终端中的程序,提示 write lockalready set by 3683

3.右边终端敲  回车  ,释放读锁

4.左边终端敲  回车  , 提示 write lock set by 3639

代码分析:源代码是 《嵌入式应用程序设计》 这本书中,但是源代码不能在自己的机子上编译,

于是修改了下,共有三个文件 set_lock.c set_lock.h write_lock.c

还有一个程序是 读锁,原理一样。

set_lock.h

#ifndef _LOCK_SET_H

#define _ LOCK_SET_H

#include

#include

#include

#include

int lock_set(int fd,int type);

#endif

set_lock.c

/* lock_set.c */

#include"lock_set.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;

}/* end of switch */

return 0;

}

write_lock.c

/* write_lock.c */

#include

#include

#include

#include

#include

#include

#include "lock_set.h"

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);

return 0;

}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部