<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Soul Of Free Loop &#187; 建议锁</title>
	<atom:link href="https://zohead.com/archives/tag/advisory-lock/feed" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>Linux下fcntl实现建议锁和强制锁</title>
		<link>https://zohead.com/archives/linux-fcntl-advisory-mandatory-lock/</link>
		<comments>https://zohead.com/archives/linux-fcntl-advisory-mandatory-lock/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 17:17:31 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[fcntl]]></category>
		<category><![CDATA[flock]]></category>
		<category><![CDATA[lockf]]></category>
		<category><![CDATA[建议锁]]></category>
		<category><![CDATA[强制锁]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=78</guid>
		<description><![CDATA[近日小温下APUE，发现Linux下的 fcntl 实现强制锁的功能好像都没试验过，简单做个测试。 首先用 fcntl 实现建议锁（Advisory locking），比较简单，贴个最简单的代码： 关键的几句已高亮显示，用 F_SETLKW 等待写的锁，很好测试，分别开一个终端运行一次就可以测试出来。 Linux 同时实现了 POSIX 的 fcntl 锁函数，BSD 的 flock 函数，SVR4 的 lockf 函数，这些默认都是建议锁。 这个简单的实现只是建议锁，需要每个对文件的操作的进程都遵循同样的锁操作才能起作用，这些进程称为合作进程（Cooperative processes），但 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>近日小温下APUE，发现Linux下的 fcntl 实现强制锁的功能好像都没试验过，简单做个测试。</p>
<p>首先用 fcntl 实现建议锁（Advisory locking），比较简单，贴个最简单的代码：</p>
<pre class="brush: cpp; highlight: [13,14,15,16,20]; title: cat &gt; test.c; notranslate">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;unistd.h&gt;

int main(int argc, char ** argv)
{
	int fd = 0, ret = 0;
	struct flock lock = {0};

	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;

	fd = open(&quot;test.file&quot;, O_RDWR | O_CREAT);
	printf(&quot;before flock\n&quot;);
	ret = fcntl(fd, F_SETLKW, &amp;lock);
	printf(&quot;after flock, ret: %d\n&quot;, ret);
	getchar();
	close(fd);

	return 0;
}
</pre>
<p>关键的几句已高亮显示，用 F_SETLKW 等待写的锁，很好测试，分别开一个终端运行一次就可以测试出来。</p>
<p>Linux 同时实现了 POSIX 的 fcntl 锁函数，BSD 的 flock 函数，SVR4 的 lockf 函数，这些默认都是建议锁。</p>
<p>这个简单的实现只是建议锁，需要每个对文件的操作的进程都遵循同样的锁操作才能起作用，这些进程称为合作进程（Cooperative processes），但实际使用时会有例外的情况，如果另外开一个终端窗口直接写 test.file 文件，会发现可以直接写，因为这种写没有锁操作，不是合作进程，这种情况就需要用强制锁（Mandatory locking）了。</p>
<p>强制锁的实际代码和上面的完全一样，不过在 Linux 上需要做一些改动：</p>
<ol>
<li>挂载文件系统时需要加 mand 参数在文件系统上启用强制锁支持，比较新的 Linux kernel 里已经基本在所有文件系统上都实现了；</li>
<li>去掉程序的组执行权限；</li>
<li>增加程序的设置组ID权限。</li>
</ol>
<p>第二项和第三项在普通情况下实际上是自相矛盾的，所以 Linux 就用这种特殊情况就表示启用强制锁（Mandatory locking）了。</p>
<blockquote>
<p><strong>备注</strong></p>
<ol>
<li>使用 BSD 的 flock 函数时不能使用强制锁，见 Linux kernel 源码下 mandatory-locking.txt 中的说明：<br />
	Mandatory locks can only be applied via the fcntl()/lockf() locking<br />
	interface - in other words the System V/POSIX interface. BSD style<br />
	locks using flock() never result in a mandatory lock.</li>
<li>如果一个文件被某进程强制锁住，另一个进程通过 creat 函数或者 open 时加 O_TRUNC 参数，都会导致函数调用失败；</li>
<li>强制锁在不同的 UNIX 及 类UNIX 系统中实现不同，第二个备注中的 O_TRUNC 参数便是 Linux kernel 和 HP-UX 不同的地方；</li>
<li>tmpfs、nfs 也支持强制锁，可以用这两个文件系统方便测试；</li>
<li>删除文件（unlink操作）再重新创建文件，会导致强制锁失效；</li>
<li>Linux kernel 的强制锁的实现并不完全可靠（感觉白写了，哈哈，实际情况还要做处理），见 man fcntl 的说明。</li>
</ol>
</blockquote>
<p>强制锁的实际操作：</p>
<pre class="brush: bash; title: ; notranslate">
mount -t tmpfs -o size=10m,mand tmpfs /mnt
cp test /mnt
cd /mnt
chmod g-x test
chmod g+s test
</pre>
<p>运行 test 程序，同时开另一个终端，直接用 echo 读写 test 文件，会发现强制锁已经起作用。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/linux-fcntl-advisory-mandatory-lock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
