<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>mojavy.com</title>
    <link>http://mojavy.com/blog</link>
    <description></description>
    <pubDate>Tue, 18 Mar 2014 21:41:12 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>pthreadの取り消しポイント(cancellation point)についてのメモ</title>
      <link>http://mojavy.com/blog/2014/03/18/pthread-cancellation-point/</link>
      <pubDate>Tue, 18 Mar 2014 21:41:12 JST</pubDate>
      <category><![CDATA[unix]]></category>
      <category><![CDATA[programming]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2014/03/18/pthread-cancellation-point/</guid>
      <description>pthreadの取り消しポイント(cancellation point)についてのメモ</description>
      <content:encoded><![CDATA[<p>cancellation pointsとは、スレッドのキャンセル種別が<code>deferred</code>のときに、そこに到達したときにはじめて実際にそのスレッドのキャンセル要求が処理されるような関数のこと。</p>
<p>POSIX.1では、基本的にはブロックするような関数がcancellation pointsであることが要求されている。</p>
<h2 id="_1">参考</h2>
<ul>
<li><a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html">http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html</a> </li>
<li><a href="http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/pthread_cancel.3.html">pthread_cancel(3)</a> </li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>スレッドプールの実装方法について</title>
      <link>http://mojavy.com/blog/2014/03/03/implementing-thread-pool/</link>
      <pubDate>Mon, 03 Mar 2014 20:58:58 JST</pubDate>
      <category><![CDATA[unix]]></category>
      <category><![CDATA[programming]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2014/03/03/implementing-thread-pool/</guid>
      <description>スレッドプールの実装方法について</description>
      <content:encoded><![CDATA[<p>スレッドプール(thread pool)を実装するには、暇なときはthreadを寝かせておいて必要なときに起こす、というイベント通知の仕組みが必要になる。
UnixでC/C++で実装するときはpthreadの条件変数を使うのが普通だと思われるが、適当なファイルディスクリプタをopenしておいてread等でブロックさせる方法でも実装できそう。</p>
<p>どのようなやり方が一般的なのか、いくつか有名どころのOSSの実装を調べてみた。</p>
<h3 id="libuv">libuvの場合</h3>
<p><a href="https://github.com/joyent/libuv">https://github.com/joyent/libuv</a> </p>
<p>単純に<code>pthread_cond_wait</code>をつかっている <sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> </p>
<div class="pygments_borland"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">worker</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">arg</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">struct</span> <span class="n">uv__work</span><span class="o">*</span> <span class="n">w</span><span class="p">;</span>
  <span class="n">QUEUE</span><span class="o">*</span> <span class="n">q</span><span class="p">;</span>

  <span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="n">arg</span><span class="p">;</span>

  <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
    <span class="n">uv_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>

    <span class="k">while</span> <span class="p">(</span><span class="n">QUEUE_EMPTY</span><span class="p">(</span><span class="o">&amp;</span><span class="n">wq</span><span class="p">))</span>
      <span class="n">uv_cond_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>

    <span class="n">q</span> <span class="o">=</span> <span class="n">QUEUE_HEAD</span><span class="p">(</span><span class="o">&amp;</span><span class="n">wq</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">q</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">exit_message</span><span class="p">)</span>
      <span class="n">uv_cond_signal</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cond</span><span class="p">);</span>
    <span class="k">else</span> <span class="p">{</span>
      <span class="n">QUEUE_REMOVE</span><span class="p">(</span><span class="n">q</span><span class="p">);</span>
      <span class="n">QUEUE_INIT</span><span class="p">(</span><span class="n">q</span><span class="p">);</span>  <span class="cm">/* Signal uv_cancel() that the work req is</span>
<span class="cm">                             executing. */</span>
    <span class="p">}</span>

    <span class="n">uv_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">);</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">q</span> <span class="o">==</span> <span class="o">&amp;</span><span class="n">exit_message</span><span class="p">)</span>
      <span class="k">break</span><span class="p">;</span>

    <span class="n">w</span> <span class="o">=</span> <span class="n">QUEUE_DATA</span><span class="p">(</span><span class="n">q</span><span class="p">,</span> <span class="k">struct</span> <span class="n">uv__work</span><span class="p">,</span> <span class="n">wq</span><span class="p">);</span>
    <span class="n">w</span><span class="o">-&gt;</span><span class="n">work</span><span class="p">(</span><span class="n">w</span><span class="p">);</span>

    <span class="n">uv_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">w</span><span class="o">-&gt;</span><span class="n">loop</span><span class="o">-&gt;</span><span class="n">wq_mutex</span><span class="p">);</span>
    <span class="n">w</span><span class="o">-&gt;</span><span class="n">work</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>  <span class="cm">/* Signal uv_cancel() that the work req is done</span>
<span class="cm">                        executing. */</span>
    <span class="n">QUEUE_INSERT_TAIL</span><span class="p">(</span><span class="o">&amp;</span><span class="n">w</span><span class="o">-&gt;</span><span class="n">loop</span><span class="o">-&gt;</span><span class="n">wq</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">w</span><span class="o">-&gt;</span><span class="n">wq</span><span class="p">);</span>
    <span class="n">uv_async_send</span><span class="p">(</span><span class="o">&amp;</span><span class="n">w</span><span class="o">-&gt;</span><span class="n">loop</span><span class="o">-&gt;</span><span class="n">wq_async</span><span class="p">);</span>
    <span class="n">uv_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">w</span><span class="o">-&gt;</span><span class="n">loop</span><span class="o">-&gt;</span><span class="n">wq_mutex</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</pre></div>

<h3 id="boostasio">Boost.Asioの場合</h3>
<p><a href="http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio.html">http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio.html</a> </p>
<p><code>Boost.Asio</code>にスレッドプールそのものは提供されてないが以下のようにして簡単に実装することができる</p>
<div class="pygments_borland"><pre><span class="cp">#include &lt;thread&gt;</span>
<span class="cp">#include &lt;functional&gt;</span>
<span class="cp">#include &lt;boost/asio.hpp&gt;</span>

<span class="kt">int</span> <span class="n">main</span> <span class="p">(</span> <span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[]</span> <span class="p">)</span> <span class="p">{</span>
    <span class="n">asio</span><span class="o">::</span><span class="n">io_service</span> <span class="n">io_service</span><span class="p">;</span>
    <span class="n">asio</span><span class="o">::</span><span class="n">io_service</span><span class="o">::</span><span class="n">work</span> <span class="n">work</span><span class="p">(</span><span class="n">io_service</span><span class="p">);</span>

    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="o">&gt;</span> <span class="n">threadPool</span><span class="p">;</span>

    <span class="k">for</span><span class="p">(</span><span class="n">size_t</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">t</span> <span class="o">&lt;</span> <span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="o">::</span><span class="n">hardware_concurrency</span><span class="p">();</span> <span class="n">t</span><span class="o">++</span><span class="p">){</span>
        <span class="n">threadPool</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="kr">thread</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">(</span><span class="o">&amp;</span><span class="n">asio</span><span class="o">::</span><span class="n">io_service</span><span class="o">::</span><span class="n">run</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">io_service</span><span class="p">)));</span>
    <span class="p">}</span>

    <span class="n">io_service</span><span class="p">.</span><span class="n">post</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">(</span><span class="n">an_expensive_calculation</span><span class="p">,</span> <span class="mi">42</span><span class="p">));</span>
    <span class="n">io_service</span><span class="p">.</span><span class="n">post</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">bind</span><span class="p">(</span><span class="n">a_long_running_task</span><span class="p">,</span> <span class="mi">123</span><span class="p">));</span>

    <span class="c1">//Do some things with the main thread</span>

    <span class="n">io_service</span><span class="p">.</span><span class="n">stop</span><span class="p">();</span>
    <span class="k">for</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="o">&amp;</span> <span class="n">t</span> <span class="o">:</span> <span class="n">threadPool</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">t</span><span class="p">.</span><span class="n">join</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><a href="http://stackoverflow.com/questions/14265676/using-boostasio-thread-pool-for-general-purpose-tasks">http://stackoverflow.com/questions/14265676/using-boostasio-thread-pool-for-general-purpose-tasks</a> </p>
<p>長くなるのでコードは省略するが、<code>io_service::post</code>するとunixの場合は最終的には<code>task_io_service::wake_one_idle_thread_and_unlock</code>から<code>pthread_cond_signal</code>が呼ばれる。</p>
<h3 id="memcached">memcachedの場合</h3>
<p><a href="https://github.com/memcached/memcached">https://github.com/memcached/memcached</a> </p>
<p><code>libevent</code>のイベント通知機能を利用して実装している。それぞれのthread初期化の際にpipeをつくって、そのfdをlibeventに渡す。 <sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>  libevent内部でそのfdを<code>epoll</code>なり<code>kqueue</code>なりでブロックして待つ。</p>
<div class="pygments_borland"><pre><span class="c1">//</span>
<span class="c1">// memcached.c</span>
<span class="c1">//</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
    <span class="n">pthread_t</span> <span class="n">thread_id</span><span class="p">;</span>        <span class="cm">/* unique ID of this thread */</span>
    <span class="k">struct</span> <span class="n">event_base</span> <span class="o">*</span><span class="n">base</span><span class="p">;</span>    <span class="cm">/* libevent handle this thread uses */</span>
    <span class="k">struct</span> <span class="n">event</span> <span class="n">notify_event</span><span class="p">;</span>  <span class="cm">/* listen event for notify pipe */</span>
    <span class="kt">int</span> <span class="n">notify_receive_fd</span><span class="p">;</span>      <span class="cm">/* receiving end of notify pipe */</span>
    <span class="kt">int</span> <span class="n">notify_send_fd</span><span class="p">;</span>         <span class="cm">/* sending end of notify pipe */</span>
    <span class="k">struct</span> <span class="n">thread_stats</span> <span class="n">stats</span><span class="p">;</span>  <span class="cm">/* Stats generated by this thread */</span>
    <span class="k">struct</span> <span class="n">conn_queue</span> <span class="o">*</span><span class="n">new_conn_queue</span><span class="p">;</span> <span class="cm">/* queue of new connections to handle */</span>
    <span class="n">cache_t</span> <span class="o">*</span><span class="n">suffix_cache</span><span class="p">;</span>      <span class="cm">/* suffix cache */</span>
    <span class="kt">uint8_t</span> <span class="n">item_lock_type</span><span class="p">;</span>     <span class="cm">/* use fine-grained or global item lock */</span>
<span class="p">}</span> <span class="n">LIBEVENT_THREAD</span><span class="p">;</span>

<span class="c1">//</span>
<span class="c1">// thread.c</span>
<span class="c1">//</span>
<span class="kt">void</span> <span class="nf">thread_init</span><span class="p">(</span><span class="kt">int</span> <span class="n">nthreads</span><span class="p">,</span> <span class="k">struct</span> <span class="n">event_base</span> <span class="o">*</span><span class="n">main_base</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//</span>
<span class="c1">// 中略</span>
<span class="c1">//</span>
    <span class="n">threads</span> <span class="o">=</span> <span class="n">calloc</span><span class="p">(</span><span class="n">nthreads</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">LIBEVENT_THREAD</span><span class="p">));</span>
<span class="c1">//</span>
<span class="c1">// さらに中略</span>
<span class="c1">//</span>
    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nthreads</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="kt">int</span> <span class="n">fds</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">pipe</span><span class="p">(</span><span class="n">fds</span><span class="p">))</span> <span class="p">{</span>
            <span class="n">perror</span><span class="p">(</span><span class="s">&quot;Can&#39;t create notify pipe&quot;</span><span class="p">);</span>
            <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">notify_receive_fd</span> <span class="o">=</span> <span class="n">fds</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
        <span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">notify_send_fd</span> <span class="o">=</span> <span class="n">fds</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>

        <span class="n">setup_thread</span><span class="p">(</span><span class="o">&amp;</span><span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="cm">/* Reserve three fds for the libevent base, and two for the pipe */</span>
        <span class="n">stats</span><span class="p">.</span><span class="n">reserved_fds</span> <span class="o">+=</span> <span class="mi">5</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="cm">/* Create threads after we&#39;ve done all the libevent setup. */</span>
    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nthreads</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">create_worker</span><span class="p">(</span><span class="n">worker_libevent</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">threads</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
    <span class="p">}</span>

    <span class="cm">/* Wait for all the threads to set themselves up before returning. */</span>
    <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">init_lock</span><span class="p">);</span>
    <span class="n">wait_for_thread_registration</span><span class="p">(</span><span class="n">nthreads</span><span class="p">);</span>
    <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">init_lock</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<h3 id="pthread_cond_wait">pthread_cond_waitの実装</h3>
<p>脱線するが、pthread_cond_waitがどのようにsleepにはいってるのか気になったので調べた。</p>
<p><a href="https://sourceware.org/git/?p=glibc.git;a=tree;f=nptl;hb=HEAD">https://sourceware.org/git/?p=glibc.git;a=tree;f=nptl;hb=HEAD</a> </p>
<p><code>pthread_cond_wait</code>のソースコードは<code>glibc</code>の<code>nptl</code>以下にある。
<code>__pthread_cond_wait</code>が<code>lll_futex_wait</code>を呼んでおり、これは以下のように実装されている。(以下はx86_64のもの) </p>
<div class="pygments_borland"><pre><span class="cp">#define lll_futex_wait(futex, val, private) \</span>
<span class="cp">  lll_futex_timed_wait(futex, val, NULL, private)</span>

<span class="cp">#define lll_futex_timed_wait(futex, val, timeout, private) \</span>
<span class="cp">  ({                                         \</span>
<span class="cp">    register const struct timespec *__to __asm (&quot;r10&quot;) = timeout;          \</span>
<span class="cp">    int __status;                                \</span>
<span class="cp">    register __typeof (val) _val __asm (&quot;edx&quot;) = (val);                \</span>
<span class="cp">    __asm __volatile (&quot;syscall&quot;                            \</span>
<span class="cp">             : &quot;=a&quot; (__status)                         \</span>
<span class="cp">             : &quot;0&quot; (SYS_futex), &quot;D&quot; (futex),                 \</span>
<span class="cp">           &quot;S&quot; (__lll_private_flag (FUTEX_WAIT, private)),         \</span>
<span class="cp">           &quot;d&quot; (_val), &quot;r&quot; (__to)                    \</span>
<span class="cp">             : &quot;memory&quot;, &quot;cc&quot;, &quot;r11&quot;, &quot;cx&quot;);                 \</span>
<span class="cp">    __status;                                    \</span>
<span class="cp">  })</span>
</pre></div>

<p>上記アセンブラは大体以下のような意味<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup> </p>
<div class="pygments_borland"><pre><span class="n">futex</span><span class="p">(</span><span class="n">futex</span><span class="p">,</span> <span class="n">FUTEX_WAIT</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="n">timeout</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>  <span class="c1">// 便宜上、上記コードの引数の変数名をそのままつかっているが、</span>
                                                  <span class="c1">// 1つめのfutexはシステムコールのfutexで、</span>
                                                  <span class="c1">// 2つめは引数のpthread_cond_tの__futexメンバ変数のアドレス</span>
</pre></div>

<blockquote>
<p>futex() システムコールは、 指定したアドレスの値が変更されるのをプログラムが待つ手段や 特定のアドレスに対して待機中のプロセスを wake (起床) させる手段を提供する </p>
<p><a href="http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/futex.2.html">futex(2) http://linuxjm.sourceforge.jp/html/LDP_man-pages/man2/futex.2.html</a></p>
</blockquote>
<p>とのこと。</p>
<h3 id="_1">まとめ</h3>
<ul>
<li>pthread_cond_waitをつかったもののほうが普通は高速なはず</li>
<li>memcachedのようなやりかただとユーザプロセス側でスレッドプール管理のための排他制御がほとんど不要になるので多少実装が簡単か</li>
</ul>
<div class="footnote">
<hr />
<ol>
<li id="fn:1">
<p><code>pthread_cond_wait</code>はunixの場合。windowsの場合は<code>pSleepConditionVariableCS</code>、これが使えない場合は疑似的に同様の動作をするようなラッパを定義している。&#160;<a href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text">&#8617;</a></p>
</li>
<li id="fn:2">
<p>memcachedでは使用してないが、libeventはシグナルを通知する際もfdをつかう。Boost.Asioもシグナル通知はpipeを経由する。&#160;<a href="#fnref:2" rev="footnote" title="Jump back to footnote 2 in the text">&#8617;</a></p>
</li>
<li id="fn:3">
<p>厳密には違う。&#160;<a href="#fnref:3" rev="footnote" title="Jump back to footnote 3 in the text">&#8617;</a></p>
</li>
</ol>
</div>]]></content:encoded>
    </item>
    <item>
      <title>シェルスクリプトでプロセスの多重起動を防止する簡単で安全な方法</title>
      <link>http://mojavy.com/blog/2014/02/16/shell-script-ensure-one-process/</link>
      <pubDate>Sun, 16 Feb 2014 18:35:51 JST</pubDate>
      <category><![CDATA[unix]]></category>
      <category><![CDATA[shell]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2014/02/16/shell-script-ensure-one-process/</guid>
      <description>シェルスクリプトでプロセスの多重起動を防止する簡単で安全な方法</description>
      <content:encoded><![CDATA[<p><code>flock(1)</code>を使うのが一番安全かつ簡単</p>
<div class="pygments_borland"><pre><span class="nv">LOCKFILE</span><span class="o">=</span>/tmp/my.lockfile

<span class="o">(</span>
    flock -n 200 <span class="o">||</span> <span class="nb">exit </span>1

    <span class="c"># do something</span>
<span class="o">)</span> 200&gt;<span class="nv">$LOCKFILE</span>
</pre></div>

<p>タイムアウトを設定したければ<code>-w</code>オプションをつかえばよい。</p>
<p>リードライトロックとしてつかえるので、更新系のスクリプトは1つしか起動したくないけど参照系は並列実行を許す、みたいなことも比較的簡単にできる。</p>]]></content:encoded>
    </item>
    <item>
      <title>Mach-Oバイナリのライブラリロードパスをカスタマイズする方法</title>
      <link>http://mojavy.com/blog/2013/05/17/mach-o-rpath/</link>
      <pubDate>Fri, 17 May 2013 19:46:31 JST</pubDate>
      <category><![CDATA[osx]]></category>
      <category><![CDATA[unix]]></category>
      <category><![CDATA[elf]]></category>
      <category><![CDATA[mach-o]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2013/05/17/mach-o-rpath/</guid>
      <description>Mach-Oバイナリのライブラリロードパスをカスタマイズする方法</description>
      <content:encoded><![CDATA[<p><img alt="matrix" src="/images/matrix3.png" /></p>
<p>ライブラリの単体テストをするときとかに、実行プログラムがロードする共有ライブラリのパスを任意のディレクトリで上書きしたいときがある。</p>
<p>例えば以下のようなディレクトリ構成で、<code>project/t/mytest</code>というバイナリをビルドするときに<code>project/src/libmy.so</code>をリンクするようにしておけば作業しやすい。</p>
<div class="pygments_borland"><pre>└── project
    ├── src
    │   ├── libmy.a
    │   ├── libmy.so -&gt; libmy.so.1
    │   ├── libmy.so.1
    │   ├── Makefile
    │   ├── mylib.c
    │   ├── mylib.h
    │   └── mylib.o
    └── t
        ├── Makefile
        ├── mytest
        ├── mytest.c
        └── mytest.o
</pre></div>

<p>こういうときは、<code>mytest</code>をビルドするときに以下のようにしてrpathを相対パスで追加していた。</p>
<div class="pygments_borland"><pre>$ cc -I../src -L../src -Wl,-rpath=../src *.c -lmy -o mytest
$ readelf -d mytest
Dynamic section at offset 0xe30 contains 22 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libmy.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000f (RPATH)              Library rpath: [../src]
 0x000000000000000c (INIT)               0x4004c8
 0x000000000000000d (FINI)               0x4006f8
 0x000000006ffffef5 (GNU_HASH)           0x400298
 0x0000000000000005 (STRTAB)             0x4003c0
 0x0000000000000006 (SYMTAB)             0x4002d0
 0x000000000000000a (STRSZ)              134 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x600fe8
 0x0000000000000002 (PLTRELSZ)           48 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x400498
 0x0000000000000007 (RELA)               0x400480
 0x0000000000000008 (RELASZ)             24 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x400460
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0x400446
 0x0000000000000000 (NULL)               0x0
</pre></div>

<p>しかし、OSXの場合は上記のように単に実行バイナリ側にrpathを追加しただけだと、ローダがrpathを設定するコマンドより先にライブラリをロードするコマンドを実行しようとして該当ファイルがみつけられなくて以下のようなエラーになってしまう.</p>
<div class="pygments_borland"><pre>dyld: Library not loaded: libmy.1.dylib
  Referenced from: /Users/path/to/project/t/./mytest
  Reason: image not found
zsh: trace trap  ./mytest
</pre></div>

<p><code>otool -l &lt;executable file&gt;</code>でロードコマンドの詳細をみると以下のようなエントリがみつかるが、ここのnameの値はライブラリ側の<code>install_path</code>が設定される。</p>
<div class="pygments_borland"><pre>-- 中略
Load command 11
          cmd LC_LOAD_DYLIB
      cmdsize 40
         name libmy.1.dylib (offset 24)
   time stamp 2 Thu Jan  1 09:00:02 1970
      current version 1.0.0
compatibility version 0.0.0
</pre></div>

<p><code>install_path</code>は<code>soname</code>のかわりのようなもので、なにも指定しなければ出力ファイル名になる。
ここに<code>@executable_path</code>や<code>@rpath</code>をつかうことによって、このダイナミックライブラリをリンクする側のバイナリに応じて挙動をかえることができる。
これらの変数(?)の詳細は参考リンクに解説がある。</p>
<p>要は、ELFのrpathとおなじような挙動にしたければ、 <code>-Wl,-install_name,@rpath/libmy.1.dylib</code> というようなオプション付きでライブラリをビルドすればよい。</p>
<p>また、<code>-Wl,-install_name,@executable_path/../src/libmy.1.dylib</code>のようにすると実行ファイルからの相対パスにすることができる。</p>
<p>この情報はリンクされる側のライブラリに埋めこまれている点に注意。</p>
<p>ELFに比べると柔軟にロードパスを制御することができると思われるが、うまく活用するのはちょっと難しそう。</p>
<h4 id="_1">参考リンク</h4>
<ul>
<li><a href="https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath">@executable_path, @load_path and @rpath </a> </li>
<li><a href="https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html">DynamicLibraryDesignGuidelines</a> </li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>おやつの時間をお知らせしてくれるUnixコマンド：at teatime (他...)</title>
      <link>http://mojavy.com/blog/2013/01/08/favorite-linux-command/</link>
      <pubDate>Tue, 08 Jan 2013 20:30:00 JST</pubDate>
      <category><![CDATA[unix]]></category>
      <category><![CDATA[tips]]></category>
      <category><![CDATA[linux]]></category>
      <guid isPermaLink="true">http://mojavy.com/blog/2013/01/08/favorite-linux-command/</guid>
      <description>おやつの時間をお知らせしてくれるUnixコマンド：at teatime (他...)</description>
      <content:encoded><![CDATA[<p><img alt="banana" src="/images/banana-200.png" /></p>
<p><a href="http://clippy.in/b/YJLM9W">Favorite Linux Commands(http://clippy.in/b/YJLM9W)</a> で紹介されてたコマンドのうち知らなかったものをメモ。</p>
<h2 id="at">at</h2>
<p>入力されたコマンドを指定されたタイミングで実行するようにスケジュールする。
cronに登録するほどでもない単発のコマンドを実行したいときとかにつかう。
時間の指定には現在の時刻からの経過時間や絶対時間の他にteatimeやmidnightといった文字列もつかえる。
ちなみにteatimeは午後4時。
出力先を指定しなければコマンドの出力はcronと同じようにメールにとぶ。$TTYにリダイレクトしてやればコマンドを実行した端末に表示させることもできる。</p>
<p>例</p>
<div class="pygments_borland"><pre>echo &quot;echo おやつの時間です &gt; $TTY&quot;| at teatime
echo &quot;echo はろー &gt; $TTY&quot; | at now + 3 minute
</pre></div>

<h2 id="mtr">mtr</h2>
<p>tracerouteとpingをあわせたようなもの。tracerouteより表示がみやすい。
ネットワークのどこで時間がかかってるのか一目でわかる。</p>
<p>例</p>
<div class="pygments_borland"><pre>mtr mojavy.com
</pre></div>

<h2 id="column">column</h2>
<p>入力テキストをいい感じのカラム表示にフォーマットしてくれる。
縦に長い出力するコマンドとか、そのままだと出力がみづらいときとかにつかう。</p>
<p>例</p>
<div class="pygments_borland"><pre>gem list | column
mount | column -t
grep -v &#39;^#&#39; /etc/apt/sources.list | column -t
</pre></div>

<h2 id="reset">reset</h2>
<p>端末をリセットする。
うっかりバイナリファイルをcatとかしてしまって端末が壊れてしまった場合に端末を閉じずに復帰できる。</p>
<h2 id="sshfs">sshfs</h2>
<p>ssh経由でリモートのファイルシステムをマウントできる。</p>
<p>例</p>
<div class="pygments_borland"><pre>sshfs name@server:/path/to/dir /path/to/mount/point
fusermount -u /path/to/mount/point  # unmount
</pre></div>

<h2 id="_1">その他</h2>
<p>以下はコマンド自体の機能ではないけど覚えておくと便利かもしれないもの</p>
<h3 id="curl-ifconfigme">curl ifconfig.me</h3>
<p>ifconfig.meというサイトがある。自分のグローバルIPがわかる。</p>
<h3 id="dig-short-txt-wzxhzdk5wpdgcx">dig +short txt <keyword>.wp.dg.cx</h3>
<p>dnsクエリでwikipediaのエントリーがみれる。</p>
<p>例</p>
<div class="pygments_borland"><pre><span class="nv">$ </span>dig +short txt banana.wp.dg.cx
<span class="s2">&quot;Banana is the common name for herbaceous plants of the genus Musa and for the fruit they produce. It is one of the oldest cultivated plants. They are native to tropical South and Southeast Asia, and are likely to have been first domesticated in Papua New &quot;</span> <span class="s2">&quot;Guinea. Today, they are cultivated throughout the tropics. They are grown in at least 107 countries, primarily for their... http://en.wikipedia.org/wiki/Banana&quot;</span>
</pre></div>]]></content:encoded>
    </item>
  </channel>
</rss>
