代码之家  ›  专栏  ›  技术社区  ›  cweston Given

fcntl,lockf,哪个更好地用于文件锁定?

  •  44
  • cweston Given  · 技术社区  · 15 年前

    正在查找有关 优势 缺点 两者兼而有之 文件锁 洛克夫 用于文件锁定。例如,哪一个更适合用于可移植性?我目前正在编写一个Linux守护进程,想知道哪一个更适合用于强制互斥。

    5 回复  |  直到 8 年前
        1
  •  60
  •   Will Vousden    8 年前

    lockf和fcntl有什么区别:

    在许多系统上, lockf() 库例程只是一个包装器 fcntl() . 这就是说 lockf 提供以下功能的子集: fcntl 做。

    Source

    但在某些系统上, 文件锁 洛克夫 锁是完全独立的。

    Source

    由于它依赖于实现,请确保始终使用相同的约定。因此,要么始终使用两个进程中的lockf,要么始终使用fcntl。它们很有可能是可以互换的,但使用同一个更安全。

    你选择哪一个无关紧要。


    关于强制锁和咨询锁的一些说明:

    默认情况下,在UNIX/Linux中锁定 咨询的 ,这意味着其他进程不需要遵循设置的锁定规则。所以无论您锁定的方式是什么,只要您的合作过程也使用相同的约定。

    Linux确实支持 强制性的 锁定,但仅当安装了文件系统并设置了选项on和文件特殊属性时。你可以用 mount -o mand 安装文件系统并设置文件属性 g-x,g+s 要启用强制锁,请使用 文件锁 洛克夫 . 有关强制锁如何工作的详细信息,请参阅 here .

    请注意,锁不是应用于单个文件,而是应用于inode。这意味着指向相同文件数据的两个文件名将共享相同的锁定状态。

    另一方面,在Windows中,您可以以独占方式打开一个文件,这将阻止其他进程完全打开该文件。即使他们愿意。也就是说,锁是强制性的。Windows和文件锁也是如此。具有适当访问权限的打开文件句柄的任何进程都可以锁定文件的一部分,其他进程将无法访问该部分。


    Linux中强制锁的工作方式:

    关于强制锁,如果一个进程用读取锁锁定了文件的某个区域,那么其他进程就可以读取但不能写入该区域。如果一个进程用写锁锁定了文件的某个区域,则不允许其他进程读取或写入该文件。如果不允许进程访问文件的一部分,则会发生什么情况取决于您是否指定了 O_NONBLOCK 或者没有。如果设置了阻塞,它将等待执行该操作。如果没有设置阻塞,您将得到错误代码 EAGAIN .


    NFS警告:

    如果在NFS装载上使用锁定命令,请小心。这种行为是未定义的,无论是只使用本地锁还是支持远程锁,实现方式都有很大的不同。

        2
  •  10
  •   Diomidis Spinellis    15 年前

    这两个接口都是POSIX标准的一部分,现在这两个接口在大多数系统上都可用(我刚刚检查了Linux、FreeBSD、Mac OS X和Solaris)。因此,选择一个更适合您的需求并使用它。

    一句警告:当一个进程使用fcntl锁定文件,另一个进程使用lockf锁定文件时,会发生什么,这是未指定的。在大多数系统中,这些操作都是等效的(实际上,在Linux中,lockf是在fcntl之上实现的),但是posix说它们的交互是未指定的。因此,如果您正在与使用这两个接口之一的另一个进程进行交互操作,请选择相同的接口。

    其他人则写道,这些锁只是建议性的:您负责检查某个区域是否被锁定。此外,如果要使用锁定功能,请不要使用stdio函数。

        3
  •  9
  •   strager    10 年前

    您的主要关注点,在这种情况下(即 对Linux守护进程进行编码 想知道哪个更适合使用 用于强制相互排斥 “”,应该是:

    1. 锁定的文件是本地的还是在NFS上的?
      • 例如,用户能否欺骗您在NFS上创建和锁定守护进程的PID文件?
    2. 锁什么时候开 fork 或者当守护进程以极端偏见终止时,例如 kill -9 ?

    这个 flock fcntl 两种情况下命令的行为都不同。

    我的建议是 文件锁 . 您可以参考 File locking article on Wikipedia 要深入讨论这两种解决方案所涉及的问题:

    Flock和Fcntl都有一些怪癖, 偶尔会让程序员感到困惑 其他操作系统。羊群 锁在网络文件系统上工作, 如nfs,is实现 依赖的。在BSD系统上,群呼叫 成功了没有行动。Linux之前 到2.6.12对NFS文件的Flock调用 只能在当地行动。内核2.612 上面实现了对NFS的集群调用 使用POSIX字节范围锁的文件。 其他人可以看到这些锁 实现的NFS客户端 fcntl()/posix锁。 1 锁升级 降级释放旧锁 在应用新锁之前。如果一个 应用程序降级独占 锁定到共享锁,而另一个 应用程序被阻止等待 独占锁,后一个应用程序 将获得专用锁和 第一个应用程序将被锁定。 与文件关联的所有fcntl锁 对于给定的进程,当 该文件的任何文件描述符都是 通过那个过程关闭,即使锁 从未请求该文件 描述符。此外,fcntl锁不是 由子进程继承。这个 fcntl关闭语义尤其重要 应用程序出现问题 调用可能 访问文件。

        4
  •  7
  •   RMCE    10 年前

    最近我在使用fcntl和flock时遇到了一个问题,我觉得我应该在这里报告,因为搜索任何一个术语都会在这两个术语的顶部显示此页面。

    如上所述,BSD锁是 咨询的 . 对于那些不知道奥斯陆(达尔文)是BSD的人来说。打开要写入的文件时必须记住这一点。

    要使用fcntl/flock,必须首先打开文件并获取其ID。但是,如果已使用“w”打开文件,则文件将立即 归零 . 如果您的进程在其他地方使用该文件时未能获得锁,那么它很可能会返回,将文件保留为0KB。拥有锁的过程现在会发现文件已经从它下面消失了,灾难性的结果通常会随之而来。

    为了解决这种情况,在使用文件锁定时, 从未 打开文件“w”,而不是打开它“a”,以附加。然后,如果成功获取锁,则可以安全地将文件清除为“w”,即:

    fseek(filehandle,0,seek_set);//移动到开始

    ftruncate(fileno((file*)filehandle),0);//清除

    这对我来说是一个不愉快的教训。

        5
  •  1
  •   MarkR    15 年前

    因为您只对一个守护进程进行编码,而这个守护进程使用它进行互斥,所以它们是等效的,毕竟,您的应用程序只需要与自身兼容。

    文件锁定机制的诀窍是保持一致——使用一个并坚持下去。改变它们是个坏主意。

    我在这里假设文件系统是本地的-如果不是,那么所有的赌注都是关闭的,NFS/其他网络文件系统以不同的有效性处理锁定(在某些情况下没有)。