<?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>Yoichi Kawasaki&#039;s Web &#187; kernel</title>
	<atom:link href="http://yk55.com/blog/tags/kernel/feed/" rel="self" type="application/rss+xml" />
	<link>http://yk55.com/blog</link>
	<description>the place to organize and record my ideas ...</description>
	<lastBuildDate>Sun, 05 Feb 2012 15:16:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<!-- google_ad_section_end --><!-- google_ad_section_start(weight=ignore) -->	<item>
		<title>Scatter/Gather I/O(readv/writev)の実装</title>
		<link>http://yk55.com/blog/2010/01/31/readv_writev_implementation/</link>
		<comments>http://yk55.com/blog/2010/01/31/readv_writev_implementation/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 02:03:15 +0000</pubDate>
		<dc:creator>yoichi</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://yk55.com/blog/?p=86</guid>
		<description><![CDATA[readv、writevは複数バッファをまとめて読み書きするシステムコールです。 writevはiovec 構造体の配列に書き込みたいものを突っ込んでまとめてその複数バッファーを書き込み、readvは指定した個数分の複数バッファーをiovec 構造体の配列に格納します。例えばwritevによる複数バッファの書き込みはこんな感じです。 #include &#60;stdio.h&#62; #include &#60;unistd.h&#62; #include &#60;fcntl.h&#62; #include &#60;string.h&#62; #include &#60;sys/uio.h&#62; int &#160;main&#40; int argc, char** argv &#41; &#123; &#160; &#160; int fd = 0; &#160; &#160; ssize_t written; &#160; &#160; struct iovec iov&#91;3&#93;; &#160; &#160; char *buffer0, *buffer1, *buffer2; &#160; &#160; char *file = argv&#91;1&#93;; &#160; &#160; fd = open&#40; file, [...]]]></description>
			<content:encoded><![CDATA[<p>readv、writevは複数バッファをまとめて読み書きするシステムコールです。 writevはiovec 構造体の配列に書き込みたいものを突っ込んでまとめてその複数バッファーを書き込み、readvは指定した個数分の複数バッファーをiovec 構造体の配列に格納します。例えばwritevによる複数バッファの書き込みはこんな感じです。</p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;stdio.h&gt;</span><br />
<span style="color: #339933;">#include &lt;unistd.h&gt;</span><br />
<span style="color: #339933;">#include &lt;fcntl.h&gt; </span><br />
<span style="color: #339933;">#include &lt;string.h&gt;</span><br />
<span style="color: #339933;">#include &lt;sys/uio.h&gt;</span><br />
<span style="color: #993333;">int</span> <br />
&nbsp;main<span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span><span style="color: #339933;">**</span> argv <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">int</span> fd <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; ssize_t written<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> iovec iov<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">3</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buffer0<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>buffer1<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>buffer2<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>file <span style="color: #339933;">=</span> argv<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span> file<span style="color: #339933;">,</span> &nbsp;O_RDWR<span style="color: #339933;">|</span>O_CREAT<span style="color: #339933;">|</span>O_EXCL<span style="color: #339933;">,</span> <span style="color: #208080;">0666</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> fd <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span style="color: #000066;">printf</span></a><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;cannot open file:%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> file<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; buffer0 <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;buffer0 string&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; buffer1 <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;buffer1 string&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; buffer2 <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;buffer2 string&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; iov<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">iov_base</span> <span style="color: #339933;">=</span> buffer0<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; iov<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">iov_len</span> <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span>buffer0<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; iov<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">iov_base</span> <span style="color: #339933;">=</span> buffer1<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; iov<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">iov_len</span> <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span>buffer1<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; iov<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">iov_base</span> <span style="color: #339933;">=</span> buffer2<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; iov<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #009900;">&#93;</span>.<span style="color: #202020;">iov_len</span> <span style="color: #339933;">=</span> strlen<span style="color: #009900;">&#40;</span>buffer2<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; written <span style="color: #339933;">=</span> writev<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> iov<span style="color: #339933;">,</span> <span style="color: #0000dd;">3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; close<span style="color: #009900;">&#40;</span>fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p><span style="text-decoration: underline;">※iovec 構造体の定義 </span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/* Structure for scatter/gather I/O. &nbsp;*/</span><br />
<span style="color: #993333;">struct</span> iovec<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>iov_base<span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* Pointer to data. &nbsp;*/</span><br />
&nbsp; &nbsp;size_t iov_len<span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* Length of data. &nbsp;*/</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></div>
<p><a href="http://www.linux.or.jp/JM/html/LDP_man-pages/man2/readv.2.html">man</a>によると基本的にはこのシステムコールの特徴は次の2つです。</p>
<ol>
<li>1.  readv、writevともに複数のバッファにデータを読み込む点を除いてそれぞれread(2)、write(2)と全く同様の動作を行う。</li>
<li>2.  readvと writevともにatomic。writevによるデータ書き込み中に他のスレッド、プロセスのwrite による割り込みが入らない。readvも同様にファイルから連続するデータブロックが読み出すことを保証。 </li>
</ol>
<p>本当にこのシステムコールが上記のような実装になっているのか確かめるために実際にソースコードを覗いてみます。readv、writevでは内部で次のdo_readv_writev関数がコールされます。</p>
<p><span style="text-decoration: underline;">do_readv_writev @ linux-2.6.12.1/fs/read_write.c</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">static</span> ssize_t do_readv_writev<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> type<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> file <span style="color: #339933;">*</span>file<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333;">const</span> <span style="color: #993333;">struct</span> iovec __user <span style="color: #339933;">*</span> uvector<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333;">unsigned</span> <span style="color: #993333;">long</span> nr_segs<span style="color: #339933;">,</span> loff_t <span style="color: #339933;">*</span>pos<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #202020;">ret</span> <span style="color: #339933;">=</span> rw_verify_area<span style="color: #009900;">&#40;</span>type<span style="color: #339933;">,</span> file<span style="color: #339933;">,</span> pos<span style="color: #339933;">,</span> tot_len<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">goto</span> out<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fnv <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>type <span style="color: #339933;">==</span> READ<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fn <span style="color: #339933;">=</span> file<span style="color: #339933;">-&gt;</span>f_op<span style="color: #339933;">-&gt;</span>read<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fnv <span style="color: #339933;">=</span> file<span style="color: #339933;">-&gt;</span>f_op<span style="color: #339933;">-&gt;</span>readv<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fn <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>io_fn_t<span style="color: #009900;">&#41;</span>file<span style="color: #339933;">-&gt;</span>f_op<span style="color: #339933;">-&gt;</span>write<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fnv <span style="color: #339933;">=</span> file<span style="color: #339933;">-&gt;</span>f_op<span style="color: #339933;">-&gt;</span>writev<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>fnv<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">=</span> fnv<span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> iov<span style="color: #339933;">,</span> nr_segs<span style="color: #339933;">,</span> pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">goto</span> out<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/* Do it by hand, with file-ops */</span><br />
&nbsp; &nbsp; ret <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; vector <span style="color: #339933;">=</span> iov<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>nr_segs <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333;">void</span> __user <span style="color: #339933;">*</span> base<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; size_t len<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ssize_t nr<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; base <span style="color: #339933;">=</span> vector<span style="color: #339933;">-&gt;</span>iov_base<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; len <span style="color: #339933;">=</span> vector<span style="color: #339933;">-&gt;</span>iov_len<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; vector<span style="color: #339933;">++;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; nr_segs<span style="color: #339933;">--;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; nr <span style="color: #339933;">=</span> fn<span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> base<span style="color: #339933;">,</span> len<span style="color: #339933;">,</span> pos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>nr <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>ret<span style="color: #009900;">&#41;</span> ret <span style="color: #339933;">=</span> nr<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ret <span style="color: #339933;">+=</span> nr<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>nr <span style="color: #339933;">!=</span> len<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; ...<br />
<span style="color: #009900;">&#125;</span></div></div>
<p>後半のwhileブロックを見るとたしかにreadv、writevのときそれぞれ内部でread、writeがループで繰り返されています。 想像を超えたシンプルさでした。次にatomicを保障している箇所ですがREADかWRITEのtypeチェックを行う前のrw_verify_areaがそれっぽい。ということでrw_verify_areaを覗いてみます。</p>
<p><span style="text-decoration: underline;">rw_verify_area @ linux-2.6.12.1/fs/read_write.c</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333;">int</span> rw_verify_area<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> read_write<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> file <span style="color: #339933;">*</span>file<span style="color: #339933;">,</span> loff_t <span style="color: #339933;">*</span>ppos<span style="color: #339933;">,</span> size_t count<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> inode <span style="color: #339933;">*</span>inode<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; loff_t pos<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>unlikely<span style="color: #009900;">&#40;</span>count <span style="color: #339933;">&gt;</span> file<span style="color: #339933;">-&gt;</span>f_maxcount<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">goto</span> Einval<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; pos <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>ppos<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>unlikely<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>pos <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>loff_t<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span>pos <span style="color: #339933;">+</span> count<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">goto</span> Einval<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; inode <span style="color: #339933;">=</span> file<span style="color: #339933;">-&gt;</span>f_dentry<span style="color: #339933;">-&gt;</span>d_inode<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>inode<span style="color: #339933;">-&gt;</span>i_flock <span style="color: #339933;">&amp;&amp;</span> MANDATORY_LOCK<span style="color: #009900;">&#40;</span>inode<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> locks_mandatory_area<span style="color: #009900;">&#40;</span>read_write <span style="color: #339933;">==</span> READ <span style="color: #339933;">?</span> FLOCK_VERIFY_READ <span style="color: #339933;">:</span> FLOCK_VERIFY_WRITE<span style="color: #339933;">,</span> inode<span style="color: #339933;">,</span> file<span style="color: #339933;">,</span> pos<span style="color: #339933;">,</span> count<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<br />
Einval<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span>EINVAL<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>ここではファイルの読み込み・書き込みエリアのバリデーションチェックとlocks_mandatory_areaで排他チェックを行っています。念のためlocks_mandatory_areaを覗いてみます。</p>
<p><span style="text-decoration: underline;">locks_mandatory_area @ linux-2.6.12.1/fs/locks.c</span></p>
<div class="codecolorer-container c mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">/**<br />
&nbsp;* locks_mandatory_area - Check for a conflicting lock<br />
&nbsp;* @read_write: %FLOCK_VERIFY_WRITE for exclusive access, %FLOCK_VERIFY_READ<br />
&nbsp;* &nbsp; &nbsp; &nbsp;for shared<br />
&nbsp;* @inode: &nbsp; &nbsp; &nbsp;the file to check<br />
&nbsp;* @filp: &nbsp; &nbsp; &nbsp; how the file was opened (if it was)<br />
&nbsp;* @offset: &nbsp; &nbsp; start of area to check<br />
&nbsp;* @count: &nbsp; &nbsp; &nbsp;length of area to check<br />
&nbsp;*<br />
&nbsp;* Searches the inode's list of locks to find any POSIX locks which conflict.<br />
&nbsp;* This function is called from rw_verify_area() and<br />
&nbsp;* locks_verify_truncate().<br />
&nbsp;*/</span><br />
<span style="color: #993333;">int</span> locks_mandatory_area<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> read_write<span style="color: #339933;">,</span> <span style="color: #993333;">struct</span> inode <span style="color: #339933;">*</span>inode<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333;">struct</span> file <span style="color: #339933;">*</span>filp<span style="color: #339933;">,</span> loff_t offset<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;size_t count<span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">struct</span> file_lock fl<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">int</span> error<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; locks_init_lock<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>fl<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fl.<span style="color: #202020;">fl_owner</span> <span style="color: #339933;">=</span> current<span style="color: #339933;">-&gt;</span>files<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fl.<span style="color: #202020;">fl_pid</span> <span style="color: #339933;">=</span> current<span style="color: #339933;">-&gt;</span>tgid<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fl.<span style="color: #202020;">fl_file</span> <span style="color: #339933;">=</span> filp<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fl.<span style="color: #202020;">fl_flags</span> <span style="color: #339933;">=</span> FL_POSIX <span style="color: #339933;">|</span> FL_ACCESS<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>filp <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>filp<span style="color: #339933;">-&gt;</span>f_flags <span style="color: #339933;">&amp;</span> O_NONBLOCK<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; fl.<span style="color: #202020;">fl_flags</span> <span style="color: #339933;">|=</span> FL_SLEEP<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fl.<span style="color: #202020;">fl_type</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>read_write <span style="color: #339933;">==</span> FLOCK_VERIFY_WRITE<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> F_WRLCK <span style="color: #339933;">:</span> F_RDLCK<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fl.<span style="color: #202020;">fl_start</span> <span style="color: #339933;">=</span> offset<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; fl.<span style="color: #202020;">fl_end</span> <span style="color: #339933;">=</span> offset <span style="color: #339933;">+</span> count <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">;;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; error <span style="color: #339933;">=</span> __posix_lock_file<span style="color: #009900;">&#40;</span>inode<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>fl<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>error <span style="color: #339933;">!=</span> <span style="color: #339933;">-</span>EAGAIN<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>fl.<span style="color: #202020;">fl_flags</span> <span style="color: #339933;">&amp;</span> FL_SLEEP<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; error <span style="color: #339933;">=</span> wait_event_interruptible<span style="color: #009900;">&#40;</span>fl.<span style="color: #202020;">fl_wait</span><span style="color: #339933;">,</span> <span style="color: #339933;">!</span>fl.<span style="color: #202020;">fl_next</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>error<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">/*<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* If we've been sleeping someone might have<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* changed the permissions behind our back.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>inode<span style="color: #339933;">-&gt;</span>i_mode <span style="color: #339933;">&amp;</span> <span style="color: #009900;">&#40;</span>S_ISGID <span style="color: #339933;">|</span> S_IXGRP<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> S_ISGID<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; locks_delete_block<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>fl<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> error<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p><span style="text-decoration: underline;">※ kernelソースコード<a href="http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.12.1.tar.gz">linux-2.6.12.1</a></span> </p>
<p>以上、簡単ではありますがreadv、writevの実装でした。 このシステムコールはこれまで何度か業務で利用していておなじみな物のではありましたが特に内部の実装を気にすることなく使ってました。実際に見てみると単純な複数バッファ分のread, writeの繰り返しではありますがその処理間に排他制御がしっかりされているのでパフォーマンスはさておき安心して使えると思います。その辺の自分で実装するのは面倒ですから。</p>
<iframe src="http://www.facebook.com/plugins/like.php?href=http://yk55.com/blog/2010/01/31/readv_writev_implementation/&amp;layout=button_count&amp;show_faces=1&amp;width=450&amp;action=like&amp;colorscheme=light&amp;font=arial" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:25px"></iframe>]]></content:encoded>
			<wfw:commentRss>http://yk55.com/blog/2010/01/31/readv_writev_implementation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	<!-- google_ad_section_end --><!-- google_ad_section_start(weight=ignore) --></channel>
</rss>

