<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>C on liubang's blog</title><link>https://blog.liubang.cc/tags/c/</link><description>Recent content in C on liubang's blog</description><generator>Hugo</generator><language>en</language><copyright>Copyright © 2019-2026 LiuBang. All Rights Reserved.</copyright><lastBuildDate>Sun, 18 Aug 2019 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.liubang.cc/tags/c/index.xml" rel="self" type="application/rss+xml"/><item><title>使用c语言模拟lisp语法</title><link>https://blog.liubang.cc/posts/sp/2019-08-18-c%E8%AF%AD%E8%A8%80%E6%A8%A1%E6%8B%9Flisp%E8%AF%AD%E6%B3%95/</link><pubDate>Sun, 18 Aug 2019 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2019-08-18-c%E8%AF%AD%E8%A8%80%E6%A8%A1%E6%8B%9Flisp%E8%AF%AD%E6%B3%95/</guid><description><![CDATA[<p>使用 c 语言的 macro 操作，能够很简单的用 c 语言模拟 lisp 语法。</p>

<h3 id="下面我们来定义-lisph-头文件" data-numberify>下面我们来定义 lisp.h 头文件<a class="anchor ms-1" href="#下面我们来定义-lisph-头文件"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#ifndef LISP_H_OTE1HWPK
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#define LISP_H_OTE1HWPK
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdio.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdlib.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#7f848e">#define define(ret, name, args, block) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span><span style="color:#7f848e">    ret name args { return block; }
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span><span style="color:#7f848e">#define if(expr, block1, block2) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span><span style="color:#7f848e">    expr ? block1 : block2
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span><span style="color:#7f848e">#define eq(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span><span style="color:#7f848e">    a == b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span><span style="color:#7f848e">#define neq(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span><span style="color:#7f848e">    a != b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span><span style="color:#7f848e">#define sub(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span><span style="color:#7f848e">    a - b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span><span style="color:#7f848e">#define mul(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span><span style="color:#7f848e">    a * b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span><span style="color:#7f848e">#define add(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span><span style="color:#7f848e">    a + b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span><span style="color:#7f848e">#define div(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-29"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-29">29</a></span><span><span style="color:#7f848e">    a / b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-30"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-30">30</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-31"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-31">31</a></span><span><span style="color:#7f848e">#endif </span><span style="color:#7f848e">/* end of include guard: LISP_H_OTE1HWPK */</span><span style="color:#7f848e">
</span></span></span></code></pre></div>
<h3 id="然后来用类似于-lisp-的语法编写一段求阶乘的代码" data-numberify>然后来用类似于 lisp 的语法编写一段求阶乘的代码：<a class="anchor ms-1" href="#然后来用类似于-lisp-的语法编写一段求阶乘的代码"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#61afef;font-weight:bold">define</span>(<span style="color:#e5c07b">int</span>, <span style="color:#e06c75">factorial</span>, (<span style="color:#e5c07b">int</span> <span style="color:#e06c75">n</span>),
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span>       <span style="color:#c678dd">if</span>(<span style="color:#61afef;font-weight:bold">eq</span>(<span style="color:#e06c75">n</span>, <span style="color:#d19a66">0</span>),
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span>          <span style="color:#d19a66">1</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span>          <span style="color:#61afef;font-weight:bold">mul</span>(<span style="color:#e06c75">n</span>, <span style="color:#61afef;font-weight:bold">factorial</span>(<span style="color:#61afef;font-weight:bold">sub</span>(<span style="color:#e06c75">n</span>, <span style="color:#d19a66">1</span>)))))
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5">5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6">6</a></span><span><span style="color:#61afef;font-weight:bold">define</span>(<span style="color:#e5c07b">int</span>, <span style="color:#e06c75">main</span>, (<span style="color:#e5c07b">void</span>),
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7">7</a></span><span>       (<span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;10! = %d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#61afef;font-weight:bold">factorial</span>(<span style="color:#d19a66">10</span>)), <span style="color:#e06c75">EXIT_SUCCESS</span>))
</span></span></code></pre></div>
<h3 id="编写-makefile" data-numberify>编写 Makefile:<a class="anchor ms-1" href="#编写-makefile"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1">1</a></span><span>CFLAGS = -Wall -include &#34;lisp.h&#34;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-2">2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-3">3</a></span><span>TARGET=factorial
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-4">4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-5">5</a></span><span>all:
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-6">6</a></span><span>	gcc -o $(TARGET) $(TARGET).c $(CFLAGS)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-7">7</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-8">8</a></span><span>clean:
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-9">9</a></span><span>	rm -f $(TARGET)
</span></span></code></pre></div>
<h3 id="编译并运行" data-numberify>编译并运行：<a class="anchor ms-1" href="#编译并运行"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-1">1</a></span><span>liubang@venux-dev:~$ make
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-2">2</a></span><span>gcc -o factorial factorial.c -Wall -include &#34;lisp.h&#34;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-3">3</a></span><span>liubang@venux-dev:~$ ./factorial
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-4">4</a></span><span>10! = 3628800
</span></span></code></pre></div>]]></description></item><item><title>动态连接器技巧之使用LD_PRELOAD改变程序的行为</title><link>https://blog.liubang.cc/posts/sp/2019-07-18-%E5%8A%A8%E6%80%81%E8%BF%9E%E6%8E%A5%E5%99%A8%E6%8A%80%E5%B7%A7%E4%B9%8B%E4%BD%BF%E7%94%A8ld_preload%E6%94%B9%E5%8F%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E8%A1%8C%E4%B8%BA/</link><pubDate>Thu, 18 Jul 2019 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2019-07-18-%E5%8A%A8%E6%80%81%E8%BF%9E%E6%8E%A5%E5%99%A8%E6%8A%80%E5%B7%A7%E4%B9%8B%E4%BD%BF%E7%94%A8ld_preload%E6%94%B9%E5%8F%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E8%A1%8C%E4%B8%BA/</guid><description><![CDATA[<p>我们有这样一段简单的代码，用来输出 10 个[0, 100)的随机数：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// random.c
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdio.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdlib.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;time.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>() {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#61afef;font-weight:bold">srand</span>(<span style="color:#61afef;font-weight:bold">time</span>(<span style="color:#e5c07b">NULL</span>));
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">10</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#c678dd">while</span> (<span style="color:#e06c75">i</span><span style="color:#56b6c2">--</span>) <span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;%d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#61afef;font-weight:bold">rand</span>() <span style="color:#56b6c2">%</span> <span style="color:#d19a66">100</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>}
</span></span></code></pre></div><p>编译运行：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span>liubang@venux-dev:~$ gcc random.c -o random
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>liubang@venux-dev:~$ ./random
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span><span style="color:#d19a66">44</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span><span style="color:#d19a66">46</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span><span style="color:#d19a66">97</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span><span style="color:#d19a66">51</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span><span style="color:#d19a66">62</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span><span style="color:#d19a66">76</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span><span style="color:#d19a66">92</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span><span style="color:#d19a66">76</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span><span style="color:#d19a66">38</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span><span style="color:#d19a66">10</span>
</span></span></code></pre></div><p>这个程序每次运行的结果都是不一样的，现在我们希望我们能够在不修改源码的情况下，控制程序的输出结果，例如我希望这段程序运行的结果是
每次都能输出 10 个 10。由于不能修改源码，或者我们根本没有源码，面对这样一个编译后的可执行二进制文件，想要修改程序的运行结果，可能显
得有些困难。然而，如果能够善用动态连接器的话，这都不是问题。</p>]]></description></item><item><title>多线程编程</title><link>https://blog.liubang.cc/posts/sp/2018-12-05-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B/</link><pubDate>Wed, 05 Dec 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2018-12-05-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B/</guid><description><![CDATA[<h2 id="开始之前" data-numberify>开始之前<a class="anchor ms-1" href="#开始之前"></a></h2>
<p>这篇文章主要是为了帮助大家熟悉 POSIX 线程库以及在实际开发中使用它的特性。我们会具体讲解如何利用这个线程库定义的不同工具
来解决编程中的问题。当然这里隐含了一个假设，就是读者已经了解过并行编程（或者多进程）的相关概念，如果没有这些背景知识
的话，读者可能会感觉到很难理解。不过也没关系，我的另一篇教程里边有专门为只具备线性编程思维的读者提供了对并行编程理论
和相关术语的讲解。</p>
<p>同样的，我假设聪明的你已经熟悉了异步编程模型，那些经常使用桌面环境的人会更容易去接受多线程编程的理念。</p>
<p>当我们谈到 POSIX 线程的时候，肯定会有人心生疑惑：“我们应该使用哪个标准下的 POSIX 线程？”。由于 POSIX 线程标准已经修订了好
多年，人们会发现，依据不同标准的实现有不同的函数集，不同的默认值和不同的细微差别。所以在此说明的是，本教程使用的是 v0.5 版的 Linux 内核中的线程库，使用其他操作系统和使用其他版本的读者，需要阅读一下你们对应的系统文档来同本文中的实例进行对应。同时，有些示例代码中使用到了阻塞式的系统调用，它们不能再用户级的线程库中很好的工作（参考另一篇文章：<a href="http://www.actcom.co.il/~choo/lupg/tutorials/parallel-programming-theory/parallel-programming-theory.html#multi_thread_lib" target="_blank" rel="noopener noreferrer">parallel programming theory tutorial<i class="fas fa-external-link-square-alt ms-1"></i></a> 来获取详细信息）。好了，说了那么多，主要是为了能保证文章中的示例代码能够在其他系统中正常使用，从而提高跨平台性。</p>

