linux高级IO——记录锁

<div id="blogDetailDiv" style="font-size: 14px;">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><strong><span lang="EN-US"><span>1</span>
</span>
</strong>
<strong><span style="">.记录锁的功能</span>
</strong>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
</span>
</span>
<span style="">当一个进程正在读或修改文件的某个部分时,它可以阻止其他进程修改同一文件区。我们不应该从字面上去理解记录锁,实际上它应该叫“区域锁”,因为它锁定的只是文件的一个(也可能是整个文件)。这个区域用来存放多用户的共享区。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><strong><span lang="EN-US"><span>2</span>
</span>
</strong>
<strong><span style="">.记录锁的分类</span>
</strong>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
</span>
</span>
<span style="">记录锁分为共享读锁和独占写锁,前者也叫做共享锁后者也叫做排他锁。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><strong><span lang="EN-US"><span>3</span>
</span>
</strong>
<strong><span style="">.加锁规则</span>
</strong>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span></span>
<span> </span>
</span>
</span>
<span style="">如果一个进程对共享区加了共享读锁,其他进程只能加共享读锁。如果一个进程加了独占写锁,其他进程就不能加任何锁。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><strong><span lang="EN-US"><span>4</span>
</span>
</strong>
<strong><span style="">.死锁</span>
</strong>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
</span>
</span>
<span style="">如果两个相互等待对方持有并且不释放(已被锁定)的资源是时,则这两个进程就处于死锁状态。如果一个进程已经控制了文件的一个加锁区域,然后它又试图对另一个进程控制的区域加锁,则它就会睡眠,在这种情况下,有发生死锁的可能性。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><strong><span lang="EN-US"><span>5</span>
</span>
</strong>
<strong><span style="">.锁的隐含继承和释放</span>
</strong>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">(</span>
<span lang="EN-US"><span>1</span>
</span>
<span style="">)锁与进程和文件两方面有关系,它和前者关系是:当一个进程结束后,他对文件加的锁也就消失了。它和后者的关系是:当进程</span>
<span lang="EN-US"><span>close</span>
</span>
<span style="">文件描述符,切断文件和进程的联系进程所创建的锁也会消失。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">(</span>
<span lang="EN-US"><span>2</span>
</span>
<span style="">)由</span>
<span lang="EN-US"><span>fork</span>
</span>
<span style="">产生的子进程不继承父进程所设置的锁。这意味着,若一个进程得到一把锁,然后调用</span>
<span lang="EN-US"><span>fork</span>
</span>
<span style="">,那么对于父进程创建的锁而言,子进程被视为另一个进程,不会拥有该锁。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">(</span>
<span lang="EN-US"><span>3</span>
</span>
<span style="">)在执行</span>
<span lang="EN-US"><span>exec</span>
</span>
<span style="">后,新进程可以继承原执行的锁。因为执行</span>
<span lang="EN-US"><span>exec</span>
</span>
<span style="">前后还是一个进程。我们只是改变进程执行的程序,并没有创建新的进程。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><strong><span lang="EN-US"><span>6</span>
</span>
</strong>
<strong><span style="">.要注意的问题</span>
</strong>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="" lang="EN-US"><span> </span>
</span>
<span style="">记录锁只是提供竞争进入某段代码区的功能,不会导致对文件操作失败。也就是说,我们对文件进行加锁后,我们还是可以对文件进行操作。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small;"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span>1</span>
</span>
<span style="">.</span>
</span>
</p>
<table class="MsoNormalTable" style="margin: auto 6.75pt; border-collapse: collapse;" border="0" cellspacing="0" cellpadding="0" align="left"><tbody>
<tr style="height: 15.5pt;">
<td style="padding: 0cm 5.4pt; width: 96.05pt; height: 15.5pt; background-color: transparent;" width="128" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">名称</span>
<span lang="EN-US"><span>:</span>
</span>
<span style="">:</span>
</span>
</p>
</td>
<td style="padding: 0cm 5.4pt; width: 333.05pt; height: 15.5pt; background-color: transparent;" width="444" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small;">fcntl</span>
</span>
</p>
</td>
</tr>
<tr style="height: 14.75pt;">
<td style="padding: 0cm 5.4pt; width: 96.05pt; height: 14.75pt; background-color: transparent;" width="128" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">功能</span>
<span style="">:</span>
</span>
</p>
</td>
<td style="padding: 0cm 5.4pt; width: 333.05pt; height: 14.75pt; background-color: transparent;" width="444" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style=""><span style="font-size: small;">对文加解锁。</span>
</span>
</p>
</td>
</tr>
<tr style="height: 15.5pt;">
<td style="padding: 0cm 5.4pt; width: 96.05pt; height: 15.5pt; background-color: transparent;" width="128" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">头文件</span>
<span style="">:</span>
</span>
</p>
</td>
<td style="padding: 0cm 5.4pt; width: 333.05pt; height: 15.5pt; background-color: transparent;" width="444" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small;">#include &lt;pthread.h&gt;</span>
</span>
</p>
</td>
</tr>
<tr style="height: 12.1pt;">
<td style="padding: 0cm 5.4pt; width: 96.05pt; height: 12.1pt; background-color: transparent;" width="128" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">函数原形</span>
<span style="">:</span>
</span>
</p>
</td>
<td style="padding: 0cm 5.4pt; width: 333.05pt; height: 12.1pt; background-color: transparent;" width="444" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span>int fcntl(int filedes,int cmd,…/*struct flock *flockptr */)</span>
</span>
<span style="">;</span>
</span>
</p>
</td>
</tr>
<tr style="height: 10.95pt;">
<td style="padding: 0cm 5.4pt; width: 96.05pt; height: 10.95pt; background-color: transparent;" width="128" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">参数</span>
<span style="">:</span>
</span>
</p>
</td>
<td style="padding: 0cm 5.4pt; width: 333.05pt; height: 10.95pt; background-color: transparent;" width="444" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span>filedes<span> </span>
</span>
</span>
<span style="">文件描述符</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span>cmd<span> </span>
</span>
</span>
<span style="">测试锁或加锁</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span>flockptr<span> </span>
</span>
</span>
<span style="">指向</span>
<span lang="EN-US"><span>flock</span>
</span>
<span style="">结构的指针</span>
</span>
</p>
</td>
</tr>
<tr style="height: 15.5pt;">
<td style="padding: 0cm 5.4pt; width: 96.05pt; height: 15.5pt; background-color: transparent;" width="128" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style=""><span style="font-size: small;">返回值:</span>
</span>
</p>
</td>
<td style="padding: 0cm 5.4pt; width: 333.05pt; height: 15.5pt; background-color: transparent;" width="444" valign="top">
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style="">若成功返回</span>
<span lang="EN-US"><span>0</span>
</span>
<span style="">,若失败返回错误编号。</span>
</span>
</p>
</td>
</tr>
</tbody></table>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span></span>
</span>
</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"></span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span></span>
</span>
<span style="">对于记录锁,</span>
<span lang="EN-US"><span>cmd</span>
</span>
<span style="">是</span>
<span lang="EN-US"><span>F_GETLK,F_SETLKW</span>
</span>
<span style="">或</span>
<span lang="EN-US"><span>F_SETLKW.</span>
</span>
<span style="">。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
F_GETLK</span>
</span>
<span style="">判断由</span>
<span lang="EN-US"><span>flockptr</span>
</span>
<span style="">所描述的锁是否会被另外一把锁排斥。如果存在一把锁,他阻止创建由</span>
<span lang="EN-US"><span>flockptr</span>
</span>
<span style="">所描述的锁,则把该现存锁的信息写到</span>
<span lang="EN-US"><span>flockptr</span>
</span>
<span style="">指向的结构中。如果不存在这种情况除了将</span>
<span lang="EN-US"><span>l_type</span>
</span>
<span style="">设置为</span>
<span lang="EN-US"><span>F_UNLCK</span>
</span>
<span style="">之外,</span>
<span lang="EN-US"><span>flockptr</span>
</span>
<span style="">所描述的其他信息都不变。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span>F_SETLK</span>
</span>
<span style="">和</span>
<span lang="EN-US"><span>F_SETLKW</span>
</span>
<span style="">企图建立一把锁。</span>
<span lang="EN-US"><span>F_SETLK</span>
</span>
<span style="">和</span>
<span lang="EN-US"><span>F_SETLKW</span>
</span>
<span style="">的区别是</span>
<span lang="EN-US"><span>F_SETLKW</span>
</span>
<span style="">是</span>
<span lang="EN-US"><span>F_SETLK</span>
</span>
<span style="">的阻塞版本。如果存在其他锁,调用的进程就被阻塞直道捕捉到信号。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
</span>
</span>
<span style="">第三个参数是一个指向</span>
<span lang="EN-US"><span>flock</span>
</span>
<span style="">结构的指针:</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small;">struct flock{</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small;"><span><span> </span>
short l_type; /*F_RDLCK,F_WRLCK,F_UNLCK*/</span>
</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
off_t l_start; /*</span>
</span>
<span style="">加锁的地址</span>
<span lang="EN-US"><span>*/</span>
</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
shout l_whence; /*</span>
</span>
<span style="">加锁的偏移地址</span>
<span lang="EN-US"><span>*/</span>
</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
off_t l_len; /*</span>
</span>
<span style="">加锁区域的长度</span>
<span lang="EN-US"><span>*/</span>
</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
pid_t l_pid; /*</span>
</span>
<span style="">持有锁的进程</span>
<span lang="EN-US"><span>ID*/</span>
</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span lang="EN-US"><span style="font-size: small;">};</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span>flock</span>
</span>
<span style="">结构说明:</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">所希望的锁类型:</span>
<span lang="EN-US"><span>F_RDLCK(</span>
</span>
<span style="">共享读锁</span>
<span lang="EN-US"><span>)</span>
</span>
<span style="">、</span>
<span lang="EN-US"><span>F_WRLCK(</span>
</span>
<span style="">独占性写锁</span>
<span lang="EN-US"><span>)</span>
</span>
<span style="">、</span>
<span lang="EN-US"><span>F_UNLCK(</span>
</span>
<span style="">解锁一个区域</span>
<span lang="EN-US"><span>)</span>
</span>
<span style="">,这是由</span>
<span> <span lang="EN-US">l_type</span>
</span>
<span style="">决定的。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">要加锁或解锁区域的起始字节偏移量,这是由</span>
<span lang="EN-US"><span>l_statt</span>
</span>
<span style="">和</span>
<span lang="EN-US"><span>l_whence</span>
</span>
<span style="">两者决定。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">区域的字节长度,由</span>
<span lang="EN-US"><span>l_len</span>
</span>
<span style="">表示。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="">具有能阻塞当前进程的锁,其持有的</span>
<span lang="EN-US"><span>ID</span>
</span>
<span style="">存放在</span>
<span lang="EN-US"><span>l_pid</span>
</span>
<span style="">中。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
</span>
</span>
<span style="">如若</span>
<span lang="EN-US"><span>l_len</span>
</span>
<span style="">为</span>
<span lang="EN-US"><span>0</span>
</span>
<span style="">,则表示锁的区域从其起点(由</span>
<span lang="EN-US"><span>l_start</span>
</span>
<span style="">和</span>
<span lang="EN-US"><span>l_whence</span>
</span>
<span style="">决定)开始直至最大可能位置为止。也就是不管添写到该文件中多少数据,它都处于的范围。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
</span>
</span>
<span style="">如果想锁住整个文件,通常的方法是将</span>
<span lang="EN-US"><span>l_start</span>
</span>
<span style="">说明为</span>
<span lang="EN-US"><span>0</span>
</span>
<span style="">,</span>
<span lang="EN-US"><span>l_whence</span>
</span>
<span style="">说明为</span>
<span lang="EN-US"><span>SEEK_SET</span>
</span>
<span style="">,</span>
<span lang="EN-US"><span>1_len</span>
</span>
<span style="">说明为</span>
<span lang="EN-US"><span>0</span>
</span>
<span style="">。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span> </span>
</span>
</span>
<span style="">还要注意的是,对文件加共享读锁时文件应以只读的方式打开,对文件加独占写锁时文件应以只读的方式打开。</span>
</span>
</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span style=""><br></span>
</span>
</p>
</div>

你可能感兴趣的:(linux)