在多进程共享的应用程序中,通过“锁”来对同一个计算资源进行协同是非常常见的做法,无论在单机或多机的系统、数据库、文件系统中,都需要依赖“锁”机制来避免并发访问导致的不确定结果,今天我们就来讲讲文件系统中的“锁”。
-
进程 A:读取当前值,减去 20,然后将结果保存回文件中。 -
进程 B:读取当前值,加 80,然后将结果写回到文件中。
-
进程 A 读取文件的当前值(200),并准备进行进一步的计算。 -
这时,进程 B 读取相同的文件并获得当前余额(200)。 -
进程 A 计算 200-20 并将结果 180 保存回文件。 -
进程 B 不知道余额已更新。因此,它仍将使用过时的值 200 计算 200 + 80,并将结果 280 写入文件。
Linux 中的文件锁
协同锁(Advisory lock)
现在,让我们看一下锁如何在协作流程中发挥作用:
-
进程 B 尝试在读取文件之前(与进程 A 协作)获得对 account.dat 文件的锁。 -
由于进程 A 已获得文件锁,因此进程 B 必须等待进程 A 释放锁。 -
进程 A 计算 200-20 并将 180 写回到文件中。 -
进程 A 释放锁。 -
进程 B 现在获取一个锁并读取文件,并获取更新的值:180。 -
进程 B 开始其逻辑,并将结果 260(180 + 80)写回到文件中。 -
进程 B 释放锁,以便其他协作进程可以继续读写该文件。
强制锁(Mandatory Lock)
要在 Linux 中启用强制性文件锁定,必须满足两个要求:
-
我们必须使用mand选项挂载文件系统(挂载-o mand FILESYSTEM MOUNT_POINT)。
-
我们必须为要锁定的文件(chmod g + s,g-x FILE)打开 set-group-ID 位,并关闭组执行位。
检查系统中的所有锁

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

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

-
第一列是序列号。 -
第二个字段指示使用的锁类别,例如 FLOCK(来自flock系统调用)或 POSIX(来自lockf,fcntl系统调用)。 -
此列用于说明锁类型。它可以有两个值:ADVISORY 或 MANDATORY。 -
第四个字段显示该锁是 WRITE 还是 READ 锁。 -
第五个字段是锁的进程 ID。 -
该字段包含一个冒号分隔的字符串,以“ major-device:minor-device:inode”的格式显示锁定文件的 ID。 -
此列以及最后一列显示了被锁定文件的锁定区域的开始和结束。在此示例行中,整个文件被锁定(0-EOF)。
由于分布式文件系统主要用于多个客户端中共享文件,客户端的应用程序并发访问文件是很常见的操作,在实际应用中,渲染、HPC 等业务都需要使用到文件锁,锁的支持对分布式文件系统而言至关重要。YRCloudFile 支持 POSIX 语义中的协同锁和共享锁,用户可以通过 flock或 fcntl 等系统调用来对文件进行锁操作,锁的粒度可以支持到文件级别或文件内的指定区间。