乐趣区

关于高性能:文件系统中的锁

在多过程共享的应用程序中,通过“锁”来对同一个计算资源进行协同是十分常见的做法,无论在单机或多机的零碎、数据库、文件系统中,都须要依赖“锁”机制来防止并发拜访导致的不确定后果,明天咱们就来讲讲文件系统中的“锁”。

首先,文件锁也是一种互斥机制,可确保多个过程以平安的形式读取 / 写入同一个文件。之所以要对这些多过程业务进行管制,就是因为这些过程的调度是不可预期的,这种时序上的不可预期会对同一个文件资源产生竞争性拜访,从而带来预期外的后果。

咱们能够看一个例子,以便更好地了解这个问题。

假如咱们有一个 account.dat 文件,用于存储帐户余额,其初始值为“200”。并发零碎有两个过程来更新这个文件上的余额值:

  1. 过程 A:读取以后值,减去 20,而后将后果保留回文件中。
  2. 过程 B:读取以后值,加 80,而后将后果写回到文件中。

显然,在程序执行完这两个过程后,咱们冀望文件具备以下值:200-20 + 80 = 260。

然而,如果过程的执行不是按预期的程序直径,在以下这种状况下,可能会呈现不一样的后果:

  1. 过程 A 读取文件的以后值(200),并筹备进行进一步的计算。
  2. 这时,过程 B 读取雷同的文件并取得以后余额(200)。
  3. 过程 A 计算 200-20 并将后果 180 保留回文件。
  4. 过程 B 不晓得余额已更新。因而,它仍将应用过期的值 200 计算 200 + 80,并将后果 280 写入文件。

后果,account.dat 文件中保留的余额就是 280 而不是预期值 260。

Linux 中的文件锁

像后面提到的,文件锁是一种在多个过程之间限度文件并发拜访的机制。它仅容许一个过程在特定工夫内拜访文件,从而防止更新问题。

咱们都晓得 rm -rf / 在 Linux 中是十分危险的命令。如果咱们以 root 用户身份执行该命令,它甚至能够删除正在运行的零碎中的所有文件。这是因为 Linux 通常不会主动给关上的文件加锁,所以即便是正在运行的文件,依然有可能被 rm 命令删除。Linux 反对两种文件锁:协同锁(Advisory lock)和强制锁(Mandatory lock)。

协同锁(Advisory lock)

协同锁定不是强制性锁计划,仅当参加的过程通过显式获取锁进行合作时,它才无效。否则,如果某个过程基本不晓得锁,则这个协同锁会被疏忽掉(意味着各个过程间必须协商并恪守这个协同锁的机制,能力施展锁的作用)。

上面这个例子能够帮忙咱们更容易地了解协同锁机制。让咱们先回顾一下咱们之前提到的账户文件的例子。

首先,咱们假如文件 account.dat 仍蕴含初始值“200”。

过程 A 获取 account.dat 文件的排他锁,而后关上并读取该文件以获取以后值:200。

咱们必须理解,协同锁不是由操作系统或文件系统设置的。因而,即便过程 A 锁定了文件,过程 B 依然能够通过零碎调用自在读取、写入或删除文件。

如果过程 B 不尝试在获取锁的状况下,就执行文件操作,则能够说过程 B 与过程 A 没有应用协同锁机制进行单干,依然会带来不可预期的后果。

当初,让咱们看一下锁如何在合作流程中发挥作用:

  1. 过程 B 尝试在读取文件之前(与过程 A 合作)取得对 account.dat 文件的锁。
  2. 因为过程 A 已取得文件锁,因而过程 B 必须期待过程 A 开释锁。
  3. 过程 A 计算 100-20 并将 80 写回到文件中。
  4. 过程 A 开释锁。
  5. 过程 B 当初获取一个锁并读取文件,并获取更新的值:180。
  6. 过程 B 开始其逻辑,并将后果 260(180 + 80)写回到文件中。
  7. 过程 B 开释锁,以便其余合作过程能够持续读写该文件。

强制锁(Mandatory Lock)

与合作锁不同,强制锁不须要参加过程之间的任何单干。一旦在文件上激活了强制锁,操作系统便会阻止其余过程读取或写入文件。

要在 Linux 中启用强制性文件锁定,必须满足两个要求:

  1. 咱们必须应用 mand 选项挂载文件系统(挂载 -o mand FILESYSTEM MOUNT_POINT)。
  2. 咱们必须为要锁定的文件(chmod g + s,g-x FILE)关上 set-group-ID 位,并敞开组执行位。

应用强制锁之后,这个锁会在操作系统级别进行治理和管制。

查看零碎中的所有锁

slocks 命令

lslocks 命令是 util-linux 软件包的一个组件,在所有 Linux 发行版中都可用,通过这个命令能够列出零碎中所有以后持有的文件锁。

在以下列表中,咱们能够看到零碎中所有以后锁定的文件,还能够看到每个锁的详细信息,例如锁的类型以及哪个过程持有该锁。

/ proc /locks

/ proc / locks 不是命令,它是 procfs 虚构文件系统中的文件。该文件蕴含所有以后文件锁,lslocks 命令也依赖于此文件来生成列表。

要获取 / proc / locks 的信息,咱们执行“cat / proc / locks”:

咱们从第一行开始,理解 / proc / locks 文件系统中锁信息的组织形式:

  1. 第一列是序列号。
  2. 第二个字段批示应用的锁类别,例如 FLOCK(来自 flock 零碎调用)或 POSIX(来自 lockf,fcntl 零碎调用)。
  3. 此列用于阐明锁类型。它能够有两个值:ADVISORY 或 MANDATORY。
  4. 第四个字段显示该锁是 WRITE 还是 READ 锁。
  5. 第五个字段是锁的过程 ID。
  6. 该字段蕴含一个冒号分隔的字符串,以“major-device:minor-device:inode”的格局显示锁定文件的 ID。
  7. 此列以及最初一列显示了被锁定文件的锁定区域的开始和完结。在此示例行中,整个文件被锁定(0-EOF)。

因为分布式文件系统次要用于多个客户端中共享文件,客户端的应用程序并发拜访文件是很常见的操作,在理论利用中,渲染、HPC 等业务都须要应用到文件锁,锁的反对对分布式文件系统而言至关重要。YRCloudFile 反对 POSIX 语义中的协同锁和共享锁,用户能够通过 flock 或 fcntl 等零碎调用来对文件进行锁操作,锁的粒度能够反对到文件级别或文件内的指定区间。

退出移动版