【问题标题】:How to lock and unlock pid file with "fcntl()"如何使用“fcntl()”锁定和解锁 pid 文件
【发布时间】:2013-06-07 15:55:33
【问题描述】:

为了找到使用fcntl() 锁定和解锁pid 文件"/var/run/myapp.pid" 的示例,我在网上甚至在stackoverflow 上进行了研究,但我没有找到一个明确的示例。

您能否指出一个使用fcntl() 锁定和解锁pid 文件的示例?

不应阻止锁(如果文件已被锁定)

【问题讨论】:

    标签: c linux fcntl


    【解决方案1】:

    当您标记 Linux 时,逐字记录 man lockf(我强调):

    在 Linux 上,lockf()只是 fcntl(2) 锁定之上的一个接口。许多其他系统以这种方式实现 lockf(),但请注意 POSIX.1-2001 保留了 lockf() 和 fcntl( 2) 未指定的锁。一个可移植的应用程序可能应该避免混合调用这些接口。

    因此查找当前的 glibc 源 (eglibc-2.11.3/io/lockf.c) 可能使用 fcntl() 来实现锁定,如下所示:

    /* Copyright (C) 1994,1996,1997,1998,2000,2003 Free Software Foundation, Inc.
       This file is part of the GNU C Library.
    
       The GNU C Library is free software; you can redistribute it and/or
       modify it under the terms of the GNU Lesser General Public
       License as published by the Free Software Foundation; either
       version 2.1 of the License, or (at your option) any later version.
    
       The GNU C Library is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       Lesser General Public License for more details.
    
       You should have received a copy of the GNU Lesser General Public
       License along with the GNU C Library; if not, write to the Free
       Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
       02111-1307 USA.  */
    
    #include <sys/types.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <string.h>
    
    /* lockf is a simplified interface to fcntl's locking facilities.  */
    
    int
    lockf (int fd, int cmd, off_t len)
    {
      struct flock fl;
    
      memset ((char *) &fl, '\0', sizeof (fl));
    
      /* lockf is always relative to the current file position.  */
      fl.l_whence = SEEK_CUR;
      fl.l_start = 0;
      fl.l_len = len;
    
      switch (cmd)
        {
        case F_TEST:
          /* Test the lock: return 0 if FD is unlocked or locked by this process;
             return -1, set errno to EACCES, if another process holds the lock.  */
          fl.l_type = F_RDLCK;
          if (__fcntl (fd, F_GETLK, &fl) < 0)
            return -1;
          if (fl.l_type == F_UNLCK || fl.l_pid == __getpid ())
            return 0;
          __set_errno (EACCES);
          return -1;
    
        case F_ULOCK:
          fl.l_type = F_UNLCK;
          cmd = F_SETLK;
          break;
        case F_LOCK:
          fl.l_type = F_WRLCK;
          cmd = F_SETLKW;
          break;
        case F_TLOCK:
          fl.l_type = F_WRLCK;
          cmd = F_SETLK;
          break;
    
        default:
          __set_errno (EINVAL);
          return -1;
        }
    
      /* lockf() is a cancellation point but so is fcntl() if F_SETLKW is
         used.  Therefore we don't have to care about cancellation here,
         the fcntl() function will take care of it.  */
      return __fcntl (fd, cmd, &fl);
    }
    

    首先需要一些模组来编译:

    • __fcntl 替换为fcntl
    • __set_errno(&lt;errno-define&gt;) 替换为errno = &lt;errno-define&gt;

    .. 其次让它变成 async-signal-save:

    • 将对memset() 的调用替换为对struct fcntl 变量的适当分配。

    【讨论】:

    • 所以如果我开发自己的lockf() 函数,例如它的名字将是async_lockf()。然后我将上述函数的内容复制到此函数中,并进行您指定的更改。那么新函数async_lockf() 将是一个异步信号保存函数,然后我可以在 sigaction 处理程序中使用它。是真的吗?
    • 对于memset():我将其更改为:struct flock fl = {0}
    • @MOHAMED:看起来是这样,是的。但我宁愿避免称它为 *lockf* 之类的东西,因为它并不真正指代 lockf(),而只是模仿它的行为。但是:您知道这是 GPL 的代码,不是吗?
    • GPL 没问题。我也在开发一个开源项目(GPL)。并保留版权
    • 所以最后我们为解锁文件提供了一个带有同步信号保存的解决方案,以便在 sigaction 处理程序中使用它。非常感谢您的支持。这可能是我第一个问题的最终答案
    猜你喜欢
    • 2021-08-14
    • 2018-03-27
    • 2019-11-24
    • 2018-07-18
    • 2016-12-11
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多