<h2 id="什么是线程为什么要使用线程" data-numberify>什么是线程？为什么要使用线程？<a class="anchor ms-1" href="#什么是线程为什么要使用线程"></a></h2>
<p>线程是一个迷你版的进程，它们拥有自己的栈，能够执行给定的一段代码。但是不同于进程的是，线程通常与其他线程共享记忆体（而
每个进程都拥有一个独立的记忆体区域）。一个线程组就是一个执行相同代码的线程的集合，他们共用记忆体，可以访问相同的全局变
量，拥有同样的文件描述符等等，他们以并行的方式执行（可能是时间片的方式，或者对于多核心系统，他们会真正平行执行）。</p>
<p>使用线程组而不是普通顺序执行程序的好处是多个操作可以同时进行，当一些事件产生的时候，他们能立马被处理（例如：如果我们有
一个线程处理用户接口，另一个线程处理数据库查询，那么我们可以在处理很多用户查询的同时，依然能够响应用户的输入）。</p>
<p>使用线程组而不是进程组的好处是线程间的上下文切换要比进程间的上下文切换要快很多（上下文切换是指系统从一个正在运行的线程或进程切换到去执行另一个线程或进程）。此外，线程间的通信也远远比进程间通信要高效很多。</p>
<p>线程编程有利也有弊，由于线程组共享记忆体，如果一个线程破坏了记忆体，那么其他线程也要受到牵连。但是进程就不同了，操作系
统会将进程之间隔离开，如果一个进程破坏了它的记忆体，那么其他进程不会受到影响。使用进程的另一个好处是，不同的进程可以运
行在不同的机器上，但是线程必须运行在同一台机器上（至少通常情况下是这样的）。</p>

