c语言多进程flock,从flock引发的一个bug谈起(1) 进程的文件描述符

本文介绍了在c语言中使用flock进行多进程文件锁时遇到的一个bug,该bug导致多个进程因等待锁而卡死。文章详细解释了flock的用法,包括其作为劝告锁的性质,以及在父子进程间如何传递和持有文件锁。通过一个具体的代码示例,展示了当父进程未关闭文件并释放锁就调用Python脚本时,导致子进程意外持有锁并引起问题的情况。此外,还探讨了Linux内核中关于文件描述符和文件锁的管理机制。
摘要由CSDN通过智能技术生成

引子

前两天我们QA发现了一个比较有意思的bug,我细细分析一下,发现多个进程卡死在一个·配置文件上。简单的说,我们为了防止多个进程同时写同一个配置文件,将文件格式破坏,我们用了flock,对于写打开,同时调用flock 系统调用,LOCK_EX方式。当然了由于持有锁,就必须临界区要小,写完之后,尽量释放,持有锁的期间不要有time cost high 的操作,否则,会有其他进程获取不到文件锁,活活饿死。

这个bug比较有意思的地方是,大家都等锁的原因调用那个了一个python脚本,而这个脚本并不需要操作配置文件,仅仅是因为父进程system函数调用python脚本之前,没有关闭文件释放锁,导致python脚本很无辜的持有了这本锁,而python偏偏是个time cost high的操作,这就真是急中风偏偏遇到了慢郎中,外围一群进程焦急地等待这把锁,而python进程却占着毛坑不那啥,呵呵。

我们知道,linux存在强制锁(mandatory lock)和劝告锁(advisory lock)。所谓强制锁,比较好理解,就是你家大门上的那把锁,最要命的是只有一把钥匙,只有一个进程可以操作。所谓劝告锁,本质是一种协议,你访问文件前,先检查锁,这时候锁才其作用,如果你不那么kind,不管三七二十一,就要读写,那么劝告锁没有任何的作用。而遵守协议,读写前先检查锁的那些进程,叫做合作进程。我们代码用的是flock这种劝告锁。

Linux实现了POSIX规定的基于fcntl系统调用文件加锁机制,同时LINUX还支持BSD 变体的flock系统调用实现的劝告锁,当然system V变体的lockf也支持,大家可以自行查找手册。对于fcntl这个系统调用,大家可以阅读Stevens大神的UNIX网络编程卷2进程间通信,讲解的非常好。我的重点是flock。

应用层

flock的应用层接口如下

#include int flock(int fd, int operation);

其中fd是系统调用open返回的文件描述符,operation的选项有:

LOCK_SH :共享锁

LOCK_EX :排他锁或者独占锁

LOCK_UN :解锁。

事实上Linux内核也实现了LOCK_MAND选项,所然manual中没有提到。这种情况我们不讨论。

注意了,flock系统调用实现的FL_FLOCK类型的锁,本质是一种劝告锁,只有多个进程之间遵循要读写,先调锁的协议,才会生效。遵循协议的进程叫合作进程。

下面看一段代码:

#include#include#include #include #include #include #include #includeint main()

{

char buf[128];

time_t ltime;

int fd = open("./tmp.txt",O_RDWR);

if(fd < 0)

{

fprintf(stderr,"open failed %s\n",strerror(errno));

return -1;

}

int ret = flock(fd,LOCK_EX);

if(ret)

{

fprintf(stderr,"flock failed for father\n");

return -2;

}

else

{

time(&ltime);

fprintf(

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值