免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3898 | 回复: 9
打印 上一主题 下一主题

求助 fcntl 锁文件的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-07-20 14:26 |只看该作者 |倒序浏览

  1. #include <stdio.h>;
  2. #include <sys/types.h>;
  3. #include <sys/stat.h>;
  4. #include <unistd.h>;
  5. #include <fcntl.h>;

  6. void get_lock_status(int fd,char *msg)
  7. {
  8.         struct flock my_lock;

  9.         bzero(&my_lock,sizeof(struct flock));
  10.         my_lock.l_type   =F_WRLCK;
  11.         my_lock.l_whence =0;
  12.         my_lock.l_start  =0;
  13.         my_lock.l_len    =0;

  14.         if(-1==fcntl(fd, F_GETLK, &my_lock))
  15.         {
  16.                 printf("get_lock_status error\n");
  17.                 return;
  18.         }

  19.         printf("%s l_type=%d,l_pid=%d\n",msg,my_lock.l_type,my_lock.l_pid);
  20.         return;
  21. }
  22. int lock_file(int fd)
  23. {
  24.         struct flock my_lock;

  25.         get_lock_status(fd,"before lock ");

  26.         my_lock.l_type   =F_WRLCK;
  27.         my_lock.l_whence =0;
  28.         my_lock.l_start  =0;
  29.         my_lock.l_len    =0;

  30.         if (-1 == fcntl(fd, F_SETLKW, &my_lock))
  31.         {
  32.                 close(fd);
  33.                 printf("fcntl error \n");
  34.                 return -3;
  35.         }

  36.         get_lock_status(fd,"after lock ");

  37.         return 0;
  38. }
  39. int main()
  40. {
  41.         int fd;

  42.         fd = open("test.lock", O_RDWR);
  43.         if (-1 == fd)
  44.         {
  45.                 printf("open error\n");
  46.                 return -1;
  47.         }

  48.         if(0!=lock_file(fd))
  49.         {
  50.                 printf("lock error\n");
  51.         }
  52.         return 0;
  53. }


复制代码

  1. #gcc -o test test.c
  2. ./test
  3. before lock  l_type=2,l_pid=0
  4. after lock  l_type=2,l_pid=0

复制代码


不知道代码有没有问题。如果代码没问题,那么为什么结果的 l_type 都是2呀?
我的代码好像没给文件加上锁,期待有人来解答。

我发现在/usr/include/bits/fcntl.h里有
#define F_RDLCK         0       /* Read lock.  */
#define F_WRLCK         1       /* Write lock.  */
#define F_UNLCK         2       /* Remove lock.  */

论坛徽章:
0
2 [报告]
发表于 2005-07-20 15:35 |只看该作者

求助 fcntl 锁文件的问题

关注ing

论坛徽章:
0
3 [报告]
发表于 2005-07-20 16:35 |只看该作者

求助 fcntl 锁文件的问题

怎么没人理阿!!我顶!!

论坛徽章:
0
4 [报告]
发表于 2005-07-20 17:21 |只看该作者

求助 fcntl 锁文件的问题

我觉得锁应该是加上了,只是在同一个进程里,不能返回锁定的状态。因为这个进程有权对锁定的文件操作,所以在同一个进程里返回的锁定状态是 “未被锁定”。

不知说的对否?

论坛徽章:
0
5 [报告]
发表于 2005-07-20 18:07 |只看该作者

求助 fcntl 锁文件的问题

怎么没人解答呀?是不是问题太弱了,

论坛徽章:
0
6 [报告]
发表于 2005-07-20 23:38 |只看该作者

求助 fcntl 锁文件的问题

l_type:锁的类型.
F_RDLCK读锁(共享锁)
F_WRLCK写锁(独占锁)

锁的分类可以分为强制性锁和建议性锁两种,强制型锁不需要在采取其它措施就自动起到互斥作用;建议性锁仅起到告示作用.在使用建议性锁时,进程需要监测文件相关部分是否上了锁,然后在决定是否对其进行读写操作,这样也能起到若干个进程对相关文件部分进行互吃的对写操作.
使用chmod和fcntl的F_SETLK命令相结合可以设置强制性锁;单独调用fcntl的F_SETLK的命令只能设置建议性锁.
chmod +l example


从操作类型可以将锁分为读锁和写锁;在使用fcntl的的F_SETLK命令设置锁时,使用锁类型F_RDLK, F_WRLK指定.

锁的合并:
若不同进程需要设置的两把锁作用范围部分或全部重叠,则先设置的读锁阻止后来设置的;先设置的写锁阻止后来的读/写锁.若同一进程先后要求设置的两把锁(A,B)的作用范围部分或全部重叠,则在两把锁同类的情况下,它们的作用范围合并成一把锁(AUB);若两把锁不同类,则后设置的锁覆盖先设置的锁,先设置的锁的范围变成(AUB) - B.锁的互斥,合并及覆盖与是建议性还是强制型锁无关.

强制性读锁能阻止其它进程对相应文件(或记录)进行写操作;强制性写锁能阻止其它进程进行读/写操作.

为了检测文件的上锁情况,应当使用fcntl的F_GETLK命令.
可以使用带锁类型F_UNLCK的F_SETLK命令清除锁的部分或全部.当文件关闭或进程中止时,它所设置的锁全部自动清除.一个进程不能清除其它进程所加的锁.