<h2 id="创建和销毁线程" data-numberify>创建和销毁线程<a class="anchor ms-1" href="#创建和销毁线程"></a></h2>
<p>当一个多线程程序启动执行到<code>main()</code>函数的时候，就会有一个线程运行，这是一个全程线程（full-fledged thread，或者叫主线程），如果想创建一个新的线程，程序中需要使用<code>pthread_create()</code>函数</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdio.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;pthread.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">do_loop</span>(<span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">data</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span>; <span style="color:#7f848e">// counter, to print numbers
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">j</span>; <span style="color:#7f848e">// counter, for delay
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">me</span> <span style="color:#56b6c2">=</span> <span style="color:#56b6c2">*</span>((<span style="color:#e5c07b">int</span> <span style="color:#56b6c2">*</span>)<span style="color:#e06c75">data</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#c678dd">for</span> (<span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#d19a66">10</span>; <span style="color:#e06c75">i</span><span style="color:#56b6c2">++</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>        <span style="color:#c678dd">for</span> (<span style="color:#e06c75">j</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">j</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#d19a66">50000</span>; <span style="color:#e06c75">j</span><span style="color:#56b6c2">++</span>) <span style="color:#7f848e">// delay loop
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>            ;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>        <span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;&#39;%d&#39; - Got &#39;%d&#39;</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#e06c75">me</span>, <span style="color:#e06c75">i</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>    <span style="color:#7f848e">// terminate the thread
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>    <span style="color:#61afef;font-weight:bold">pthread_exit</span>(<span style="color:#e5c07b">NULL</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">argc</span>, <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">argv</span>[])
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>    <span style="color:#e5c07b">int</span>       <span style="color:#e06c75">thr_id</span>;    <span style="color:#7f848e">// thread ID for the newly created thread
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span>    <span style="color:#e5c07b">pthread_t</span> <span style="color:#e06c75">p_thread</span>;  <span style="color:#7f848e">// thread&#39;s structure
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">a</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">1</span>;           <span style="color:#7f848e">// thread 1 identifying number
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">b</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">2</span>;           <span style="color:#7f848e">// thread 2 identifying number
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span>    <span style="color:#7f848e">// create a new thread that will execute &#39;do_loop()&#39;
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>    <span style="color:#e06c75">thr_id</span> <span style="color:#56b6c2">=</span> <span style="color:#61afef;font-weight:bold">pthread_create</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">p_thread</span>, <span style="color:#e5c07b">NULL</span>, <span style="color:#e06c75">do_loop</span>, (<span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span>)<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">a</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-29"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-29">29</a></span><span>    <span style="color:#7f848e">// run &#39;do_loop&#39; in the main thread as well
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-30"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-30">30</a></span><span>    <span style="color:#61afef;font-weight:bold">do_loop</span>((<span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span>)<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">b</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-31"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-31">31</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-32"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-32">32</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-33"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-33">33</a></span><span>}
</span></span></code></pre></div><p>上述这段代码需要特殊说明的是：</p>]]></description></item><item><title>PHP7虚拟机</title><link>https://blog.liubang.cc/posts/php/2017-11-29-php7%E8%99%9A%E6%8B%9F%E6%9C%BA/</link><pubDate>Wed, 29 Nov 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-11-29-php7%E8%99%9A%E6%8B%9F%E6%9C%BA/</guid><description><![CDATA[<p>原文地址<a href="http://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html" target="_blank" rel="noopener noreferrer">http://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html<i class="fas fa-external-link-square-alt ms-1"></i></a></p>
<p>写这篇文章的目的是基于 php7，阐述 Zend Virtual Machine 的内部实现。这不是一篇综合描述，我将尽可能地覆盖到所有重要的部分和细节。</p>
<p>本文的描述对象是 php7.2 版本，但是几乎所有的特性都已经应用在了 php7.0/7.1 中了。然而，它们同 php5.x 系列 VM 的不同之处同样也很重要，我会很有耐心的同步描述。</p>
<p>这篇文章主要是从指令的角度来阐述，只有在末尾花了少量篇幅描述了 C 语言实现 VM 的细节。但是在文章开始之前，我想先提供一些实现 VM 的主要代码文件：</p>
<ul>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_vm_def.h" target="_blank" rel="noopener noreferrer">zend_vm_def.h<i class="fas fa-external-link-square-alt ms-1"></i></a>: VM 定义文件</li>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_vm_execute.h" target="_blank" rel="noopener noreferrer">zend_vm_execute.h<i class="fas fa-external-link-square-alt ms-1"></i></a>: 生成的 VM</li>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_vm_gen.php" target="_blank" rel="noopener noreferrer">zend_vm_gen.php<i class="fas fa-external-link-square-alt ms-1"></i></a>: VM 生成脚本</li>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_execute.c" target="_blank" rel="noopener noreferrer">zend_execute.c<i class="fas fa-external-link-square-alt ms-1"></i></a>: 大多数直接支持的代码</li>
</ul>

<h2 id="opcodes" data-numberify>Opcodes<a class="anchor ms-1" href="#opcodes"></a></h2>
<p>首先我们来聊聊 opcode。&ldquo;Opcode&quot;是用来表示整个 VM 指令集（包括操作数）的，但是也可能仅仅就是指“真实的”操作码，这些操作码是一个很小的整数用来区分不同的指令类型。其具体的含义需要结合代码的上下文才能清楚。在程式码中，指令通常被称作&quot;oplines&rdquo;。</p>
<p>下面是<code>zend_op</code>的结构</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_op</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span>    <span style="color:#c678dd">const</span> <span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">handler</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>    <span style="color:#e06c75">znode_op</span> <span style="color:#e06c75">op1</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>    <span style="color:#e06c75">znode_op</span> <span style="color:#e06c75">op2</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>    <span style="color:#e06c75">znode_op</span> <span style="color:#e06c75">result</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#e5c07b">uint32_t</span> <span style="color:#e06c75">extended_value</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#e5c07b">uint32_t</span> <span style="color:#e06c75">lineno</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">opcode</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">op1_type</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">op2_type</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">result_type</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>};
</span></span></code></pre></div><p>由此看来，opcodes 本质上就是一个“三地址码”格式的指令。有一个<code>opcode</code>代表指令的类型，有两个输入操作数<code>op1</code>和<code>op2</code>和一个输出操作数<code>result</code>。</p>]]></description></item><item><title>PHP和线程</title><link>https://blog.liubang.cc/posts/php/2017-10-12-php%E5%92%8C%E7%BA%BF%E7%A8%8B/</link><pubDate>Thu, 12 Oct 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-10-12-php%E5%92%8C%E7%BA%BF%E7%A8%8B/</guid><description><![CDATA[<p>原文地址<a href="http://blog.jpauli.tech/2017/01/12/threads-and-php.html" target="_blank" rel="noopener noreferrer">http://blog.jpauli.tech/2017/01/12/threads-and-php.html<i class="fas fa-external-link-square-alt ms-1"></i></a></p>

<h2 id="前言" data-numberify>前言<a class="anchor ms-1" href="#前言"></a></h2>
<p>PHP 和线程，单凭这简短的几个字，就足以写一本书。像往常一样，我们不会这么做，但是会给出一定程度上跟这个话题相关的信息与细节。让我们从一些人在谈论这个话题时通常感到的困惑开始，PHP 不是一种线程语言，
PHP 的内核没有使用线程，而且 PHP 天生也不允许用户层代码通过任何方式使用多线程作为并发机制。</p>
<p>因此 PHP 跟其他一些技术有很大的区别，例如 Java。Java 不仅自身使用了大量的线程，它还允许用户通过编程来是用线程。然而，PHP 不适用线程是有它的原因的。</p>
<p>PHP 内核没有使用线程，主要是为了简化开发。当你读到下一节的时候，你就会了解到线程并不是一个能使任何程序都能更快运行的魔法技术。是不是听起来很像是在推销不是吗？但是我们不是推销，而是谈论技术，而且
我们很清楚我们在说什么。因此 PHP 引擎目前没有使用多线程，也许将来会使用。但是使用多线程在编程上会引发很多问题，例如程序运行结果不是你所期待的等等。主要的困难是跨平坦的多线程编程，其次就是资源共享和
锁的管理，再次就是并不是所有的程序都能够被转化成多线程程序。PHP 的设计主要在 2000 前后，在那个时候，多线程编程并不是很广泛和成熟，PHP 引擎开发工程师决定创造一个完全没有线程的单片机引擎（当然他们也没有
足够的能力去驾驭一个稳定的跨平台的多线程引擎）。</p>
<p>PHP 用户层代码也不允许使用线程，因为那不是 PHP 期待你的代码运行的方式。PHP 是一个&quot;发送并忘记(fire-and-forget)&ldquo;型的语言，你应该尽可能快的处理完请求，然后释放，然后接着处理下一个请求。PHP 被设计作为一种
胶水语言：你不用处理可能使用到线程的复杂任务，而是访问快速而且已经准备好的资源，将它们粘合到一起，然后再返回给用户。通过 PHP，无论什么可能花费比通常时间多的时间的任务，都不能用 PHP 来处理。这就是为什么
在 PHP 中我们通常使用基于消息队列的系统(Gearman, AMQP, ActiveMQ 等等)来异步处理一些耗时任务。正如 Unix 看待事物的方式：“开发小而完备的工具，然后将他们连接在一起”。因此 PHP 的设计不是允许大规模的并行，而是
其他专门的技术&ndash;是用正确的工具来解决特定的问题。</p>

<h2 id="线程的简介" data-numberify>线程的简介<a class="anchor ms-1" href="#线程的简介"></a></h2>
<p>让我们来快速的介绍下线程。注意，我们不会阐述太多细节的东西，对于你想深入了解关于线程的任何细节，都可以在相关书籍和站点上找到。</p>
<p>线程是进程中的轻量的事务处理单元，注意，一个进程可以产生多个线程，一个线程必须有且只能属于一个进程。进程是操作系统中的基本工作处理单元。在多 CPU 的机器上，不同的 CPU 将会平行工作，这样对于计算能力的提升会
有很大的好处。如果进程 A 和 B 都准备被执行，而且两个 CPU（或者两个 CPU 核心）也都有空闲的负载，那么进程 A 和 B 将会同时被执行。因此，计算机将能高效的在一个单位时间内同时进行多个运算，我们称之为“并行”(parallelism)。</p>]]></description></item><item><title>理解c语言中的声明</title><link>https://blog.liubang.cc/posts/sp/2017-09-12-%E7%90%86%E8%A7%A3c%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E5%A3%B0%E6%98%8E/</link><pubDate>Tue, 12 Sep 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2017-09-12-%E7%90%86%E8%A7%A3c%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E5%A3%B0%E6%98%8E/</guid><description><![CDATA[<p>在阅读优秀的 c 语言开源程式的时候，我们经常会看到各种复杂的声明，顿时会让我们怀疑人生，怀疑自己是否真的看得懂 c 语言。然而冷静三秒钟，透过现象看本质，发现牛人写的代码并不是“天书”，
也是很好懂的，关键是要冷静和耐心去阅读。</p>

<h2 id="从中的一个例子说起" data-numberify>从“中的一个例子说起<a class="anchor ms-1" href="#从中的一个例子说起"></a></h2>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span>(<span style="color:#56b6c2">*</span>(<span style="color:#e5c07b">void</span>(<span style="color:#56b6c2">*</span>)())<span style="color:#d19a66">0</span>)()
</span></span></code></pre></div><p>下面我们来一步步分析：</p>
<p>我们知道变量的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#e06c75">a</span>;
</span></span></code></pre></div><p>函数的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1">1</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">fn</span>();
</span></span></code></pre></div><p>指针的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-1">1</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">a</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">10</span>;
</span></span></code></pre></div><p>函数指针的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-4-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-4-1">1</a></span><span><span style="color:#e5c07b">int</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">fn</span>)(); <span style="color:#7f848e">//fn 是一个指向返回int型的函数的指针
</span></span></span></code></pre></div><p>函数指针的调用方式：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-1"> 1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#61afef;font-weight:bold">int</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">fn_type</span>)();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-2"> 2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-3"> 3</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">fn</span>() {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-4"> 4</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-5"> 5</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-7"> 7</a></span><span><span style="color:#e06c75">fn_type</span> <span style="color:#e06c75">a</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">fn</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-8"> 8</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-9"> 9</a></span><span><span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;%d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#61afef;font-weight:bold">a</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-10">10</a></span><span><span style="color:#7f848e">//或者
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-11">11</a></span><span><span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;%d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, (<span style="color:#56b6c2">*</span>)<span style="color:#61afef;font-weight:bold">a</span>());
</span></span></code></pre></div><p>最简单的类型转换：</p>]]></description></item><item><title>PHP扩展开发之迭代器</title><link>https://blog.liubang.cc/posts/php/2017-08-28-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%BF%AD%E4%BB%A3%E5%99%A8/</link><pubDate>Mon, 28 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-28-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%BF%AD%E4%BB%A3%E5%99%A8/</guid><description><![CDATA[<h2 id="preface" data-numberify>preface<a class="anchor ms-1" href="#preface"></a></h2>
<p>在之前的文章中，我们已经实现了一些 object handlers 来将我们的 ArrayBuffer 整合到 php 中。但是美中不足的是，我们的 ArrayBufferView 并不支持迭代器操作。也就是它不能像 php 中的数组那样使用<code>foreach</code>来遍历。
那么，我们接下来就来看看迭代器在内核中是如何实现的，并且给我们的 ArrayBufferView 也增加一个迭代器。</p>

<h2 id="get_iterator-handler" data-numberify>get_iterator handler<a class="anchor ms-1" href="#get_iterator-handler"></a></h2>
<p>内核中的迭代器跟用户端的<code>IteratorAggregate</code>接口功能是一样的。一个具有迭代功能的类都有一个<code>get_iterator</code>处理器，它会返回一个<code>zend_object_iterator *</code>类型的结构，该结构定义如下（位于 phpsrc/Zend/zend_iterators.h 中）：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_object_iterator</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>    <span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">data</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e06c75">zend_object_iterator_funcs</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">funcs</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>    <span style="color:#e06c75">ulong</span> <span style="color:#e06c75">index</span>; <span style="color:#7f848e">/* private to fe_reset/fe_fetch opcodes */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>};
</span></span></code></pre></div><p>其中的<code>index</code>成员就是内核中用以实现<code>foreach</code>的，它的值会在每次迭代后增加。<code>funcs</code>成员包含了不同的迭代操作：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_object_iterator_funcs</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>    <span style="color:#7f848e">/* release all resources associated with this iterator instance */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">dtor</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>    <span style="color:#7f848e">/* check for end of iteration (FAILURE or SUCCESS if data is valid) */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>    <span style="color:#e5c07b">int</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">valid</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>    <span style="color:#7f848e">/* fetch the item data for the current element */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">get_current_data</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">***</span><span style="color:#e06c75">data</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>    <span style="color:#7f848e">/* fetch the key for the current element (optional, may be NULL). The key
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span><span style="color:#7f848e">     * should be written into the provided zval* using the ZVAL_* macros. If
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-13">13</a></span><span><span style="color:#7f848e">     * this handler is not provided auto-incrementing integer keys will be
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-14">14</a></span><span><span style="color:#7f848e">     * used. */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-15">15</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">get_current_key</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-16">16</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-17">17</a></span><span>    <span style="color:#7f848e">/* step forwards to next element */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-18">18</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">move_forward</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-19">19</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-20">20</a></span><span>    <span style="color:#7f848e">/* rewind to start of data (optional, may be NULL) */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-21">21</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">rewind</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-22">22</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-23">23</a></span><span>    <span style="color:#7f848e">/* invalidate current value/key (optional, may be NULL) */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-24">24</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">invalidate_current</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-25">25</a></span><span>} <span style="color:#e06c75">zend_object_iterator_funcs</span>;
</span></span></code></pre></div><p>这些处理器跟<code>Iterator</code>接口中的抽象方法类似，只不过名字不同罢了。唯一没有对应用户端接口的是<code>invalidate_current</code>，它可以被用来销毁当前的<code>key/value</code>。
然而这个操作几乎不会被用到，通常<code>foreach</code>也不会取调用它。</p>]]></description></item><item><title>PHP扩展开发之对象处理器(Object Handlers)</title><link>https://blog.liubang.cc/posts/php/2017-08-27-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E5%AF%B9%E8%B1%A1%E5%A4%84%E7%90%86%E5%99%A8/</link><pubDate>Sun, 27 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-27-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E5%AF%B9%E8%B1%A1%E5%A4%84%E7%90%86%E5%99%A8/</guid><description><![CDATA[<h2 id="object-handlers" data-numberify>Object Handlers<a class="anchor ms-1" href="#object-handlers"></a></h2>
<p>在前面的博文中，已经介绍过一些 object handlers 了，也特别介绍了如何通过指定 handlers 来创建一个自定义的结构和使用<code>clone_obj</code>来对自定义的结构进行克隆操作。
然而，这只是开始：在 php 中，几乎所有的对象操作，都可以通过 object handlers 来实现，而且所有的魔术方法和魔术接口在内核中都是实现了对应的 object handler。此外，
一些 handlers 并没有开放给用户端的 php，例如，内部类可以自定义类的比较操作，而使用 php 代码是无法实现的。</p>
<p>由于 php 中有很多不同的 object handlers，这里只挑几个来讨论，其它的只给出简单的说明。</p>

<h2 id="概述" data-numberify>概述<a class="anchor ms-1" href="#概述"></a></h2>
<p>下面列举出 php 中主要的 26 个(php5.6 中为 28 个)object handlers（位于 phpsrc/Zend/zend_object_handlers.h），并给出简要的说明。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">read_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">type</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">write_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">value</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">has_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">has_set_exists</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">unset_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#61afef;font-weight:bold">get_property_ptr_ptr</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span></code></pre></div><p>上述 handlers 分别表示<code>__get</code>，<code>__set</code>，<code>__isset</code>，<code>__unset</code>方法。<code>get_property_ptr_ptr</code>等同于<code>__get</code>返回一个引用类型。<code>zend_literal *key</code>作为这些函数的参数
起到优化作用，例如它包含了一些将属性名进行 hash 计算的结果。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">read_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">offset</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">type</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">write_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">offset</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">value</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">has_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">check_empty</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">unset_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">offset</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span></code></pre></div><p>上述了几个 handlers 就是内核用以实现<code>ArrayAccess</code>接口的。</p>]]></description></item><item><title>PHP扩展开发之打造一个简易的ArrayBuffer</title><link>https://blog.liubang.cc/posts/php/2017-08-25-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E6%89%93%E9%80%A0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E7%9A%84arraybuffer/</link><pubDate>Fri, 25 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-25-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E6%89%93%E9%80%A0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E7%9A%84arraybuffer/</guid><description><![CDATA[<h2 id="arraybuffer-简介" data-numberify>ArrayBuffer 简介<a class="anchor ms-1" href="#arraybuffer-简介"></a></h2>
<p>ArrayBuffer 又叫二进制数组，是一个用来表示通用的，固定长度的二进制数据缓冲区。你不能直接操纵 ArrayBuffer 的内容，
而是创建一个表示特定格式的 buffer 的类型化数组对象（也叫做数据视图对象）来对 buffer 的内容进行读写操作。</p>
<p>我最早了解 ArrayBuffer 是从 JavaScript 开始的，具体的用法和 api 可以参考<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer" target="_blank" rel="noopener noreferrer">JavaScript 标准库－－ArrayBuffer<i class="fas fa-external-link-square-alt ms-1"></i></a></p>
<p>那么接下来，我们就给 PHP 扩展一个简单的 ArrayBuffer，顺便巩固一下<a href="https://iliubang.github.io/c/2017/08/24/php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AD%98%E5%82%A8/" target="_blank" rel="noopener noreferrer">php 扩展开发之自定义对象的存储<i class="fas fa-external-link-square-alt ms-1"></i></a>。</p>

<h2 id="定义-arraybuffer-的数据结构和相关-handlers" data-numberify>定义 ArrayBuffer 的数据结构和相关 handlers<a class="anchor ms-1" href="#定义-arraybuffer-的数据结构和相关-handlers"></a></h2>
<p><code>ArrayBuffer</code>是一个非常简单的对象，它只需要申明并存储一个<code>buffer</code>和它的长度即可：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_buffer_object</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>    <span style="color:#e06c75">zend_object</span> <span style="color:#e06c75">std</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">buffer</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>    <span style="color:#e5c07b">size_t</span> <span style="color:#e06c75">length</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>} <span style="color:#e06c75">buffer_object</span>;
</span></span></code></pre></div><p>接下来我们来实现它的<code>create</code>和<code>free</code> handlers，有了前面的基础，这个实现也是及其简单的：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#c678dd">static</span> <span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">linger_array_buffer_free_object_storage</span>(<span style="color:#e06c75">buffer_object</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">intern</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>	<span style="color:#61afef;font-weight:bold">zend_object_std_dtor</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">std</span> <span style="color:#e06c75">TSRMLS_CC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>	<span style="color:#61afef;font-weight:bold">linger_efree</span>(<span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">buffer</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span><span style="color:#e06c75">zend_object_value</span> <span style="color:#61afef;font-weight:bold">linger_array_buffer_create_object</span>(<span style="color:#e06c75">zend_class_entry</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">class_type</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>	<span style="color:#e06c75">zend_object_value</span> <span style="color:#e06c75">retval</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span>	<span style="color:#e06c75">buffer_object</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">intern</span> <span style="color:#56b6c2">=</span> <span style="color:#61afef;font-weight:bold">emalloc</span>(<span style="color:#c678dd">sizeof</span>(<span style="color:#e06c75">buffer_object</span>));
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>	<span style="color:#61afef;font-weight:bold">memset</span>(<span style="color:#e06c75">intern</span>, <span style="color:#d19a66">0</span>, <span style="color:#c678dd">sizeof</span>(<span style="color:#e06c75">buffer_object</span>));
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-13">13</a></span><span>	<span style="color:#61afef;font-weight:bold">zend_object_std_init</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">std</span>, <span style="color:#e06c75">class_type</span> <span style="color:#e06c75">TSRMLS_CC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-14">14</a></span><span>	<span style="color:#61afef;font-weight:bold">object_properties_init</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">std</span>, <span style="color:#e06c75">class_type</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-15">15</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-16">16</a></span><span>	<span style="color:#e06c75">retval</span>.<span style="color:#e06c75">handle</span> <span style="color:#56b6c2">=</span> <span style="color:#61afef;font-weight:bold">zend_objects_store_put</span>(
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-17">17</a></span><span>			<span style="color:#e06c75">intern</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-18">18</a></span><span>			(<span style="color:#e5c07b">zend_objects_store_dtor_t</span>) <span style="color:#e06c75">zend_objects_destroy_object</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-19">19</a></span><span>			(<span style="color:#e5c07b">zend_objects_free_object_storage_t</span>) <span style="color:#e06c75">linger_array_buffer_free_object_storage</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-20">20</a></span><span>			<span style="color:#e5c07b">NULL</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-21">21</a></span><span>			<span style="color:#e06c75">TSRMLS_CC</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-22">22</a></span><span>			);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-23">23</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-24">24</a></span><span>	<span style="color:#e06c75">retval</span>.<span style="color:#e06c75">handlers</span> <span style="color:#56b6c2">=</span> <span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">linger_array_buffer_handlers</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-25">25</a></span><span>	<span style="color:#c678dd">return</span> <span style="color:#e06c75">retval</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-26">26</a></span><span>}
</span></span></code></pre></div><p>从上面的代码中可以看到，我们并没有在<code>create_object</code>中申请<code>buffer</code>的空间，而这步操作将会在<code>__construct</code>中来实现，因为<code>buffer</code>的长度会作为构造函数的参数传递过来。</p>]]></description></item><item><title>PHP扩展开发之自定义对象的存储</title><link>https://blog.liubang.cc/posts/php/2017-08-24-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AD%98%E5%82%A8/</link><pubDate>Thu, 24 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-24-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AD%98%E5%82%A8/</guid><description><![CDATA[<h2 id="前言" data-numberify>前言<a class="anchor ms-1" href="#前言"></a></h2>
<p>对于 php 扩展开发，很多人可能已经不那么陌生了，zend 引擎为了们提供了非常丰富了函数和 macro，来帮助我们很快速的创建一个标准的 php 类，然而，当我们在使用自定义的数据结构(struct)，
并想把我们自己定义的数据结构封装成 php 的类的时候可能就会有些困惑，因为我们都知道 php 中的所有变量都是通过 zval 来存储的，而我们自定义的数据结构要怎样才能和 zval 实现完美的对接呢？
以前我通常采用的一种方式就是使用 zend 引擎提供的资源类型，因为资源类型的封装中包含了通用的数据类型，而且有很丰富的函数来操作资源，所以使用起来很简单也很方便。然而，强大的 zend
引擎真的没有其他方式扩展数据结构了吗？当然不是！下面就来介绍一个更加优雅的方式。要弄明白，首要要搞清 php 内核是如何创建对象的。</p>

<h2 id="如何创建一个对象" data-numberify>如何创建一个对象<a class="anchor ms-1" href="#如何创建一个对象"></a></h2>
<p>我们首先来探讨下如何创建一个 PHP 对象。为此我们将会用到<code>object_and_properties_init</code>之类的一些宏。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// 创建一个SomeClass类型的对象，并且把properties_hashtable中的变量作为其属性值
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#61afef;font-weight:bold">MAKE_STD_ZVAL</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#61afef;font-weight:bold">object_and_properties_init</span>(<span style="color:#e06c75">obj</span>, <span style="color:#e06c75">class_entry_of_SomeClass</span>, <span style="color:#e06c75">properties_hashtable</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span><span style="color:#7f848e">// 创建一个没有属性的对象
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span><span style="color:#61afef;font-weight:bold">MAKE_STD_ZVAL</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span><span style="color:#61afef;font-weight:bold">object_init_ex</span>(<span style="color:#e06c75">obj</span>, <span style="color:#e06c75">class_entry_of_SomeClass</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span><span style="color:#7f848e">// = object_and_properties_init(obj, class_entry_of_SomeClass, NULL)
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span><span style="color:#7f848e">// 创建一个stdClass的对象
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span><span style="color:#61afef;font-weight:bold">MAKE_STD_ZVAL</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span><span style="color:#61afef;font-weight:bold">object_init</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span><span style="color:#7f848e">// = object_init_ex(obj, NULL) = object_and_properties_init(obj, NULL, NULL);
</span></span></span></code></pre></div><p>在上面的例子中，最后一种情况下，当你创建一个<code>stdClass</code>的对象后，通常将会给它添加属性。这时如果使用
<code>zend_update_property</code>之类的函数，是不起作用的，取而代之的是<code>add_property</code>宏函数：</p>]]></description></item><item><title>c语言之struct</title><link>https://blog.liubang.cc/posts/sp/2017-08-21-c%E8%AF%AD%E8%A8%80%E4%B9%8Bstruct/</link><pubDate>Mon, 21 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2017-08-21-c%E8%AF%AD%E8%A8%80%E4%B9%8Bstruct/</guid><description><![CDATA[<h2 id="struct" data-numberify>struct<a class="anchor ms-1" href="#struct"></a></h2>
<blockquote>
<p>在 c 语言中，结构体(struct)是一种复合数据类型，用来将一系列相同或不同类型的变量聚集在同一个内存区间内并赋予同一个名字，使得通过一个指针就能访问集合中的所有成员。结构体中可以包含许多简单或符合数据类型，因此从内存分配上看，有点类似数组，而从变量组织上看，又类似于面向对象编程语言中的类。</p>
</blockquote>

<h3 id="定义-struct" data-numberify>定义 struct<a class="anchor ms-1" href="#定义-struct"></a></h3>
<p>定义一个 struct 非常简单，使用<code>struct</code>关键字即可。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e06c75">student</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>    <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">name</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">age</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>};
</span></span></code></pre></div>
<h3 id="struct-的初始化" data-numberify>struct 的初始化<a class="anchor ms-1" href="#struct-的初始化"></a></h3>
<p>通常有四种常用的 struct 初始化方式。</p>
<p>１．定义并初始化</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#c678dd">struct</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span>    <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">ext</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span>    <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">filetype</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span>} <span style="color:#e06c75">extensions</span>[] <span style="color:#56b6c2">=</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5">5</a></span><span>    {<span style="color:#98c379">&#34;gif&#34;</span>, <span style="color:#98c379">&#34;image/gif&#34;</span>},
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6">6</a></span><span>    {<span style="color:#98c379">&#34;jpg&#34;</span>, <span style="color:#98c379">&#34;image/jpg&#34;</span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7">7</a></span><span>};
</span></span></code></pre></div><p>２．按照成员声明的顺序初始化</p>]]></description></item><item><title>彻底掌握malloc</title><link>https://blog.liubang.cc/posts/sp/2017-03-17-%E5%BD%BB%E5%BA%95%E6%8E%8C%E6%8F%A1malloc/</link><pubDate>Fri, 17 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2017-03-17-%E5%BD%BB%E5%BA%95%E6%8E%8C%E6%8F%A1malloc/</guid><description><![CDATA[<p>说明：参考文献地址 <a href="http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf" target="_blank" rel="noopener noreferrer">A Malloc Tutorial<i class="fas fa-external-link-square-alt ms-1"></i></a></p>

<h2 id="1-简介" data-numberify>1 简介<a class="anchor ms-1" href="#1-简介"></a></h2>
<p><code>malloc</code>是干什么的？如果你连这个名字都没听过，那么你应该先去了解 Unix 环境下的 c 语言开发，然后再来阅读。对一个程序员而言，<code>malloc</code>是一个在 c 语言中用来分配内存的函数，但是大多数人并不知道它背后真正的原理，甚至有些人认为<code>malloc</code>是 c 语言的关键字或者认为它是系统调用。事实上，<code>malloc</code>是一个再简单不过的函数而已，而且只需要很少的操作系统相关知识就可以让我们彻底理解它的原理。</p>
<p>下面来一步步的实现一个简单的<code>malloc</code>函数，从而帮助我们理解其背后运作的原理。因为仅仅作为说明原理之用，所以这里实现的<code>malloc</code>不会太高效，但是足以说明原理。</p>
<p>什么是 malloc</p>
<p><code>malloc(3)</code>是一个用来分配内存块的标准的 c 语言库函数。它遵循以下规则：</p>
<ul>
<li><code>malloc</code>至少分配所需字节数的内存；</li>
<li><code>malloc</code>返回其所分配内存空间(程序可以成功读写的空间)的指针；</li>
<li>一块内存一旦被<code>malloc</code>分配，其他<code>malloc</code>调用不能再分配该内存块的任何部分，除非指向该内存块的指针被释放掉；</li>
<li><code>malloc</code>应该是可控的：他必须能够很快完成分配并返回；</li>
<li><code>malloc</code>同时应该提供重新分配内存块大小和释放内存的功能</li>
</ul>
<p><code>malloc</code>函数必须遵循以下原型：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">malloc</span>(<span style="color:#e5c07b">size_t</span> <span style="color:#e06c75">size</span>);
</span></span></code></pre></div><p>其中<code>size</code>是所需要的内存大小。如果失败（没有足够的内存空间可以分配），应该返回<code>NULL</code>。</p>

<h2 id="2-堆brk-和-sbrk-系统调用" data-numberify>2 堆，brk 和 sbrk 系统调用<a class="anchor ms-1" href="#2-堆brk-和-sbrk-系统调用"></a></h2>
<p>在开始实现第一个<code>malloc</code>函数之前，需要了解内存在大多数多任务操作系统中是如何管理的。这里我们只是做出一个抽象的解释，从大体上去帮助理解，至于很多细节，它们都依赖操作系统原理和硬件相关的知识。</p>

<h3 id="21-进程的内存" data-numberify>2.1 进程的内存<a class="anchor ms-1" href="#21-进程的内存"></a></h3>
<p>每个进程都有自己的虚拟地址空间被 MMU（Memory Management Unit, 内存管理单元）(和内核)动态的转换到物理内存地址空间。这部分空间被划分成了几个部分，我们需要了解的是至少有一部分空间存放代码，一个用来存放局部变量的栈，一部分用来存放常量和全局变量的空间，以及程序的无组织空间我们称之为堆。</p>
<p>堆是一个连续的（依据虚拟地址而言）内存空间，它有三个边界：一个起始点，一个最大限度边界（通过 sys/ressource.h 中的 getrlimit(2)函数和 setrlimit(2)函数来管理）和一个被称为<code>break</code>的结束点。<code>break</code>标记了隐射内存空间的结束，也就是说，虚拟地址空间部分对应着真实的内存空间。下图表示内存组织结构</p>
<p><picture><img class="img-fluid mx-auto d-block" alt="heap" src="https://blog.liubang.cc/images/2017-03-17/heap.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="512" height="114" />
</picture>

</p>
<p>要想实现一个<code>malloc</code>函数，我们需要知道堆的起始点和 break 的位置，然后我们来移动 break。要做到这些，就需要用到两个系统调用，<code>brk</code>和<code>sbrk</code>。</p>

<h3 id="22-brk2和-sbrk2" data-numberify>2.2 brk(2)和 sbrk(2)<a class="anchor ms-1" href="#22-brk2和-sbrk2"></a></h3>
<p>我们可以在这些系统调用的文档中看到相关描述：</p>]]></description></item><item><title>基于c语言的编程语言开发</title><link>https://blog.liubang.cc/posts/compiler/2017-03-15-%E5%9F%BA%E4%BA%8Ec%E8%AF%AD%E8%A8%80%E7%9A%84%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91/</link><pubDate>Wed, 15 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/compiler/2017-03-15-%E5%9F%BA%E4%BA%8Ec%E8%AF%AD%E8%A8%80%E7%9A%84%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91/</guid><description><![CDATA[<h2 id="preface" data-numberify>Preface<a class="anchor ms-1" href="#preface"></a></h2>
<p>当今世道，各种高级语言百花齐放。然而会有人发出这样的疑问&ndash;计算机真的能够识别这么多语言吗？稍微有点常识的人都知道，这显然是不可能滴！在计算机的世界里，他们能够直接识别的只有机器语言。然而，由于机器语言对人类不够友好，所以人们才发明了汇编，c，Java&hellip;许许多多的人类易读的编程语言，所以我个人对编程语言的理解一直是其实他们就是机器语言的语法糖，而编程语言的创造过程，就是定义一种合理的，没有二义性的语法规则，然后就是通过直接或间接的方式实现该语法到机器语言的转换过程。既然是这样的话，那么我们就很容易想到，计算机语言是一个自我完善的过程：首先我们定了一种非常简单的 x1(这里只是用来举例说明，有没有 x 语言有待考证)语言，然后用机器语言实现了这个非常简单的 x1 语言的编译器，创造了 x1 语言，实现了非常简单的新特性，然后我们再用 x1 语言(相对于机器语言较高级)实现了另一些新的特性的 x2 语言的编译器，创造了 x2 语言，&hellip;，如此下去，人们创造了汇编语言，从而创造了 c 语言，接着创造了世界上最好的语言 PHP(不知道是不是真的，反正大家都习惯这么说)。
在各种高级语言越来越强大的今天，我们可能很难再会去接触最原始的东西，高度封装确实提高了生产力，降低了学习成本，但是也使得现代程序员将太多精力花在了各种说明书上，而不清楚其本质。
毕业一年多，工作了一年多，对于计算机编程有了自己的看法，不再像在大学的时候认识的那样肤浅，反而觉得大学中学习的知识才是真正的干货，不禁感叹曾经浪费掉了大好光阴。好在陶渊明有词云：“悟已往之不谏，知来者之可追”。
闲暇之余，扒开 PHP(这里之所以是 PHP 并不因为他是世界上最好的语言，只是因为我目前从事的是 PHP 开发的工作而已)源码，了解了其内部构造和实现原理，百看不一练。今天就初步学习 yacc/lex 了，记录在我的博客中，以便以后翻阅巩固。</p>

<h2 id="过程简述" data-numberify>过程简述<a class="anchor ms-1" href="#过程简述"></a></h2>
<p>一般来说编程语言的解释执行过程如下：</p>
<p><strong>ONE</strong>. 词法分析
将源代码拆分成若干 Token 的过程</p>
<p><strong>TWO</strong>.语法分析
将 Token 构建成 Syntax Tree 的过程</p>
<p><strong>THREE</strong>.生成执行码
生成可执行文件</p>

<h2 id="yaccyet-another-compiler-compiler" data-numberify>yacc（Yet Another Compiler Compiler）<a class="anchor ms-1" href="#yaccyet-another-compiler-compiler"></a></h2>
<p>下面是 wikipedia 中对 yacc 的描述</p>
<blockquote>
<p>Yacc is a computer program for the Unix operating system. It is a Look Ahead Left-to-Right (LALR) parser generator, generating a parser, the part of a compiler that tries to make syntactic sense of the source code, specifically a LALR parser, based on an analytic grammar written in a notation similar to Backus–Naur Form (BNF). Yacc itself used to be available as the default parser generator on most Unix systems, though it has since been supplanted as the default by more recent, largely compatible, programs.</p>]]></description></item><item><title>PHP扩展开发之call_user_func原理和回调函数的实现</title><link>https://blog.liubang.cc/posts/php/2017-03-09-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8Bcall-user-func%E5%8E%9F%E7%90%86%E5%92%8C%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9E%E7%8E%B0/</link><pubDate>Thu, 09 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-03-09-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8Bcall-user-func%E5%8E%9F%E7%90%86%E5%92%8C%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9E%E7%8E%B0/</guid><description><![CDATA[<h2 id="函数调用" data-numberify>函数调用<a class="anchor ms-1" href="#函数调用"></a></h2>
<p>很多时候，我们需要通过函数名来调用函数，并传递参数，或者把匿名函数作为函数的参数传递，实现回调。当我们在遇到这样的需求的时候，用 php 代码实现起来肯定是非常容易和简单的。但是，当我们在用 c 语言编写 php 扩展的时候，如何来实现这样的功能呢？下面就一起来深入了解 php 内核，看看如何实现。</p>
<p>在 Zend 引擎中，给我们提供了<code>zend_call_function</code>,<code>call_user_function</code>以及<code>call_user_function_ex</code>函数来帮助我们实现函数调用。在<code>zend_API.h</code>文件中，我们可以看到如下函数原型的声明：</p>
<!-- more -->
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e06c75">ZEND_API</span> <span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">zend_call_function</span>(<span style="color:#e06c75">zend_fcall_info</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">fci</span>, <span style="color:#e06c75">zend_fcall_info_cache</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">fci_cache</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span><span style="color:#e06c75">ZEND_API</span> <span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">call_user_function</span>(<span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_table</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">object_pp</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_name</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">retval_ptr</span>, <span style="color:#e06c75">zend_uint</span> <span style="color:#e06c75">param_count</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">params</span>[] <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span><span style="color:#e06c75">ZEND_API</span> <span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">call_user_function_ex</span>(<span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_table</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">object_pp</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_name</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">retval_ptr_ptr</span>, <span style="color:#e06c75">zend_uint</span> <span style="color:#e06c75">param_count</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">params</span>[], <span style="color:#e5c07b">int</span> <span style="color:#e06c75">no_separation</span>, <span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">symbol_table</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span></code></pre></div><p>从函数的参数上来看，显然<code>zend_call_function</code>需要的参数很少，而其他两个都需要一堆参数，所以，我们可能会想，达到相同的效果为什么参数上有如此大的区别，于是带着这个疑问我们来解刨<code>zend_fcall_info</code>结构体。同样在<code>zend_API.h</code>中会看到如下结构体的定义：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_fcall_info</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>        <span style="color:#e5c07b">size_t</span> <span style="color:#e06c75">size</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>        <span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_table</span>; <span style="color:#7f848e">//函数表
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_name</span>;	   <span style="color:#7f848e">//函数，可以是函数名，也可以直接是匿名函数本身
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>        <span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">symbol_table</span>;   <span style="color:#7f848e">//符号表
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">retval_ptr_ptr</span>;	   <span style="color:#7f848e">//返回值
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span>        <span style="color:#e06c75">zend_uint</span> <span style="color:#e06c75">param_count</span>;     <span style="color:#7f848e">//参数个数
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">***</span><span style="color:#e06c75">params</span>; 		   <span style="color:#7f848e">//参数，数组
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object_ptr</span>;		   <span style="color:#7f848e">//调用对象方法时候需要传调用的对象
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span>        <span style="color:#e06c75">zend_bool</span> <span style="color:#e06c75">no_separation</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>} <span style="color:#e06c75">zend_fcall_info</span>;
</span></span></code></pre></div><p>不难发现，原来是把相关字段封装到了结构体中了，所以显得参数数量少，实际上该有的都有。</p>]]></description></item></channel></rss>