导航:[首页]->[cpp]->[flock及其陷阱]

flock可用作文件锁,利用它在进程结束后自动释放的特性,可用作进程互斥.

#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


int main(int argc, char** argv) 
{
    int fd = open("/tmp/fuck",O_CREAT | O_TRUNC);
    if(fd < 0)
    {   
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1; 
    }   
    if(flock(fd,LOCK_EX | LOCK_NB) != 0)
    {   
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));                                                                              
        return -1; 
    }   
    while(1) sleep(1);
    return 0;
}

不过flock有一些特性容易出问题.

由于必须所有的引用改fd的句柄被close,锁才会自动释放,所以dup或者fork出来的句柄都必须close才能让锁自动释放.例如程序fork了一个子进程并且尚未退出,那么flock这个自动释放锁的特性就失效了.因为子进程仍然保有这个锁.

我们可以使用fcntl或者在open时直接使用O_CLOEXEC (Since Linux 2.6.23)标志位,让句柄不可继承.不过这仍不可避免那些dup或者只fork不exec的情况.

另外一个特性时,任何一个句柄unlock都会导致解锁,例如先加锁,fork只进程(继承了句柄),然后使用该句柄flock(LOCK_UN),那么父进程加的锁就失效了.

若受到以上问题影响,可以使用fcntl(F_SETLK)加锁,fcntl锁在fork之后会自动清空.

参考

  1. http://www.ibm.com/developerworks/cn/linux/l-cn-filelock/
  2. http://man7.org/linux/man-pages/man2/flock.2.html
  3. http://blog.csdn.net/hiawui/article/details/6211305