<?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>kafka0102的边城客栈 &#187; flock</title>
	<atom:link href="http://www.kafka0102.com/tag/flock/feed" rel="self" type="application/rss+xml" />
	<link>http://www.kafka0102.com</link>
	<description>要有最朴素的生活与最遥远的梦想，即使明日天寒地冻、路远马亡。</description>
	<lastBuildDate>Sat, 18 Jun 2011 04:20:42 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>使用记录锁实现进程间锁</title>
		<link>http://www.kafka0102.com/2010/02/50.html</link>
		<comments>http://www.kafka0102.com/2010/02/50.html#comments</comments>
		<pubDate>Fri, 12 Feb 2010 09:40:27 +0000</pubDate>
		<dc:creator>kafka0102</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[flock]]></category>
		<category><![CDATA[记录锁]]></category>
		<category><![CDATA[进程间锁]]></category>

		<guid isPermaLink="false">http://www.kafka0102.com/?p=50</guid>
		<description><![CDATA[在一篇比较lightty和nginx实现机制的文章中提到，nginx相比于lightty，在多work进程accept时做了加锁处理，对于linux2.4之前的版本，不加锁会出现“惊群现象”。之前也隐约记得，apache对多进程的accept也是做了加锁处理。对这方面不是很熟悉，所以就翻看nginx代码查找加锁的实现代码，最后确认是使用的文件记录锁（record lock），APUE上有详细说明，这里只简单的摘取说明。]]></description>
			<content:encoded><![CDATA[<p>在一篇比较lightty和nginx实现机制的文章中提到，nginx相比于lightty，在多work进程accept时做了加锁处理，对于linux2.4之前的版本，不加锁会出现“惊群现象”。之前也隐约记得，apache对多进程的accept也是做了加锁处理。对这方面不是很熟悉，所以就翻看nginx代码查找加锁的实现代码，最后确认是使用的文件记录锁（record lock），APUE上有详细说明，这里只简单的摘取说明。</p>
<p>加锁解锁的系统接口是：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">fcntl<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> fd<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> cmd<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> flock <span style="color: #339933;">*</span>flockptr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>其中cmd 为F_GETLK、 F_SETLK（非阻塞加锁） 或 F_SETLKW（阻塞加锁）， flockptr 指向 flock结构。flock结构如下：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> flcok <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #993333;">short</span> <span style="color: #993333;">int</span> l_type<span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* 锁定的状态*/</span>
&nbsp;
<span style="color: #993333;">short</span> <span style="color: #993333;">int</span> l_whence<span style="color: #339933;">;</span><span style="color: #808080; font-style: italic;">/*决定l_start位置*/</span>
&nbsp;
off_t l_start<span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/*锁定区域的开头位置*/</span>
&nbsp;
off_t l_len<span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/*锁定区域的大小*/</span>
&nbsp;
pid_t l_pid<span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/*锁定动作的进程*/</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>l_type 有三种状态：1）F_RDLCK 建立一个供读取用的锁定，2）F_WRLCK 建立一个供写入用的锁定，3）F_UNLCK 删除之前建立的锁定。</p>
<p>对于nginx accept加排他锁，需要设置l_whence=SEEK_SET、l_start=0、l_len=0。</p>
<p>加锁和解锁函数类似于：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span>  lock_file<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> fd<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #993333;">struct</span> flock s_flock<span style="color: #339933;">;</span>
&nbsp;
s_flock.<span style="color: #202020;">l_type</span> <span style="color: #339933;">=</span> F_WRLCK<span style="color: #339933;">;</span>
&nbsp;
s_flock.<span style="color: #202020;">l_whence</span> <span style="color: #339933;">=</span> SEEK_SET<span style="color: #339933;">;</span>
&nbsp;
s_flock.<span style="color: #202020;">l_start</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
s_flock.<span style="color: #202020;">l_len</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
s_flock.<span style="color: #202020;">l_pid</span> <span style="color: #339933;">=</span> getpid<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">return</span> fcntl<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> F_SETLKW<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;</span>s_flock<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span>  unlock_file<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> fd<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #b1b100;">return</span> fcntl<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> F_SETLKW<span style="color: #339933;">,</span> F_UNLCK<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Nginx中accpet锁变量是ngx_accept_mutex，nginx会在主进程初始化event module时调用ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name)来初始化锁。该函数一个有意思的地方是，在open锁文件得到fd后，nginx又调用unlink删掉文件，实际上并不存在这样一个实体的锁文件，而后各work进程共用该fd来做加锁解锁操作。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kafka0102.com/2010/02/50.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

