1. 在linux中fcntl函数在某个位置加锁,l_start=30是指在该文件的第30个字节处开始加锁么
单位就是字节,你可以查看man手册。一般用l_whence就够了,l_start基于l_whence的相对位移量,内l_whence有SEEK_SET,SEEK_CUR ,SEEK_END 三个值可选。容
2. 「干货」linux文件系统中的“锁”
在多进程共享的应用程序中,通过“锁”来对同一个计算资源进行协同是非常常见的做法,无论在单机或多机的系统、数据库、文件系统中,都需要依赖“锁”机制来避免并发访问导致的不确定结果,今天我们就来讲讲文件系统中的“锁”。
首先,文件锁也是一种互斥机制,可确保多个进程以安全的方式读取/写入同一个文件。之所以要对这些多进程业务进行控制,就是因为这些进程的调度是不可预期的,这种时序上的不可预期会对同一个文件资源产生竞争性访问,从而带来预期外的结果。
我们可以看一个例子,以便更好地理解这个问题。
假设我们有一个 account.dat 文件,用于存储帐户余额,其初始值为“200”。并发系统有两个进程来更新这个文件上的余额值:
显然,在顺序执行完这两个进程后,我们期望文件具有以下值:200-20 + 80 = 260。
但是,如果进程的执行不是按预期的顺序直径,在以下这种情况下,可能会出现不一样的结果:
结果,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 没有使用协同锁机制进行合作,仍然会带来不可预期的结果。
现在,让我们看一下锁如何在协作流程中发挥作用:
强制锁(Mandatory Lock)
与协作锁不同,强制锁不需要参与进程之间的任何合作。一旦在文件上激活了强制锁,操作系统便会阻止其他进程读取或写入文件。
要在 Linux 中启用强制性文件锁定,必须满足两个要求:
使用强制锁之后,这个锁会在操作系统级别进行管理和控制。
3. linux中fcntl()函数的使用
前面的这5个基本函数实现了文件的打开、读写等基本操作,这一节将讨论的是,在文 件已经共享的情况下如何操作,也就是当多个用户共同使用、操作一个文件的情况,这时,Linux 通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。
文件锁包括建议性锁和强制性锁。
建议性锁要求每个上锁文件的进程都要检查是否有锁存,并且尊重已有的锁。在一般情况下,内核和系统都不使用建议性锁。强制性锁是由内 核执行的锁,当一个文件被上锁进行写入操作的时候,内核将阻止其他任何文件对其进行读写操作。采用强制性锁对性能的影响很大,每次读写操作都必须检查是否有锁存在。
在 Linux 中,实现文件上锁的函数有lock和fcntl,其中flock用于对文件施加建议性锁,而fcntl不仅可以施加建议性锁,还可以施加强制锁。同时,fcntl还能对文件的某一记录进行上锁,也就是记录锁。
记录锁又可分为读取锁和写入锁,其中读取锁又称为共享锁,它能够使多个进程都能在文件的同一部分建立读取锁。而写入锁又称为排斥锁,在任何时刻只能有一个进程在文件的某个部分上建立写入锁。当然,在文件的同一部分不能同时建立读取锁和写入锁。