F_UNLCK (释放锁)
参数l_whence和l_start标识锁的起始地址,含义与lseek的同名参数相同.l_whence可以是SEEK_SET(从文件头开始), SEEK_CUR(从当前位置开始),SEEK_END(从文件结尾计算).
参数l_len标识锁的长度是多少字节,如果为0,则表示锁一直延伸到文件结尾.
l_pid,仅在查询锁时才有用,它是锁的拥有者的pid.

F_SETLK:按照参数进行加锁和解锁的处理.如果因为冲突无法上锁,立即返回并且errno被赋值为EAGAIN.如果l_type是F_UNLCK,以存在的锁被释放.

F_SETLKW:相当于阻塞的F_SETLK(W的含义就是等待wait).如果要上锁的区域被其它进程锁住,使申请没有马上成功,则进程进入睡眠,等待原来的锁被释放,在上锁成功后返回.如果在进程阻塞时有信号发生,返回并且设置errno为EAGAIN.

F_GETLCK:检查是否可以申请由arg制定的锁.如果不和别的进程已经存在的锁发生冲突,arg所指向的flock的l_type被赋值为F_UNLCK,其它成员不变.如果不能给予锁,l_pid被赋值为发生冲突的进程的pid,这两种情况下,函数都返回0.

接着谈一下你的代码吧.
首先,你创建的一个建议性的写锁.接着使用F_GETLK测试是否允许在加一个写锁,注意我上面所提到的锁的合并条件,由于位于同一进程中,并且锁类型相同(写锁),作用范围合并成一把新锁(还是一样的)范围,

首先测试是否可以加写锁,经测试可以,所以输出before lock  l_type=2,l_pid=0(l_type=2也就是允许加写锁);

然后使用阻塞方式加一个建议性的写锁,成功.

然后在此测试是否可以加写锁.注意我上面所提到的锁的合并条件,由于位于同一进程中,并且锁类型相同(写锁),作用范围合并成一把新锁(还是一样的)范围.所以在此输出时,仍旧输出l_type=2,l_pid=0.

所以你的get_lock_status并不是获得锁的状态,实际上仅仅是一个是否可锁的测试.
要确定锁的类型,我觉得还是用


  1. if (lock.l_type == F_RDLCK)
  2.   是读锁;
复制代码

等语句来确定.[/code]

论坛徽章:
0
7 [报告]
发表于 2005-07-21 08:48 |只看该作者

求助 fcntl 锁文件的问题

原帖由 "renstone921" 发表:

然后在此测试是否可以加写锁.注意我上面所提到的锁的合并条件,由于位于同一进程中,并且锁类型相同(写锁),作
用范围合并成一把新锁(还是一样的)范围.所以在此输出时,仍旧输出l_type=2,l_pid=0.

所以你的get_lock_status并不是获得锁的状态,实际上仅仅是一个是否可锁的测试.
要确定锁的类型,我觉得还是用




  1. if (lock.l_type == F_RDLCK)
  2. 是读锁;
复制代码


等语句来确定.




在fcntl.h里定义了 #define F_UNLCK                2
所以输出结果l_type=2,l_pid=0。相当于l_type=F_UNLCK,l_pid=0.
疑问 为什么输出结果 l_type=2 ?

论坛徽章:
0
8 [报告]
发表于 2005-07-21 10:06 |只看该作者

求助 fcntl 锁文件的问题

不好意思,昨天脑袋有点乱,没说清楚,怎么好象是在梦呓.
看man fcntl的原文:
             On  input  to  this  call, lock describes a lock we would like to place on the file.  If the lock
              could be placed, fcntl() does not actually place it, but returns F_UNLCK in the l_type  field  of
              lock  and  leaves the other fields of the structure unchanged.  If one or more incompatible locks
              would prevent this lock being placed, then fcntl() returns details about one of  these  locks  in
              the  l_type, l_whence, l_start, and l_len fields of lock and sets l_pid to be the PID of the pro-
              cess holding that lock.
F_GETLK的行为就是描述一个想要加到文件上但并未实际加上的锁的锁.
如果锁可以加上.
  fcntl并不实际加上该锁,而是在lock的l_type字段赋值为F_UNLCK并保留结构的其它字段不变.
如果存在一个或多个不兼容的锁(这些锁阻止这个新的锁),则fcntl()返回这这些依存在的锁中的一个,其中pid是放置的是发生冲突的进程的pid.

也就是说,由于你的代码是这样的.
get_lock_status()的调用-由于经测试可以加写锁,因此l_type==F_UNLCK.
然后调用fcntl(fd, F_SETLKW, ...)结果成功.
然后在此调用get_lock_status-看一下以前我所提到的锁的合并条件,经测试可以加锁,因此l_type == F_UNLCK
这就是两次调用l_type都是F_UNLCK的原因.说简单一些就是,这是由你的代码的流程决定的.
因为你的代码实际上流程就是:
测试可否加上写锁---------加写锁-------------测试是否可加上写锁.
看上面的man帮助就可以知道在测试后,由于没有发生冲突,所以l_type变成了F_UNLCK,这次说清除了没有;
你可以自己写代码测试一下多进程,父子进程锁的情况.

这次说的清楚一点了吧?
有问题欢迎一起讨论.

论坛徽章:
0
9 [报告]
发表于 2005-07-21 10:17 |只看该作者

求助 fcntl 锁文件的问题

谢谢 renstone921   ,说的非常清楚。
真是有好人呀

论坛徽章:
0
10 [报告]
发表于 2014-09-01 21:52 |只看该作者
最近在研究unix网络编程卷一,虽然这都这么多年了,但还是在传承,没什么能比这个更能证明是个经久不衰的经典了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP