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

<channel>
	<title>风雪之隅</title>
	<atom:link href="http://www.laruence.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.laruence.com</link>
	<description>PHP源码分析,Zend引擎分析,Web相关技术研究,Web技术分享--左手代码 右手诗</description>
	<lastBuildDate>Mon, 08 Mar 2010 10:02:25 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>浏览器缓存机制</title>
		<link>http://www.laruence.com/2010/03/05/1332.html</link>
		<comments>http://www.laruence.com/2010/03/05/1332.html#comments</comments>
		<pubDate>Fri, 05 Mar 2010 06:19:51 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[转载]]></category>
		<category><![CDATA[cache-control]]></category>
		<category><![CDATA[浏览器]]></category>
		<category><![CDATA[缓存]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1332</guid>
		<description><![CDATA[<style>
#excerpt_random_111 {
   border:1px #000 solid;
   border-collapse:collapse;
}
#excerpt_random_111 td {
   border:1px #000 solid;
   padding:0;
}
</style>
<table id="excerpt_random_111">
	<tr>
                <caption>关键结论</caption>
		<td width="12%">打开新窗口</td>
		<td>如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如：Cache-control: max-age=5 表示当访问此网页后的5秒内再次访问不会去服务器.</td>
	</tr>
	<tr>
		<td>在地址栏回车</td>
		<td>如果值为private或must-revalidate,则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。 </td>
	</tr>
	<tr>
		<td>按后退按扭</td>
		<td>如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问.</td>
	</tr>
	<tr>
		<td>按刷新按扭</td>
		<td>无论为何值,都会重复访问. </td>
	</tr>
</table>
]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2010/03/05/1332.html"  title="Permanet Link to 浏览器缓存机制" >http://www.laruence.com/2010/03/05/1332.html</a></li>
<li>文章转自: http://harry.javaeye.com/blog/605749</li>
</ul></div>
<style>
	#random_2832398324 table {
		border:1px #555 solid; 
		border-collapse:collapse; 
		margin-top:10px;
	}
	#random_2832398324 td {
		border:1px #555 solid; 
		padding:1px;
	}
	#random_2832398324 th {
		background:none;
		border:1px #555 solid; 
		text-align:center;
	}
</style>
<div id="random_2832398324" >
	<b>Cache-Control</b></p>
<p>	Cache-Control 是最重要的规则。这个字段用于指定所有缓存机制在整个请求/响应链中必须服从的指令。这些指令指定用于阻止缓存对请求或响应造成不利干扰的行为。这些指令通常覆盖默认缓存算法。缓存指令是单向的，即请求中存在一个指令并不意味着响应中将存在同一个指令。</p>
<p>	cache-control 定义是：Cache-Control = &#8220;Cache-Control&#8221; &#8220;:&#8221; cache-directive。表 1 展示了适用的值。</p>
<table>
<caption>
			表 1. 常用 cache-directive 值<br/>
		</caption>
<tr>
<th>Cache-directive</th>
<th>说明</th>
</tr>
<tr>
<td>public</td>
<td>所有内容都将被缓存</td>
</tr>
<tr>
<td>private</td>
<td>内容只缓存到私有缓存中</td>
</tr>
<tr>
<td>no-cache</td>
<td>所有内容都不会被缓存</td>
</tr>
<tr>
<td>no-store</td>
<td>所有内容都不会被缓存到缓存或 Internet 临时文件中</td>
</tr>
<tr>
<td>must-revalidation/proxy-revalidation</td>
<td>如果缓存的内容失效，请求必须发送到服务器/代理以进行重新验证</td>
</tr>
<tr>
<td>max-age=xxx (xxx is numeric)</td>
<td>缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高</td>
</tr>
</table>
<p>	表 2 表明在不同的情形下，浏览器是将请求重新发送到服务器还是使用缓存的内容。</p>
<table>
<caption>
			表 2. 对 cache-directive 值的浏览器响应<br/>
		</caption>
<tr>
<th>Cache-directive</th>
<th>打开一个新的浏览器窗口</th>
<th>在原窗口中单击 Enter 按钮</th>
<th>刷新</th>
<th>单击 Back 按钮</th>
</tr>
<tr>
<td>public</td>
</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器</td>
<td>浏览器呈现来自缓存的页面</td>
</tr>
<tr>
<td>private</td>
<td>浏览器重新发送请求到服务器</td>
<td>第一次，浏览器重新发送请求到服务器；此后，浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器</td>
<td>浏览器呈现来自缓存的页面</td>
</tr>
<tr>
<td>no-cache/no-store</td>
<td>浏览器重新发送请求到服务器</td>
<td>浏览器重新发送请求到服务器</td>
<td>浏览器重新发送请求到服务器</td>
<td>浏览器重新发送请求到服务器</td>
</tr>
<tr>
<td>must-revalidation/proxy-revalidation</td>
<td>浏览器重新发送请求到服务器</td>
<td>第一次，浏览器重新发送请求到服务器；此后，浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器</td>
<td>浏览器呈现来自缓存的页面</td>
</tr>
<tr>
<td>max-age=xxx (xxx is numeric)</td>
<td>在 xxx 秒后，浏览器重新发送请求到服务器</td>
<td>在 xxx 秒后，浏览器重新发送请求到服务器</td>
<td>浏览器重新发送请求到服务器</td>
<td>在 xxx 秒后，浏览器重新发送请求到服务器</td>
</tr>
</tr>
</table>
<p>Cache-Control是关于浏览器缓存的最重要的设置，因为它覆盖其他设置，比如 Expires 和 Last-Modified。另外，由于浏览器的行为基本相同，这个属性是处理跨浏览器缓存问题的最有效的方法。</p>
<p><b>失效</b></p>
<p>Expires 头部字段提供一个日期和时间，响应在该日期和时间后被认为失效。失效的缓存条目通常不会被缓存（无论是代理缓存还是用户代理缓存）返回，除非首先通过原始服务器（或者拥有该实体的最新副本的中介缓存）验证。（注意：cache-control max-age 和 s-maxage 将覆盖 Expires 头部。）</p>
<p>Expires 字段接收以下格式的值：“Expires: Sun, 08 Nov 2009 03:37:26 GMT”。如果查看内容时的日期在给定的日期之前，则认为该内容没有失效并从缓存中提取出来。反之，则认为该内容失效，缓存将采取一些措施。表 3-6 表明针对不同用户操作的不同浏览器的行为。</p>
<table>
<caption>
		表 3. 当用户打开一个新的浏览器窗口时的失效操作<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容没有失效</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
</tr>
<tr>
<td>内容失效</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<table>
<caption>
		表 4. 当用户在原始浏览器窗口中单击 Enter 按钮时的失效操作<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容没有失效</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
</tr>
<tr>
<td>内容失效</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<table>
<caption>
		表 5. 当用户按 F5 键刷新页面时的失效操作<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容没有失效</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
</tr>
<tr>
<td>内容失效</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<table>
<caption>
		表 6. 当用户单击 Back 或 Forward 按钮时的失效操作<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容没有失效</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
</tr>
<tr>
<td>内容失效</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<p>注意：所有浏览器都假定为使用默认设置运行。</p>
<p><b>Last-Modified/E-Tag</b></p>
<p>Last-Modified 实体头部字段值通常用作一个缓存验证器。简单来说，如果实体值在 Last-Modified 值之后没有被更改，则认为该缓存条目有效。ETag 响应头部字段值是一个实体标记，它提供一个 “不透明” 的缓存验证器。这可能在以下几种情况下提供更可靠的验证：不方便存储修改日期；HTTP 日期值的 one-second 解决方案不够用；或者原始服务器希望避免由于使用修改日期而导致的某些冲突。</p>
<p>不同的浏览器有不同的配置行为。表 7-10 表明针对不同用户操作的不同浏览器的行为。</p>
<table>
<caption>
		表 7. 当用户打开一个新的浏览器窗口时的 Last-Modified E-Tag 操作<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容自上次访问以来没有被修改</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
</tr>
<tr>
<td>内容自上次访问以来已经被修改</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<table>
<caption>
		表 8. 当用户在原始浏览器窗口中单击 Enter 按钮时的 Last-Modified E-Tag 操作<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容自上次访问以来没有被修改</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
</tr>
<tr>
<td>内容自上次访问以来已经被修改</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<table>
<caption>
		表 9. 当用户按 F5 键刷新页面时的 Last-Modified E-Tag 操作<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容自上次访问以来没有被修改</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
<td>浏览器重新发送请求到服务器。返回代码是 304</td>
</tr>
<tr>
<td>内容自上次访问以来已经被修改</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<table>
<caption>
		表 10. 没有缓存设置且用户单击 Back 或 Forward 按钮<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>内容自上次访问以来没有被修改</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
</tr>
<tr>
<td>内容自上次访问以来已经被修改</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器呈现来自缓存的页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<p>注意：所有浏览器都假定使用默认设置运行。</p>
<p>不进行任何缓存相关设置</p>
<p>如果您不定义任何缓存相关设置，则不同的浏览器有不同的行为。有时，同一个浏览器在相同的情形下每次运行时的行为都是不同的。情况可能很复杂。另外，有些不该缓存的内容如果被缓存，将会导致安全问题。<br/>
不同的浏览器有不同的行为。表 11 展示了不同的浏览器行为。</p>
<table>
<caption>
		表 11. 没有缓存设置且用户打开一个新的浏览器窗口<br/>
	</caption>
<tr>
<th></th>
<th>Firefox 3.5</th>
<th>IE 8</th>
<th>Chrome 3</th>
<th>Safari 4</th>
</tr>
<tr>
<td>打开一个新页面</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
<tr>
<td>在原始窗口中单击 Enter 按钮</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器呈现来自缓存的页面。</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
<tr>
<td>按 F5 键刷新</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
<tr>
<td>单击 Back 或 Forward 按钮</td>
<td>浏览器呈现来自缓存的页面。</td>
<td>浏览器呈现来自缓存的页面。</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
<td>浏览器重新发送请求到服务器。返回代码是 200</td>
</tr>
</table>
<p>注意：所有浏览器都假定使用默认设置运行。</p>
<p>最后, 概括下关键的结论:</p>
<table>
<caption>关键结论</caption>
<tr>
<td width="12%" >打开新窗口</td>
<td>如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如：Cache-control: max-age=5 表示当访问此网页后的5秒内再次访问不会去服务器.</td>
</tr>
<tr>
<td>在地址栏回车</td>
<td>如果值为private或must-revalidate,则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。 </td>
</tr>
<tr>
<td>按后退按扭</td>
<td>如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问.</td>
</tr>
<tr>
<td>按刷新按扭</td>
<td>无论为何值,都会重复访问. </td>
</tr>
</table>
</div>
<hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/03/05/1332.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NCR与HTML Entities</title>
		<link>http://www.laruence.com/2010/02/25/1324.html</link>
		<comments>http://www.laruence.com/2010/02/25/1324.html#comments</comments>
		<pubDate>Thu, 25 Feb 2010 06:35:58 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[Character Entities References]]></category>
		<category><![CDATA[HTML Entity]]></category>
		<category><![CDATA[NCR]]></category>
		<category><![CDATA[Numeric Character Reference]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1324</guid>
		<description><![CDATA[Character Entities References(HTML Entities)和Numeric Character Reference(NCR)都是让你可以在页面中显示特殊的字符的编码方式, 俩者之间有什么异同呢?]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/02/25/1324.html"  title="Permanet Link to NCR与HTML Entities" >http://www.laruence.com/2010/02/25/1324.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>Character Entities References(HTML Entities)和Numeric Character Reference(NCR)都是让你可以在页面中显示特殊的字符的编码方式, 俩者之间有什么异同呢?</p>
<p>一个Numeric Character Reference编码是由一个与号(&#038;)跟着一个井号(#), 然后跟着这个字符的Unicode编码值, 最后跟着一个分号组成的, 如:</p>
<pre name="code"  class="sh_html"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&amp;#nnnn;
或者
&amp;#xhhhh;
</pre>
<p>其中, nnnn是字符编码的十进制表示, 而hhhh是字符的16进制表示. </p>
<p>另外要注意的是x在xml中必须是小写的.而hhhh可以大小写混用, 另外nnnn和hhhh也可以有前导零.</p>
<p>与NCR不同, HTML Entites是使用一个与号(&#038;),跟着这个字符的名字, 然后以分号(;)结尾来表示一个字符, 这个字符的名字必须是在HTML中已经定义的,比如:</p>
<pre name="code"  class="sh_html"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&amp;amp;  //&amp;
&amp;copy; //©
</pre>
<p>或者对于XML来说是在DTD中定义过的, 类似:</p>
<pre name="code"  class="sh_html"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;!ENTITY nbsp   CDATA &quot;&amp;#160;&quot; -- no-break space = non-breaking space,
                                  U+00A0 ISOnum --&gt;
&lt;!ENTITY iexcl  CDATA &quot;&amp;#161;&quot; -- inverted exclamation mark, U+00A1 ISOnum --&gt;
&lt;!ENTITY cent   CDATA &quot;&amp;#162;&quot; -- cent sign, U+00A2 ISOnum --&gt;
&lt;!ENTITY pound  CDATA &quot;&amp;#163;&quot; -- pound sign, U+00A3 ISOnum --&gt;
&lt;!ENTITY curren CDATA &quot;&amp;#164;&quot; -- currency sign, U+00A4 ISOnum --&gt;
&lt;!ENTITY yen    CDATA &quot;&amp;#165;&quot; -- yen sign = yuan sign, U+00A5 ISOnum --&gt;
&lt;!ENTITY brvbar CDATA &quot;&amp;#166;&quot; -- broken bar = broken vertical bar,
                                  U+00A6 ISOnum --&gt;
</pre>
<p>其中, 名字是大小写敏感的. 比如:</p>
<pre name="code"  class="sh_html"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&amp;Aring; // Å
而:
&amp;aring; // å
</pre>
<p>最后, 在PHP中, 可以通过htmlentites或者mb_convert_encoding($str, &#8220;HTML-ENTITIES&#8221;, from encoding)来获得一个字符的HTML entities,</p>
<p>也可以通过mb_encode_numericentity(), 或者手动获取unicode值添加&#***, 来获得一个字符的NCR编码.<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_html.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_html.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_html.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_html.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/02/25/1324.html#comment-2464" >2010/02/28</a>, <a href="http://www.js4j.com"  rel="external nofollow"  class="url" >技术世界</a> writes: 沙发,再慢慢看~~~</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/02/25/1324.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Apache2中俩种设置PHP的异同</title>
		<link>http://www.laruence.com/2010/02/23/1310.html</link>
		<comments>http://www.laruence.com/2010/02/23/1310.html#comments</comments>
		<pubDate>Tue, 23 Feb 2010 06:18:19 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php源码]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1310</guid>
		<description><![CDATA[  Apache2开始引入了Hook方式, 对应的在PHP中也提供了apache2handler这种sapi. 
   

   和我之前介绍过的PHP lifecycle不同, 这种情况下的PHP, 通过注册handler钩子, 从而可以在handler hook阶段有机会处理请求, 通过判断请求的handler, 来确定是否需要处理, 如果需要就会调用自身的处理器.

    那么, 这种情况下也就有了多种配置方法,  主要考虑如下俩种方式...
]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/02/23/1310.html"  title="Permanet Link to Apache2中俩种设置PHP的异同" >http://www.laruence.com/2010/02/23/1310.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   Apache2开始引入了Hook方式, 对应的在PHP中也提供了apache2handler这种sapi. </p>
<p>   和我之前介绍过的PHP lifecycle不同, 这种情况下的PHP, 通过注册handler钩子, 从而可以在handler hook阶段有机会处理请求, 通过判断请求的handler, 来确定是否需要处理, 如果需要就会调用自身的处理器.</p>
<p>    那么, 这种情况下也就有了多种配置方法,  主要考虑如下俩种方式(第二种可以有多种变种):</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
第一种:  AddType application/x-httpd-php .php
第二种:
      &lt;FilesMatch \.php$&gt;
          SetHandler application/x-httpd-php
     &lt;/FilesMatch&gt;
</pre>
<p>   首先来说, 这俩中方式的起作用的时刻不同,  对于第一种方式来说, 他是在type_check钩子阶段起作用的, 也就是在apache2src/modules/http/mod_mime.c中, 通过注册type_checker钩子, 加入find_ct(content_type), 在find_ct中, 通过配置文件中的mime映射, 或者是通过addType指令增加的映射, 根据文件的扩展来填充请求中的handler字段:</p>
<p>   而对于第二种方式, 是在fixup钩子阶段, 通过注册fixups钩子阶段加入core_override_type(apache2src/server/core.c)函数, 来将目录级的配置指令生效.</p>
<p>   而fixups钩子是晚于type_checker钩子的, 也是handler钩子之前最后的一个可以利用的钩子. 所以如果同时采用1,2俩种方式, 那么第二种方式会覆盖第一种方式设置的handler.</p>
<p>    其次, 俩种方式依赖的数据结构不同, 第一种方式依赖的是一个全局的mime对照表extension_mappings, 这个表由mime配置文件和AddType指令而来.</p>
<p>    而对于第二种方式, 它是根据配置文件构造的dir_config而来:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
....
  core_dir_config *conf =
        (core_dir_config *)ap_get_module_config(r-&gt;per_dir_config,
                                                &amp;core_module);

    /* Check for overrides with ForceType / SetHandler
     */
    if (conf-&gt;mime_type &amp;&amp; strcmp(conf-&gt;mime_type, &quot;none&quot;))
        ap_set_content_type(r, (char*) conf-&gt;mime_type);

    if (conf-&gt;handler &amp;&amp; strcmp(conf-&gt;handler, &quot;none&quot;))
        r-&gt;handler = conf-&gt;handler;
.....
</pre>
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script></p>
<hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/02/23/1310.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook性能大提升的秘密：HipHop</title>
		<link>http://www.laruence.com/2010/02/03/1283.html</link>
		<comments>http://www.laruence.com/2010/02/03/1283.html#comments</comments>
		<pubDate>Wed, 03 Feb 2010 03:00:08 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[转载]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[hiphop]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1283</guid>
		<description><![CDATA[评论: 从最早听说Facebook搞一个神奇的项目开始, 我就在猜测它会怎么做? 想APC一样编译成Opcode? 或者是象phc从Opcode再次加工. 但, 今天看到的介绍, 让我还是有点出乎意料...哪就是- HipHop提供编译器, 让你可以"用PHP的语法写C++代码".

以下为转载原文:Facebook神秘的PHP项目HipHop for  PHP终于揭开面纱。这个项目由一个PHP到C++的转换程序，一个重新实现的PHP运行库，和许多常用PHP扩展的重写版本构成，目的是旨在加速和优化 PHP。]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2010/02/03/1283.html"  title="Permanet Link to Facebook性能大提升的秘密：HipHop" >http://www.laruence.com/2010/02/03/1283.html</a></li>
<li>文章转自: <a href="http://www.csdn.net/"  target="_blank" >CSDN</a></li>
</ul></div>
<p>评论: 从最早听说Facebook搞一个神奇的项目开始, 我就在猜测它会怎么做? 想APC一样编译成Opcode? 或者是象phc从Opcode再次加工. 但, 今天看到的介绍, 让我还是有点出乎意料&#8230;哪就是- HipHop提供编译器, 让你可以&#8221;用PHP的语法写C++代码&#8221;.</p>
<p>以下为转载原文:<br/>
<a href="http://www.laruence.com/wp-content/uploads/20100203-044306-pic1.png" ><img class="alignright size-full wp-image-1286"  title="20100203-044306-pic1"  src="http://www.laruence.com/wp-content/uploads/20100203-044306-pic1.png"  alt=""  width="213"  height="278" /></a>Facebook神秘的PHP项目HipHop for  PHP终于揭开面纱。这个项目由一个PHP到C++的转换程序，一个重新实现的PHP运行库，和许多常用PHP扩展的重写版本构成，目的是旨在加速和优化 PHP。</p>
<p>用<a href="http://developers.facebook.com/news.php?story=358blog=1" >Facebook 官方博客</a>（无法直接访问）上项目负责人赵海平（北大1987届遗传与分子生物专业，普林斯顿计算机科学博士）的话说，HipHop项目对 Facebook影响巨大。它目前已经支撑了Facebook 90%的Web流量。由于HipHop，Facebook  Web服务器上的CPU使用平均减少了50%，从而大大减少了服务器的需求。为了让这一改进也惠及社区，他们决定将之开源，希望能够进一步帮助提高更多大 型复杂PHP网站的可伸缩性。</p>
<p><strong>PHP和Facebook的问题</strong></p>
<p>众所周知，Facebook的前端主要是用PHP写的。赵海平说，过去六年Facebook从PHP语言的进展上获益良多。PHP非常简单，易学易 用，好读好调试，因此新工程师成长很快，有利地促进了Facebook的更快的创新。<br/>
<a href="http://www.laruence.com/wp-content/uploads/20100203-043453-pic1.jpg" ><img class="alignright size-full wp-image-1287"  title="20100203-043453-pic1"  src="http://www.laruence.com/wp-content/uploads/20100203-043453-pic1.jpg"  alt=""  width="200"  height="200" /></a></p>
<p>PHP是一种脚本语言，其好处是编程效率高，能够支持产品的快速迭代。但是与传统的编译语言相比，脚本语言的CPU和内存使用效率不好。随着 Ajax技术的广泛采用，加上SNS对动态要求较高，这些缺点更显得突出。对于每月超过4000亿次PV的Facebook来说，如何实现扩展，尤其具有 挑战性。</p>
<p>常见的办法是直接用C++重写PHP应用中比较复杂的部分，作为PHP扩展。实际上，PHP就转变为一种胶水语言，连接前端HTML和C++应用逻 辑。从技术角度讲这也没有问题，但是增加了技能需求，能够在整个应用上工作的工程师数量就大大减少了。学习C++只是编写PHP扩展的第一步，接下来还要 理解Zend  API。由于Facebook的工程团队较小，每个工程师要支持100万以上的用户。有些代码不是团队里每个人都能看懂，这对于Facebook是无法接 受的。</p>
<p>Facebook网站本身的可伸缩性更具挑战性，因为几乎每次页面浏览都是有个性化体验的登录用户发起。浏览主页  时，系统需要查询所有朋友、朋友最重要的状态更新、  根据隐私设置筛选结果，然后还要显示评论、照片等等动态，这一切都需要在一秒内完  成。</p>
<p>自2007年以来，Facebook曾写过几种不同办法解决这些问题。其中包括用另   一种语言重写Facebook，但是由于开发的复杂性和速度等原因，未能实现。他们还重写了PHP的核心部分Zend引擎，并提交给了PHP项目，但最终 还是没有获得所需的性能。最后，他们选择了HipHop，终于得偿所愿。</p>
<p>有了HipHop，工程师可以编写代码，用PHP编写组合最后页面的逻辑，并能够继续快速迭代，同时后端服务使用C++, Erlang,  Java, Py  thon编写，提供新闻提要、搜索、聊天和其他核心功能。</p>
<p><strong>HipHop开发故事</strong></p>
<p>赵海平透露，项目最初是来自几年前Facebook公司一次Hackathon活动（员工在一个晚上自由发挥，实验新的想法），他手工将PHP转换 为C++代码，虽然语法上很类似，但是无论是CPU还是内存使用，转换后的C++代码都大大优于PHP。于是他想，如果构建一个系统，编程实现转换，会怎 么样呢？</p>
<p>在此之前，已经有了不少改善PHP性能的方法。Zend引擎在运行时转换PHP源代码为运行在Zend虚拟机上的opcode。开源项目APC和 eAccelerator将输出缓存，为大多数PHP网站所使用。此外，还有Zend  Server这样的商业产品，通过opcode优化和缓存，提高PHP速度。赵海平选择了另一条道路，将PHP直接转为C++，然后再变成本地机器码。当 然，有许多开源项目也是同样的思路，Roadsend和phc编译为C，Quercus编译为Java，而Phalanger编译为.NET。</p>
<p>Hackathon之后8个月，赵海平拿出了原型，足以说明这条路可以走通，编译后的代码的确更快。不久，Iain  Proctor和Minghui  Yang加入进来。接下来又开发了10个月，在生产服务器上测试了6个月。然后正式上线部署，6个月之后，Facebook  90%以上的Web流量都使用了HipHop。</p>
<p>按赵海平的说法，凭借HipHop，Facebook  Web服务器上的CPU使用平均减少了50%，从而大大减少了服务器的需求。项目对Facebook影响巨大。为了让这一改进也惠及社区，他们决定将之开 源，希望能够进一步帮助提高更多大型复杂PHP网站的可伸缩性。</p>
<div id="attachment_1288"  class="wp-caption aligncenter"  style="width: 660px" ><a href="http://www.laruence.com/wp-content/uploads/20100203-050719-pic1.jpg" ><img class="size-full wp-image-1288"  title="20100203-050719-pic1"  src="http://www.laruence.com/wp-content/uploads/20100203-050719-pic1.jpg"  alt=""  width="650"  height="406" /></a><p class="wp-caption-text" >Hiphop for PHP transformation process</p></div>
<p><strong>HipHop的原理</strong></p>
<p>HipHop将PHP代码转换为高度优化的C++代码，然后再用g++编译器编译。它可以保持语义等效地执行源代码，但为了提高性能，牺牲了一些很 少用到的特性，比如eval()。</p>
<p>HipHop开发中的主要困难在于，在PHP和C++这两种很不一样的语言之间怎么实现转换。虽然PHP也可以写一些很巧妙的动态特性，但是大多数 PHP代码还是非常简单的。if (&#8230;) {&#8230;} else {..} 比foo($x) { include $x; }  肯定更常见。这为性能提高提供了机会。HipHop生成的代码尽可能地使用函数和变量的静态绑定。同时，还使用类型推演来选出变量最可能对应的某个类型， 从而节省内存。</p>
<p>转换过程分三步：</p>
<p>1. 静态分析。收集声明关系和依赖关系等信息。</p>
<p>2. 类型推演。选择最合适的类型，是C++的标量？还是String, Array, classes, Object或者Variant。</p>
<p>3. 代码生成。大部分直接将PHP语句和表达式对应为C++的语句和表达式。</p>
<p>在开发过程中，还有一个副产品：HPHPi，是一个实验性的解释器。通过它，不编译PHP源代码也可以运行。它已经用于HipHop自身的调试中。</p>
<p>HipHop在保持了PHP优点的同时，也兼得了C++的性能优势。项目总共有30万行代码，5000多个单元测试。所有这些都将以PHP开源许可 证形式发布到GitHub。</p>
<p>更多信息，可以申请加入HipHop的邮件列表：</p>
<p><a href="http://groups.google.com/group/hiphop-php-dev" >http://groups.google.com/group/hiphop-php-dev</a></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/02/03/1283.html#comment-2458" >2010/02/04</a>, <a href="http://www.909520.cn"  rel="external nofollow"  class="url" >侯良</a> writes: 这个是个好东西。
一定要把它学会 。</li><li><a href="http://www.laruence.com/2010/02/03/1283.html#comment-2459" >2010/02/05</a>, <a href="http://www.nnbizhi.com"  rel="external nofollow"  class="url" >cnan</a> writes: 感觉想不想google的用java写JavaScript</li><li><a href="http://www.laruence.com/2010/02/03/1283.html#comment-2460" >2010/02/10</a>, yufeng writes: 前一阵子看到了，不过没有这篇文章详细，据说还要开源的。</li><li><a href="http://www.laruence.com/2010/02/03/1283.html#comment-2461" >2010/02/11</a>, jimmy writes: 是 c++ 而不是 c 的原因是什么呢，laruence.</li><li><a href="http://www.laruence.com/2010/02/03/1283.html#comment-2462" >2010/02/21</a>, Anonymous writes: 本来我想用的是C，而不是C++。
看来慢了一步了。</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/02/03/1283.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>注意PHP5.2.11之后的json_decode</title>
		<link>http://www.laruence.com/2010/02/02/1272.html</link>
		<comments>http://www.laruence.com/2010/02/02/1272.html#comments</comments>
		<pubDate>Tue, 02 Feb 2010 10:32:58 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[5.2.11]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[json_decode]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1272</guid>
		<description><![CDATA[<p>
    在PHP5.2.6以前, json_decode一个字符串, 将会返回字符串本身.
<coolcode lang="php" linenum="off">
php -r "var_dump(json_decode('laruence'));"
//输出
string(8)"laruence";
</coolcode>
   但是, 不知道是不是因为之前在php bug中, 有人提议对于这种情况, 因为字符串不是合法的json格式的串, 所以应该出错, 返回NULL(<a href="http://bugs.php.net/bug.php?id=45989" target="_blank">http://bugs.php.net/bug.php?id=45989</a>). 所以在PHP5.2.11之后(具体是从哪个版本开始, 我回头再验证), 竟然返回NULL了.
<coolcode lang="php" linenum="off">
php -r "var_dump(json_decode('laruence'));"
//输出
NULL
</coolcode>
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/02/02/1272.html"  title="Permanet Link to 注意PHP5.2.11之后的json_decode" >http://www.laruence.com/2010/02/02/1272.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    在PHP5.2.6以前, json_decode一个字符串, 将会返回字符串本身.</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
php -r &quot;var_dump(json_decode('laruence'));&quot;
//输出
string(8)&quot;laruence&quot;;
</pre>
<p>   但是, 不知道是不是因为之前在php bug中, 有人提议对于这种情况, 因为字符串不是合法的json格式的串, 所以应该出错, 返回NULL(<a href="http://bugs.php.net/bug.php?id=45989"  target="_blank" >http://bugs.php.net/bug.php?id=45989</a>). 所以在PHP5.2.11之后(具体是从哪个版本开始, 我回头再验证), 竟然返回NULL了.</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
php -r &quot;var_dump(json_decode('laruence'));&quot;
//输出
NULL
</pre>
<p>    但值得注意的是, 对于numeric_string, 都是返回numeric_string的数值形式.</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
php -r &quot;var_dump(json_decode('0x3f34'));&quot;
//输出
int(16180)
</pre>
<p>    另外, 在PHP5.3以后,可以通过json_last_error()来验证转换是否正确.
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2452" >2010/02/02</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: 因为之前把几个PHP版本的安装路径搞混了, 看错了5.3的实现, 误以为5.3中和5.2.6一致, 抱歉给大家造成误解.</li><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2453" >2010/02/02</a>, <a href="http://www.9enjoy.com"  rel="external nofollow"  class="url" >enjoy</a> writes: 我在5.2.8下试了下。
php -r "var_dump(json_decode('laruence'));"
//输出
string(8) "laruence"</li><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2454" >2010/02/02</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @enjoy 我看到在5.2.9的release notes中有关于json_decode的, 但不是和这个相关的.</li><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2455" >2010/02/02</a>, <a href="http://www.deepseath.com/"  rel="external nofollow"  class="url" >Deepseath</a> writes: 类似这样频繁改动的函数，我会重新写个函数。呵呵，虽然麻烦但兼容性相对好一些，而且一旦确定环境了，进行优化也相对容易一些^_^</li><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2456" >2010/02/02</a>, <a href="http://sanmuding.com"  rel="external nofollow"  class="url" >Anders</a> writes: guoxiaod@guoxiaod&gt;php -r 'var_dump(json_decode("\"abc\""));'
string(3) "abc"
guoxiaod@guoxiaod&gt;php -v 
PHP 5.2.10-2ubuntu6.4 with Suhosin-Patch 0.9.7 (cli) (built: Jan  6 2010 22:41:56)</li><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2457" >2010/02/02</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @anderson  不要"\"abc\"", 这里是指"abc", ;)</li><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2463" >2010/02/23</a>, darasion writes: json_encode 有没有类似这样的问题？</li><li><a href="http://www.laruence.com/2010/02/02/1272.html#comment-2469" >2010/03/07</a>, RainChen writes: 一般都会把这些封装到一个类，用静态方法调用，如
JSON::decode()
这样一来可以方便管理（归类、增加相关的方法），
二来可以避免PHP升级后的接口变异。
缺点是比直接调用原生的函数慢一点，但对比带来的可维护性的好处，这点效率牺牲完全可以忽略</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/02/02/1272.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>pkg-config与LD_LIBRARY_PATH</title>
		<link>http://www.laruence.com/2010/01/27/1265.html</link>
		<comments>http://www.laruence.com/2010/01/27/1265.html#comments</comments>
		<pubDate>Wed, 27 Jan 2010 11:34:28 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[GNU C/C++]]></category>
		<category><![CDATA[转载]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[ld.so.conf]]></category>
		<category><![CDATA[LD_LIBRARY_PATH]]></category>
		<category><![CDATA[pkg-config]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1265</guid>
		<description><![CDATA[    一般来说，如果库的头文件不在 /usr/include 目录中，那么在编译的时候需要用 -I 参数指定其路径。由于同一个库在不同系统上可能位于不同的目录下，用户安装库的时候也可以将库安装在不同的目录下，所以即使使用同一个库，由于库的路径的不同，造成了用 -I 参数指定的头文件的路径也可能不同，其结果就是造成了编译命令界面的不统一。如果使用 -L 参数，也会造成连接界面的不统一。编译和连接界面不统一会为库的使用带来麻烦。

       为了解决编译和连接界面不统一的问题，人们找到了一些解决办法。其基本思想就是：事先把库的位置信息等保存起来，需要的时候再通过特定的工具将其中有用的 信息提取出来供编译和连接使用。这样，就可以做到编译和连接界面的一致性。其中，目前最为常用的库信息提取工具就是下面介绍的 pkg-config...]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2010/01/27/1265.html"  title="Permanet Link to pkg-config与LD_LIBRARY_PATH" >http://www.laruence.com/2010/01/27/1265.html</a></li>
<li>文章转自: <a href="http://hi.baidu.com/litaosmile/blog/item/751be4f45bbb4ee67609d7be.html"  target="_blank" >Lucky_xi的百度空间</a></li>
</ul></div>
<p>最近遇到的几个问题， 都和LD_LIBRARY_PATH有关， 想整理一篇心得， 但发现一片比较好的介绍文章， 就不再赘笔了。</p>
<h3>一、编译和连接</h3>
<p>        一般来说，如果库的头文件不在 /usr/include 目录中，那么在编译的时候需要用 -I 参数指定其路径。由于同一个库在不同系统上可能位于不同的目录下，用户安装库的时候也可以将库安装在不同的目录下，所以即使使用同一个库，由于库的路径的不同，造成了用 -I 参数指定的头文件的路径也可能不同，其结果就是造成了编译命令界面的不统一。如果使用 -L 参数，也会造成连接界面的不统一。编译和连接界面不统一会为库的使用带来麻烦。</p>
<p>       为了解决编译和连接界面不统一的问题，人们找到了一些解决办法。其基本思想就是：事先把库的位置信息等保存起来，需要的时候再通过特定的工具将其中有用的 信息提取出来供编译和连接使用。这样，就可以做到编译和连接界面的一致性。其中，目前最为常用的库信息提取工具就是下面介绍的 pkg-config。</p>
<p>       pkg-config 是通过库提供的一个 .pc 文件获得库的各种必要信息的，包括版本信息、编译和连接需要的参数等。这些信息可以通过 pkg-config 提供的参数单独提取出来直接供编译器和连接器使用。</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
  The pkgconfig package contains tools for passing the include path and/or library
paths to build tools during the make file execution.

  pkg-config is a function that returns meta information for the specified library.

  The default setting for PKG_CONFIG_PATH is /usr/lib/pkgconfig because of the prefix
we use to install pkgconfig. You may add to PKG_CONFIG_PATH by exporting additional
paths on your system where pkgconfig files are installed. Note that PKG_CONFIG_PATH is
only needed when compiling packages, not during run-time.
</pre>
<p>        在默认情况下，每个支持 pkg-config 的库对应的 .pc 文件在安装后都位于安装目录中的 lib/pkgconfig 目录下。例如，我们在上面已经将 Glib 安装在 /opt/gtk 目录下了，那么这个 Glib 库对应的 .pc 文件是 /opt/gtk/lib/pkgconfig 目录下一个叫 glib-2.0.pc 的文件：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
prefix=/opt/gtk/
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums

Name: GLib
Description: C Utility Library
Version: 2.12.13
Libs: -L${libdir} -lglib-2.0
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include
</pre>
<p>使用 pkg-config 的 &#8211;cflags 参数可以给出在编译时所需要的选项，而 &#8211;libs 参数可以给出连接时的选项。例如，假设一个 sample.c 的程序用到了 Glib 库，就可以这样编译：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ gcc -c `pkg-config --cflags glib-2.0` sample.c
</pre>
<p>然后这样连接：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ gcc sample.o -o sample `pkg-config --libs glib-2.0`
</pre>
<p>或者上面两步也可以合并为以下一步：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ gcc sample.c -o sample `pkg-config --cflags --libs glib-2.0`
</pre>
<p>可以看到：由于使用了 pkg-config 工具来获得库的选项，所以不论库安装在什么目录下，都可以使用相同的编译和连接命令，带来了编译和连接界面的统一。</p>
<p>使用 pkg-config 工具提取库的编译和连接参数有两个基本的前提：</p>
<p>库本身在安装的时候必须提供一个相应的 .pc 文件。不这样做的库说明不支持 pkg-config 工具的使用。</p>
<p>pkg-config 必须知道要到哪里去寻找此 .pc 文件。</p>
<p>GTK+ 及其依赖库支持使用 pkg-config 工具，所以剩下的问题就是如何告诉 pkg-config 到哪里去寻找库对应的 .pc 文件，这也是通过设置搜索路径来解决的。</p>
<p>       对于支持 pkg-config 工具的 GTK+ 及其依赖库来说，库的头文件的搜索路径的设置变成了对 .pc 文件搜索路径的设置。.pc 文件的搜索路径是通过环境变量 PKG_CONFIG_PATH 来设置的，pkg-config 将按照设置路径的先后顺序进行搜索，直到找到指定的 .pc 文件为止。</p>
<p>安装完 Glib 后，在 bash 中应该进行如下设置：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH
</pre>
<p>可以执行下面的命令检查是否 /opt/gtk/lib/pkgconfig 路径已经设置在 PKG_CONFIG_PATH 环境变量中：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ echo $PKG_CONFIG_PATH
</pre>
<p>这样设置之后，使用 Glib 库的其它程序或库在编译的时候 pkg-config 就知道首先要到 /opt/gtk/lib/pkgconfig 这个目录中去寻找 glib-2.0.pc 了（GTK+ 和其它的依赖库的 .pc 文件也将拷贝到这里，也会首先到这里搜索它们对应的 .pc 文件）。之后，通过 pkg-config 就可以把其中库的编译和连接参数提取出来供程序在编译和连接时使用。</p>
<p>另外还需要注意的是：环境变量的设置只对当前的终端窗口有效。如果到了没有进行上述设置的终端窗口中，pkg-config 将找不到新安装的 glib-2.0.pc 文件、从而可能使后面进行的安装（如 Glib 之后的 Atk 的安装）无法进行。</p>
<p>       在我们采用的安装方案中，由于是使用环境变量对 GTK+ 及其依赖库进行的设置，所以当系统重新启动、或者新开一个终端窗口之后，如果想使用新安装的 GTK+ 库，需要如上面那样重新设置 PKG_CONFIG_PATH 和 LD_LIBRARY_PATH 环境变量。</p>
<p>这种使用 GTK+ 的方法，在使用之前多了一个对库进行设置的过程。虽然显得稍微繁琐了一些，但却是一种最安全的使用 GTK+ 库的方式，不会对系统上已经存在的使用了 GTK+ 库的程序（比如 GNOME 桌面）带来任何冲击。</p>
<p>为了使库的设置变得简单一些，可以把下面的这两句设置保存到一个文件中（比如 set_gtk-2.10 文件）:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH
export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH
</pre>
<p>之后，就可以用下面的方法进行库的设置了（其中的 source 命令也可以用 . 代替）：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ source set_gtk-2.10
</pre>
<p>只有在用新版的 GTK+ 库开发应用程序、或者运行使用了新版 GTK+ 库的程序的时候，才有必要进行上述设置。</p>
<p>           如果想避免使用 GTK+ 库之前上述设置的麻烦，可以把上面两个环境变量的设置在系统的配置文件中（如 /etc/profile）或者自己的用户配置文件中（如 ~/.bash_profile） ；库的搜索路径也可以设置在 /etc/ld.so.conf 文件中，等等。这种设置在系统启动时会生效，从而会导致使用 GTK+ 的程序使用新版的 GTK+ 运行库，这有可能会带来一些问题。当然，如果你发现用新版的 GTK+ 代替旧版没有什么问题的话，使用这种设置方式是比较方便的。加入到~/.bashrc中，例如：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig
</pre>
<p>重启之后：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
[root@localhost ~]# echo $PKG_CONFIG_PATH
/opt/gtk/lib/pkgconfig
</pre>
<h3> 二、运行时 </h3>
<p>        库文件在连接（静态库和共享库）和运行（仅限于使用共享库的程序）时被使用，其搜索路径是在系统中进行设置的。一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径，所以使用这两个目录中的库时不需要进行设置搜索路径即可直接使用。对于处于默认库搜索路径之外的库，需要将库的位置添加到 库的搜索路径之中。设置库文件的搜索路径有下列两种方式，可任选其一使用：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。
在 /etc/ld.so.conf 文件中添加库的搜索路径。
</pre>
<p>        将自己可能存放库文件的路径都加入到/etc/ld.so.conf中是明智的选择 ^_^<br/>
添加方法也极其简单，将库文件的绝对路径直接写进去就OK了，一行一个。例如：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
/usr/X11R6/lib
/usr/local/lib
/opt/lib
</pre>
<p>        需要注意的是：第二种搜索路径的设置方式对于程序连接时的库（包括共享库和静态库）的定位已经足够了，但是对于使用了共享库的程序的执行还是不够的。这是 因为为了加快程序执行时对共享库的定位速度，避免使用搜索路径查找共享库的低效率，所以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非文本的数据文件，不能直接编辑，它是根据 /etc/ld.so.conf 中设置的搜索路径由 /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的（ldconfig 命令要以 root 权限执行）。因此，为了保证程序执行时对库的定位，在 /etc/ld.so.conf 中进行了库搜索路径的设置之后，还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache 文件之后才可以。ldconfig ,简单的说，它的作用就是将/etc/ld.so.conf列出的路径下的库文件 缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件，(例如刚安装好glib)，或者修改ld.so.conf增加新的库路径后，需要运行一下 /sbin/ldco                                 .cache中，如果没做，即使库文件明明就在/usr/lib下的，也是不会被使用 的，结果编译                                现明明就在那放着，搞的想大骂computer蠢猪一个。 ^_^</p>
<p>       在程序连接时，对于库文件（静态库和共享库）的搜索路径，除了上面的设置方式                                 。因为用 -L 设置的路径将被优先搜索，所以在连接的时候通常都会以这种方式直接指定</p>
<p>        前面已经说明过了，库搜索路径的设置有两种方式：在环境变量 LD_LIBRARY_PA                                文件中设置。其中，第二种设置方式需要 root 权限，以改变 /etc/ld.so.conf 文件并执                                 系统重新启动后，所有的基于 GTK2 的程序在运行时都将使用新安装的 GTK+ 库。不幸的                                会给应用程序带来兼容性的问题，造成某些程序运行不正常。为了避免出现上面的这些情                                中对于库的搜索路径的设置将采用第一种方式进行。这种设置方式不需要 root 权限，设</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH
</pre>
<p>可以用下面的命令查看 LD_LIBRAY_PATH 的设置内容：</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ echo $LD_LIBRARY_PATH
</pre>
<p>至此，库的两种设置就完成了。<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/01/27/1265.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IE下var的重要性的又一佐证</title>
		<link>http://www.laruence.com/2010/01/21/1254.html</link>
		<comments>http://www.laruence.com/2010/01/21/1254.html#comments</comments>
		<pubDate>Thu, 21 Jan 2010 04:43:07 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[Js/CSS]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[var]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1254</guid>
		<description><![CDATA[ 一个朋友问了一个js问题, 一段看不出有任何问题的代码, 在ie下报错:"object doesn't support this property or method".
 <coolcode lang="javascript" linenum="off">
function foo(obj) {
   productTree = obj.toString();
   document.getElementById('productTree').innerHTML = productTree;
} 
</coolcode>
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/01/21/1254.html"  title="Permanet Link to IE下var的重要性的又一佐证" >http://www.laruence.com/2010/01/21/1254.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   一个朋友问了一个js问题, 一段看不出有任何问题的代码, 在ie下报错:&#8221;object doesn&#8217;t support this property or method&#8221;.</p>
<pre name="code"  class="sh_javascript"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
function foo(obj) {
   productTree = obj.toString();
   document.getElementById('productTree').innerHTML = productTree;
}
</pre>
<p>    开始, 还以为错误是指obj的toString方法, 绕了半天弯路, 无果..</p>
<p>    后来,注意到变量名是productTree没有用var申明, 加上getElementById(&#8216;productTree&#8217;)说明有个id为productTree的元素, 并且我们知道在IE下可以直接通过id获取DOM元素的引用, so~</p>
<p>    所以啊, 局部变量一定要用var申明, 不仅仅是因为不用var会成全局变量, 更因为在IE下, 有可能会出现这种, 让人很莫名的错误&#8230;.
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_javascript.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/01/21/1254.html#comment-2440" >2010/01/21</a>, rzhome writes: 在IE下就是这样的痛苦，不过加var来声明变量应该规范点。</li><li><a href="http://www.laruence.com/2010/01/21/1254.html#comment-2441" >2010/01/21</a>, yangliang writes: 难道window下的所有变量ie都认为是dom咯，该死的ie</li><li><a href="http://www.laruence.com/2010/01/21/1254.html#comment-2442" >2010/01/22</a>, janpoem writes: 这是ie的老问题了，应该规范使用var声明变量。</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/01/21/1254.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Nginx/PHP Fastcgi PATH_INFO的一个问题</title>
		<link>http://www.laruence.com/2010/01/20/1247.html</link>
		<comments>http://www.laruence.com/2010/01/20/1247.html#comments</comments>
		<pubDate>Tue, 19 Jan 2010 16:24:40 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[fastcgi]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[path_info]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[urldecode]]></category>
		<category><![CDATA[urlencode]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1247</guid>
		<description><![CDATA[通过<a href="http://www.laruence.com/2009/11/13/1138.html" target="_blank">在nginx.conf中模拟PATH_INFO</a>的方法会有一个bug. 那就是PATH_INFO不会被urldecode.
 
    对于Apache+PHP(php2handler)来说, PATH_INFO来自Apache, 不会有问题, 对于Apache fastcgi也应该没有问题, 因为PATH_INFO也是由Apache生成.

    但是对于nginx+fastcgi, 因为对于cgi来说PATH_INFO来自于ENV(fastcgi_params), 而php-cgi中的import_environment_variables不会对ENV中的变量做urldecode. 

    这样, nginx看到的url是urlencode以后的, 从url中分离出来的PATH_INFO也是urlencode后的, forward给php proxy以后, PHP看到的PATH_INFO也是urlencode的了. 

    所以, 如果在PATH_INFO中包含一些宽字符, 或者是"+", 那就要注意了, 需要我们主动的urldecode一下再使用.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/01/20/1247.html"  title="Permanet Link to Nginx/PHP Fastcgi PATH_INFO的一个问题" >http://www.laruence.com/2010/01/20/1247.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>    通过<a href="http://www.laruence.com/2009/11/13/1138.html"  target="_blank" >在nginx.conf中模拟PATH_INFO</a>的方法会有一个bug. 那就是PATH_INFO不会被urldecode.</p>
<p>    对于Apache+PHP(php2handler)来说, PATH_INFO来自Apache, 不会有问题, 对于Apache fastcgi也应该没有问题, 因为PATH_INFO也是由Apache生成.</p>
<p>    但是对于nginx+fastcgi, 因为对于cgi来说PATH_INFO来自于ENV(fastcgi_params), 而php-cgi中的import_environment_variables不会对ENV中的变量做urldecode. </p>
<p>    这样, nginx看到的url是urlencode以后的, 从url中分离出来的PATH_INFO也是urlencode后的, forward给php proxy以后, PHP看到的PATH_INFO也是urlencode的了. </p>
<p>    所以, 如果在PATH_INFO中包含一些宽字符, 或者是&#8221;+&#8221;, 那就要注意了, 需要我们主动的urldecode一下再使用.</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/01/20/1247.html#comment-2465" >2010/03/01</a>, <a href="http://phpvim.net"  rel="external nofollow"  class="url" >verdana</a> writes: 尝试一下 fastcgi_split_path_info</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/01/20/1247.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Youtube解封啦!</title>
		<link>http://www.laruence.com/2010/01/03/1233.html</link>
		<comments>http://www.laruence.com/2010/01/03/1233.html#comments</comments>
		<pubDate>Sun, 03 Jan 2010 15:16:51 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[youtube]]></category>
		<category><![CDATA[解封]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1233</guid>
		<description><![CDATA[<p>
事实证明,是gfw升级间隙造成的短暂开放.
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/01/03/1233.html"  title="Permanet Link to Youtube解封啦!" >http://www.laruence.com/2010/01/03/1233.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
事实证明,是gfw升级间隙造成的短暂开放. 只有5个小时&#8230;</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/01/03/1233.html#comment-2410" >2010/01/03</a>, <a href="http://www.royalar.cn"  rel="external nofollow"  class="url" >royalar</a> writes: 部分地区因为g...f..w--list调整而解封的，我这里就打不开</li><li><a href="http://www.laruence.com/2010/01/03/1233.html#comment-2411" >2010/01/04</a>, kwjlk writes: 果然是啊，访问不来</li><li><a href="http://www.laruence.com/2010/01/03/1233.html#comment-2412" >2010/01/04</a>, zong writes: 是啊 ，我这果然不能访问</li><li><a href="http://www.laruence.com/2010/01/03/1233.html#comment-2414" >2010/01/04</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: sign, 见证了youtube的短暂回光返照.... 看来确实是g-f-w的技术问题.</li><li><a href="http://www.laruence.com/2010/01/03/1233.html#comment-2415" >2010/01/04</a>, venkman writes: 一把火把g，w，f烧了</li><li><a href="http://www.laruence.com/2010/01/03/1233.html#comment-2417" >2010/01/04</a>, <a href="http://liuqingyan.blogspot.com"  rel="external nofollow"  class="url" >qy</a> writes: 我说昨天咋忽然能看wordpress了呢。。。。汗</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/01/03/1233.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>一个想当然造成的错误(赋值语句的返回值)</title>
		<link>http://www.laruence.com/2010/01/03/1225.html</link>
		<comments>http://www.laruence.com/2010/01/03/1225.html#comments</comments>
		<pubDate>Sun, 03 Jan 2010 09:53:27 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[函数调用]]></category>
		<category><![CDATA[引用]]></category>
		<category><![CDATA[引用参数]]></category>
		<category><![CDATA[赋值]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1225</guid>
		<description><![CDATA[	一个想当然造成的错误.

	需求是这样的, 我需要给一个二进制流加入一个签名串. 那么首先, 理所当然我的写了一个签名函数, 考虑到要判断签名操作是否成功, 所以我采用了传引用:

<coolcode lang="php" linenum="off">
function sign(&#038;$carrier, $fingerprint) {
	if (NULL === $fingerprint) {
		return FALSE;
	}
	//加入签名
	$carrier = 签名逻辑.
	return TRUE;
}
</coolcode> 

	接下来, 考虑到, 如果签名失败, 那还是使用原来的字符串做为结果, 所以, 我想当然的写下了如下的代码....]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/01/03/1225.html"  title="Permanet Link to 一个想当然造成的错误(赋值语句的返回值)" >http://www.laruence.com/2010/01/03/1225.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	一个想当然造成的错误.</p>
<p>	需求是这样的, 我需要给一个二进制流加入一个签名串. 那么首先, 理所当然我的写了一个签名函数, 考虑到要判断签名操作是否成功, 所以我采用了传引用:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
function sign(&amp;$carrier, $fingerprint) {
	if (NULL === $fingerprint) {
		return FALSE;
	}
	//加入签名
	$carrier = 签名逻辑.
	return TRUE;
}
</pre>
<p>	接下来, 考虑到, 如果签名失败, 那还是使用原来的字符串做为结果, 所以, 我想当然的写下了如下的代码:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$bin_str = **************;

$success = sign($after_signed = $bin_str, &quot;laruence's fingerprint&quot;);
if ($success) {
	//使用$after_signed
} else {
	//使用$bin_str
}
</pre>
<p>考虑到简单变量是传值引用, 在bin_str赋值给after_signed以后, 我以为after_signed的引用会传递给carrier..<br/>
但, 结果是, after_signed并没有被加入签名串&#8230;</p>
<p>那为什么会错呢?</p>
<p>经过对opcode的分析, 发现原来, PHP在做二元赋值运算的时候, 返回值并不是左值,而是一个临时变量. 也就是说对于:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$a = $b;
</pre>
<p>它的返回值, 并不是$a, 而是一个临时变量, 假设是$2.<br/>
所以传递给sign函数的, 并不是$a的引用, 而是$2;</p>
<p>以下内容是对源码的分析范畴, 如果只是想知道结论的, 略过如下也可:</p>
<p>现在, 结合之前的文章<a href="http://www.laruence.com/2008/09/19/520.html" >深入理解PHP原理之变量分离/引用(Variables Separation)</a>中介绍过的相关知识, 来做个详细是分析:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$a = &quot;laruence&quot;;
function ch(&amp;$p) {
    debug_zval_dump($p);
    $p = 'eve';
    debug_zval_dump($p);
}

debug_zval_dump($a);
ch($a);
ch($b=$a);
</pre>
<p>运行结果是:</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
//初始的a
string(8) &quot;laruence&quot; refcount(2)
//第一次调用change中的p
string(8) &quot;laruence&quot; refcount(1)
string(3) &quot;eve&quot; refcount(1)
//第二次赋值结果调用change中的a
string(3) &quot;eve&quot; refcount(3)
string(3) &quot;eve&quot; refcount(2)
</pre>
<p>首先, 最初的时候, $a的引用是2, 这是因为简单变量传值, 所以传给debug_zval_dump后, $a有一个copy的引用计数. </p>
<p>当第一次调用的时候, 我们直接传$a, 因为change函数的参数申明是传引用, 在change中调用debug_zval_dump时, $p是一个引用. 而要传值调用, 所以产生了一次分离, 得到计数为1.</p>
<p>重点看下第二次调用, 此时change中第一次debug_zval_dump的引用计数是3. 怎么会是3呢?.<br/>
此处要是3. 那也就是说$p是一个引用计数为2的非引用变量.</p>
<p>可是, 明明不是申明了change接受引用参数么?</p>
<p>没办法, 查看源代码. 在语法分析时刻, 看出了差别:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
non_empty_function_call_parameter_list:
        expr_without_variable
		   { Z_LVAL($$.u.constant) = 1;
				zend_do_pass_param(&amp;$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
    |   variable
			{ Z_LVAL($$.u.constant) = 1;
				zend_do_pass_param(&amp;$1, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
</pre>
<p>对于第二次调用, 它将满足的是第一条规约规则, 也就是传给zend_do_pass_param的第二个参数是ZEND_SEND_VAL&#8230;</p>
<p>继续追查zend_do_pass_param:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
if (op == ZEND_SEND_VAR &amp;&amp; zend_is_function_or_method_call(param)) {
	//是否是函数或者方法的返回值
	/* Method call */
	op = ZEND_SEND_VAR_NO_REF;
	send_function = ZEND_ARG_SEND_FUNCTION;
} else if (op == ZEND_SEND_VAL &amp;&amp; (param-&gt;op_type &amp; (IS_VAR|IS_CV))) {
	op = ZEND_SEND_VAR_NO_REF;//在这里被改成了NO_REF
}
</pre>
<p>也就是, 因为第二次调用的时候传递给change的变量, 是一个&#8221;直接量&#8221;, 并且属于IS_VAR, 所以PHP会把传递方式改变为传值.</p>
<p>所以在change中第一次debug_zval_dump的时候, 引用计数就是3了. ~ </p>
<p>其实, 分析到这里的时候, 我们可以类比函数的返回值做为参数的情形(第一个if判断条件). 想象赋值也和函数调用一样, 有返回值, 就容易理解多了.
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2406" >2010/01/03</a>, LANYE writes: ..嘿嘿</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2407" >2010/01/03</a>, <a href="http://sanmuding.com"  rel="external nofollow"  class="url" >Anders</a> writes: 有些 trick 样的语句还是少用的好，呵呵。</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2408" >2010/01/03</a>, PeterYu writes: 5.3开始,直接禁止了引用一个"非明示的变量值".
:-),你可以试试,</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2409" >2010/01/03</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @PeterYu 在PHP 5.3.0 (cli)下, 关于这个问题的语法分析逻辑以及complie.c中的zend_do_pass_param逻辑和PHP5.2.x一样,经过我测试, 结论和本文的一致.  另外我没听过"非明示变量值"这个名词, 是指匿名变量(变量直接量)么? </li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2421" >2010/01/05</a>, <a href="http://blog.csdn.net/yycai"  rel="external nofollow"  class="url" >小蔡</a> writes: $a = 'test';
$b = &amp; $a; 

function ch(&amp;$p) {
    debug_zval_dump($p);
    $p = 'eve';
    debug_zval_dump($p);
}

debug_zval_dump($a);
ch($a);
ch($b=$a);

为什么这里输出的refcount全都是1呢？</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2422" >2010/01/05</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @小蔡 b是a的引用, 调用的时候要传值, 所以就产生分离了啊.</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2423" >2010/01/05</a>, <a href="http://blog.csdn.net/yycai"  rel="external nofollow"  class="url" >小蔡</a> writes: 感觉还是有点乱，晚上回去看看源码</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2426" >2010/01/07</a>, <a href="http://www.zhouxblog.com"  rel="external nofollow"  class="url" >shinezhou</a> writes: $a = $b这个表达式的结果竟然不是左值$a...
让人郁闷了~</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2433" >2010/01/16</a>, <a href="http://www.editornote.net"  rel="external nofollow"  class="url" >erway</a> writes: 博主：你好！
我是机械工业出版社华章公司（www.hzbook.com，中国IT出版4强）的高级策划编辑杨福川，冒昧打扰了，还请见谅。
今天无意中从一位朋友的博客中链接到了你的博客中，顿时眼前一亮，原来又发现了一位高人。我一直想策划一本关于PHP源码剖析的书，苦于找不到作者，没想到今天无意中发现了一位大牛，庆幸哉！我仔细拜读了你撰写的关于PHP的文章，看得出来你对PHP颇有研究，似乎对PHP源码情有独钟，何不系统性地来分析一下PHP的源码呢？这不但能造福广大PHPer，也许能成为你人生的一个转折点，哈哈。
我准备策划一系列关于源码分析的书，目前已经出版和策划的有：
1. 《Spring技术内幕——深入解析Spring架构与设计原理》，最近刚出版，当当网2天就卖断货。
2. 《Struts技术内幕——深入解析Struts架构与设计原理》，正在策划中。
3. 《JVM技术内幕》，正在策划中。
4. 《MySQL技术内幕》，正在策划中。

《PHP技术内幕》也是我策划的这套书中非常重要的一本，一直还没有找到比较合适的朋友来写，今日认识了兄弟你，我想也许我找到了这个选题的主人，不知道是否有机会与你合作。为了便于联系，能否交换一下联系方式（MSN：erwa_yang@live.cn；QQ：15693352）？

期待与你取得联系，期待与你合作。</li><li><a href="http://www.laruence.com/2010/01/03/1225.html#comment-2439" >2010/01/20</a>, <a href="http://dev.meettea.com"  rel="external nofollow"  class="url" >shiny</a> writes: @erway

同期待laruence
如果写了必买</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/01/03/1225.html/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>朋友们,新年好.</title>
		<link>http://www.laruence.com/2010/01/01/1216.html</link>
		<comments>http://www.laruence.com/2010/01/01/1216.html#comments</comments>
		<pubDate>Thu, 31 Dec 2009 16:02:35 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[随笔]]></category>
		<category><![CDATA[2010]]></category>
		<category><![CDATA[新年]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1216</guid>
		<description><![CDATA[   2009年就这么过去了, 刚吃了个饭, 和朋友打了会儿球, 回来就2010年了.
   
   呵呵, 祝福大家2010年, 事事顺利, 天天开心.
   
   Rss feed改成全文输出了, 这样订阅我blog的朋友看的就会更方便了. (大家可能需要刷新下reader, 这样之前的文章就可以全文浏览了).
 
  另外, 想着该给blog换个皮肤了. 新年新气象么, :)]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2010/01/01/1216.html"  title="Permanet Link to 朋友们,新年好." >http://www.laruence.com/2010/01/01/1216.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
   2009年就这么过去了, 刚吃了个饭, 和朋友打了会儿球, 回来就2010年了.</p>
<p>   呵呵, 祝福大家2010年, 事事顺利, 天天开心.</p>
<p>   Rss feed改成全文输出了, 这样订阅我blog的朋友看的就会更方便了(不过, 大家可能需要刷新下reader, 这样之前的文章就应该可以全文浏览了, 还有个问题, 就是代码高亮的css没发加上去, 谁有好的办法?).</p>
<p>  另外, 想着该给blog换个皮肤了. 新年新气象么, <img src="http://www.laruence.com/wp-includes/images/smilies/icon_smile.gif"  alt=":)"  class="wp-smiley" /> </p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
  while (date(&quot;Y&quot;) == &quot;2010&quot;) {
    echo &quot;事事顺利, 工作开心&quot;;
  }
?&gt;
</pre>
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2010/01/01/1216.html#comment-2403" >2010/01/01</a>, <a href="http://www.trylife.cn"  rel="external nofollow"  class="url" >trylife</a> writes: 新年快乐</li><li><a href="http://www.laruence.com/2010/01/01/1216.html#comment-2404" >2010/01/01</a>, <a href="http://www.sychen.org"  rel="external nofollow"  class="url" >sychen</a> writes: 一年来看博主的文章，学习不少。 元旦快乐:)</li><li><a href="http://www.laruence.com/2010/01/01/1216.html#comment-2413" >2010/01/04</a>, evan writes: 建议修改下插件，在rss输出的时候把整个的高亮样式内容内联到内容中去比较合适</li><li><a href="http://www.laruence.com/2010/01/01/1216.html#comment-2420" >2010/01/05</a>, silasoni writes: 新年快乐
从您这学到不少东西</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2010/01/01/1216.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>深入理解PHP原理之变量生命期(一)</title>
		<link>http://www.laruence.com/2009/12/26/1198.html</link>
		<comments>http://www.laruence.com/2009/12/26/1198.html#comments</comments>
		<pubDate>Sat, 26 Dec 2009 13:11:44 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[GET]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[SAPI]]></category>
		<category><![CDATA[variable]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1198</guid>
		<description><![CDATA[对于PHP的中的数据来源, 不外乎有俩种:
<coolcode lang="sh" linenum="off">
1. 来自代码中
2. 来自外部(GET/POST/DB)
</coolcode>
	
	对于代码中的变量(也就是直接量)来说, 变量分配/赋值在编译期, 活跃在执行器, 在请求关闭期被销毁.对于这些变量来说, 使用APC进行Opcode缓存, 则会缓存这部分变量的值. 

	而对于来自外部的变量, 变量分配/赋值在编译器后, 执行期前, 在请求关闭期被销毁,对于这些变量来说, 使用APC进行OpCode缓存, 是不会被缓存的.

	今天就着重关注下外部变量的一个部分,GET来的数据的整个生命周期....]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/12/26/1198.html"  title="Permanet Link to 深入理解PHP原理之变量生命期(一)" >http://www.laruence.com/2009/12/26/1198.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	对于PHP的中的数据来源, 不外乎有俩种:</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 来自代码中
2. 来自外部(GET/POST/DB)
</pre>
<p>	对于代码中的变量(也就是直接量)来说, 变量分配/赋值在编译期, 活跃在执行器, 在请求关闭期被销毁.对于这些变量来说, 使用APC进行Opcode缓存, 则会缓存这部分变量的值. </p>
<p>	而对于来自外部的变量, 变量分配/赋值在编译器后, 执行期前, 在请求关闭期被销毁,对于这些变量来说, 使用APC进行OpCode缓存, 是不会被缓存的.</p>
<p>	今天就着重关注下外部变量的一个部分,GET来的数据的整个生命周期.</p>
<p>	假设, 有如下请求到来:</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
	GET /index.php?name=laruence&amp;career[]=yahoo&amp;career[]=baidu
</pre>
<p>	而, 在index.php中:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
	$name 	= $_GET['name'];
	$career = $_GET['career']; //array
</pre>
<p>	我们知道, 在最后的执行期, $_GET数组必然包含如下片段:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
	$_GET = array(
		'name'   =&gt; 'laruence',
		'career' =&gt; array(
			'yahoo', 'baidu',
		),
	)
</pre>
<p>	那么, 我们今天就重点关注下, Query String是如何构建成_GET数组的(关于GET变量的生成, 请一并阅读我之前的文章: &#8220;<a href="http://www.laruence.com/2008/11/07/581.html"  target="_blank" >PHP的GET/POST等大变量生成过程</a>&#8220;): </p>
<p>	在请求到来时刻,php_request_startup(定义在main.c)被调用,来做初始化现场. 在这个过程中包括设置超时值,调用各个模块的请求初始化函数. 当然也包括我们关心的, 创建变量环境.</p>
<p>	php_hash_environment根据php.ini中的variables_order来依次初始化各个预定义大变量, 那么对于$_GET来说:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
...
case 'g':
case 'G':
	if (!_gpc_flags[2]) {
		sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC);
		_gpc_flags[2] = 1;
		if (PG(register_globals)) {
			php_autoglobal_merge(&amp;EG(symbol_table),
				Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]) TSRMLS_CC);
		}
	}
break;
...
</pre>
<p>	大体可以看出,这段逻辑,首先通过treat_data来生成变量hash(PG(http_globals)[TRACK_VARS_GET]), 如果打开了auto_register_globals,则再把$_GET数组中的变量加入到符号表中.</p>
<p>	treat_data是属于sapi_module_struct中的一个成员: </p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
 注意:	本文基于apache2handler方式的sapi, 这个启动过程和之前的文章sapi
原理中的启动过程略有不同, php5通过注册apache2的ap_hook_post_config挂钩,
在apache server启动的时候启动php(php_apache_server_startup,定义在
sapi/apache2hander/sapi_apache2.c中), 在这个函数中调用sapi_startup启动sapi,
继而通过调用php_apache2_startup来注册sapi module struct,
然后调用php_module_startup来初始化PHP, 其中又会初始化ZEND引擎,
以及填充zend_module_struct中的treat_data成员(通过php_startup_sapi_content_types)
为php_default_treat_data
</pre>
<p>	现在回过头来继续看treat_data(也就是php_default_treat_data):</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
....
if (arg == PARSE_GET) {     /* GET data */
	c_var = SG(request_info).query_string;
	if (c_var &amp;&amp; *c_var) {
		res = (char *) estrdup(c_var);
		free_buffer = 1;
	} else {
		free_buffer = 0;
	}
} else if (arg == PARSE_COOKIE) {       /* Cookie data */
....
</pre>
<p>	在上面的逻辑中, 给res复制为query_string, SG(request_info)是一个代表了当前请求信息的结构体, 其中query_string是在php_apache_request_ctor中通过复制apache的reqeust_rec结构体中的args而来的. </p>
<p>	对于本文的例子来说, 此时res即为&#8221;name=laruence&#038;career[]=yahoo&#038;career[]=baidu&#8221;, </p>
<p>	继续在treat_data中, 随后的逻辑是:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
var = php_strtok_r(res, separator, &amp;strtok_buf);
...
while (var) {
	val = strchr(var, '=');

	if (arg == PARSE_COOKIE) {
		/* Remove leading spaces from cookie names,
			needed for multi-cookie header where ; can be followed by a space */
		while (isspace(*var)) {
			var++;
		}
		if (var == val || *var == '\0') {
			goto next_cookie;
		}
	}

	if (val) { /* have a value */
		int val_len;
		unsigned int new_val_len;

		*val++ = '\0';
		php_url_decode(var, strlen(var));
		val_len = php_url_decode(val, strlen(val));
		val = estrndup(val, val_len);
		if (sapi_module.input_filter(arg, var, &amp;val, val_len, &amp;new_val_len TSRMLS_CC)) {
			php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC);
		}
		efree(val);
	} else {
...
</pre>
<p>	首先, 通过php_strtok_r把res根据&#8221;&#038;&#8221;分割成一个一个的&#8221;key=value&#8221;段, 接下来分别为var和val复制为key和value, 注意到这个过程中会分别对var和val做php_url_decode.</p>
<p>	最后通过php_register_variable_safe, 给array_ptr(此时指向PG(http_globals)[TRACK_VARS_GET], 也就是$_GET)添加一个名为var值为val的成员.</p>
<p>	到了这一步, 我们的$_GET数组中, 就包含了如下的成员:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
'name'   =&gt; 'laruence',
'career' =&gt; array(
	'yahoo', 'baidu',
),
</pre>
<p>	未完待续(变量的销毁过程)&#8230;<br/>
<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/12/26/1198.html#comment-2390" >2009/12/26</a>, Robin writes: Hi，麻烦问问，如果想去掉 "[]"，改成
name=laruence&amp;career=yahoo&amp;career=baidu
$_GET数组还要不变，怎么改？

谢谢了。</li><li><a href="http://www.laruence.com/2009/12/26/1198.html#comment-2391" >2009/12/26</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @robin 这样的话,最终career的值为baidu</li><li><a href="http://www.laruence.com/2009/12/26/1198.html#comment-2396" >2009/12/28</a>, <a href="www.phppan.com"  rel="external nofollow"  class="url" >phppan</a> writes: 在window下用vc看也比较舒服
抚琴居主人有一篇文章有相关介绍
http://www.yanbin.org/blog/commentary-on-php-chap1_1-prep.html</li><li><a href="http://www.laruence.com/2009/12/26/1198.html#comment-2397" >2009/12/28</a>, <a href="http://www.metsky.com"  rel="external nofollow"  class="url" >天缘</a> writes: 还没真的没深究过这些源码，佩服博主认真的研究</li><li><a href="http://www.laruence.com/2009/12/26/1198.html#comment-2399" >2009/12/28</a>, phpcoder writes: 强悍的博主, 还有点不明白就是数组是怎么parse来的呢?</li><li><a href="http://www.laruence.com/2009/12/26/1198.html#comment-2400" >2009/12/28</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @phpcoder 呵呵,就是简单的字符串parse了, 遇到"[]", 就知道是个数组..</li><li><a href="http://www.laruence.com/2009/12/26/1198.html#comment-2401" >2009/12/30</a>, eve writes: 楼主，求交往</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/12/26/1198.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>服务器搬到国外主机</title>
		<link>http://www.laruence.com/2009/12/17/1182.html</link>
		<comments>http://www.laruence.com/2009/12/17/1182.html#comments</comments>
		<pubDate>Thu, 17 Dec 2009 14:56:03 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[随笔]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1182</guid>
		<description><![CDATA[<p>
    在国内声势浩大的打击非法网站的行动中, 我这个有IPC备案, 无不良内容的良民, 也几次三番的被连坐...

    万般无奈下, 只好谋求把服务器搬离国内..

    鸣谢<a href="http://onemouse.cn">OneMouse.cn</a>友情赞助空间..
 
    有些图片和素材还没法倒过来, 等过俩天国内的服务器能访问了,我在copy过来.

</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/12/17/1182.html"  title="Permanet Link to 服务器搬到国外主机" >http://www.laruence.com/2009/12/17/1182.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
    在国内声势浩大的打击非法网站的行动中, 我这个有IPC备案, 无不良内容的良民, 也几次三番的被连坐&#8230;</p>
<p>    万般无奈下, 只好谋求把服务器搬离国内..</p>
<p>    鸣谢<a href="http://onemouse.cn" >OneMouse.cn</a>友情赞助空间..</p>
<p>    有些图片和素材还没法倒过来, 等过俩天国内的服务器能访问了,我在copy过来.</p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2371" >2009/12/17</a>, <a href="http://b.freefcw.cn"  rel="external nofollow"  class="url" >巫山霏云</a> writes: 嗯，我也遇到了，很烦恼~~
现在还在找出路中</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2372" >2009/12/17</a>, <a href="http://topsy.com/tb/url4.eu/x2ET"  rel="external nofollow"  class="url" >Tweets that mention 服务器搬到国外主机 » 风雪之隅 -- Topsy.com</a> writes: [...] This post was mentioned on Twitter by siko, Laruence. Laruence said: 服务器搬到国外主机 http://url4.eu/x2ET [...]</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2373" >2009/12/17</a>, <a href="http://www.chenbin.net"  rel="external nofollow"  class="url" >siko</a> writes: 申请blog友链,在Wave里发过消息给你 。 :)</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2375" >2009/12/18</a>, <a href="http://www.xklog.org"  rel="external nofollow"  class="url" >星空泪</a> writes: 我也被……无话可说，被迫搬家</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2376" >2009/12/18</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: 看来被连坐的同学还真多啊...</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2377" >2009/12/18</a>, Venkman writes: 楼主什么时候介绍下无敌穿墙术啊， 现在墙又加了几层， 郁郁啊， 祖国到底是亲妈还是后妈啊</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2378" >2009/12/18</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @siko done~</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2379" >2009/12/18</a>, <a href="http://www.zivee.cn"  rel="external nofollow"  class="url" >zivee</a> writes: 最近是事情确实搞有些心慌</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2380" >2009/12/18</a>, andy writes: 祖国不是亲妈也不是后妈，是他妈</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2418" >2010/01/04</a>, <a href="http://liuqingyan.blogspot.com"  rel="external nofollow"  class="url" >qy</a> writes: sigh...然后domain name白名单。。。然后IP白名单。。。呵呵。。。遁无可遁</li><li><a href="http://www.laruence.com/2009/12/17/1182.html#comment-2419" >2010/01/04</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @qy 唉..大中华局域网.</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/12/17/1182.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>isset和is_null的不同</title>
		<link>http://www.laruence.com/2009/12/09/1180.html</link>
		<comments>http://www.laruence.com/2009/12/09/1180.html#comments</comments>
		<pubDate>Wed, 09 Dec 2009 07:56:44 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[different]]></category>
		<category><![CDATA[isset]]></category>
		<category><![CDATA[is_null]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1180</guid>
		<description><![CDATA[<p>
	今天有人问我isset和is_null啥区别, 
	看手册上讲的话, isset和is_null的功能几乎完全"相反的一样"..
	是不是isset就是一个is_null的相反的别名?
	
	诶, 要说区别, 那还真的是很多~
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/12/09/1180.html"  title="Permanet Link to isset和is_null的不同" >http://www.laruence.com/2009/12/09/1180.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	今天有人问我isset和is_null啥区别, </p>
<p>	看手册上讲的话, isset和is_null的功能几乎完全&#8221;相反的一样&#8221;..</p>
<p>	是不是isset就是一个is_null的相反的别名?</p>
<p>	诶, 要说区别, 那还真的是很多~
</p>
<p>
<b>一切的不同都是因为: is_null是函数, isset是语句.</b></p>
<p>	isset是语句, 和echo, print一样, 是PHP本身的一种语言结构.</p>
<p>	而is_null是函数, 和我们一般的函数一样, 可以做为可变函数调用.</p>
<p>	你也许会说, 好了,好了,我知道函数和语句的区别, 但到底是TMD什么区别?</p>
<p>	诶, 所谓语句,语言结构, 就是说, 是语言本身支持的语句, 标识符. </p>
<p>	比如, for, foreach, continue 等等, 它们在语法分析的时刻就被&#8221;抹掉&#8221;(逻辑上替代了)了.</p>
<p>	让我们看看isset这个语句在语法分析的过程中, 是如何被&#8221;抹掉&#8221;的.</p>
<pre  style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 首先, 在词法分析的时候, isset会被识别为T_ISSET标识符.

2. 而在语法分析阶段, isset($var)这个指令, 会被分析成一条Opcode:ZEND_ISSET_ISEMPTY_VARS.
</pre>
<p>	你可以理解isset就想C语言里面的宏, 在编译/执行之前已经被展开了.</p>
<p>	因为这个,　所以在表现上,　会有如下的不同:</p>
<p>	因为is_null是函数, 所以它可以通过如下方式调用:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$var  = NULL;
$func = &quot;is_null&quot;;
$func($var);
?&gt;
</pre>
<p>	而, isset因为是语句, 所以不能这样调用.</p>
<p>	因为is_null是函数, 所以它可以接受函数返回值做为参数, 而isset不行(当然, 如果PHP想支持, 其实也是可以的, 只不过就要增加编译阶段的复杂度了):</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
is_null(intval(&quot;0x45&quot;));
//OK
isset(intval(&quot;0x45&quot;));
//PHP Fatal error:  Can't use function return value in write context
is_null(NULL);
//OK
isset(NULL);
//PHP Parse error:  syntax error
?&gt;
</pre>
<p>	说了这么多isset的缺点了,  说点它的优点吧:</p>
<p>	因为isset是语句, 所以它快!</p>
<p>	在一千万次的简单检测语句循环中, 对比结果如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$a=&quot;laruence&quot;:
isset($a);   //用时: 1.15s
is_null($a); //用时: 3.89s
?&gt;
</pre>
<p>	因为isset叫做isset, 所以它在检测未定义变量的时候, 不会产生NOTICE:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
isset($laruence);
//OK
is_null($laruence);
//PHP Notice:  Undefined variable: laruence
?&gt;
</pre>
<p>	那么, 对于什么时候用isset什么时候用is_null, 我有什么建议呢?</p>
<p>	诶, 我的建议是, 用函数做函数应该做的事情~, 听起来象废话?</p>
<p>	isset => is set? => 变量有没有被赋值(声明)</p>
<p>	is_null => is null? => 变量为NULL么?</p>
<p>	另外,　如果要用is_null,　我建议使用 &#8220;=== NULL&#8221; 来代替,　它不仅语义和is_null一致,　结果一致,　速度还和isset差不多:</p>
<p>	在一千万次的简单检测语句循环中, 对比结果如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
$a=&quot;laruence&quot;:
isset($a);      //用时: 1.15s
is_null($a);    //用时: 3.88s
$a===NULL;     //用时: 1.22s
?&gt;
</pre>
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/12/09/1180.html#comment-2355" >2009/12/09</a>, Platinum writes: 让他们直接看手册比较好些

http://www.php.net/manual/en/types.comparisons.php</li><li><a href="http://www.laruence.com/2009/12/09/1180.html#comment-2356" >2009/12/09</a>, <a href="http://www.xiaoxiaozi.com"  rel="external nofollow"  class="url" >simaopig</a> writes: 几乎没用过 is_null  都是 === NULL  不过mysql得用 isnull。。</li><li><a href="http://www.laruence.com/2009/12/09/1180.html#comment-2357" >2009/12/09</a>, <a href="http://willko.javaeye.com"  rel="external nofollow"  class="url" >Willko</a> writes: isset 是指变量是否声明了
isnull 是指变量的值是否为null</li><li><a href="http://www.laruence.com/2009/12/09/1180.html#comment-2358" >2009/12/16</a>, <a href="http://hqlong.com"  rel="external nofollow"  class="url" >hqlong</a> writes: 这风格太黑了，没有以前的视觉效果好</li><li><a href="http://www.laruence.com/2009/12/09/1180.html#comment-2360" >2009/12/16</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: 唉,我换了个国外的服务器,国内的老因为封黄网被连坐</li><li><a href="http://www.laruence.com/2009/12/09/1180.html#comment-2395" >2009/12/28</a>, <a href="http://www.simaliu.com/"  rel="external nofollow"  class="url" >simaliu</a> writes: 受教了</li><li><a href="http://www.laruence.com/2009/12/09/1180.html#comment-2450" >2010/02/01</a>, <a href="http://www.phpfamily.cn"  rel="external nofollow"  class="url" >xiaokai</a> writes: 那empty是呢?</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/12/09/1180.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>PHP5.2.x + APC的一个bug的定位</title>
		<link>http://www.laruence.com/2009/12/05/1172.html</link>
		<comments>http://www.laruence.com/2009/12/05/1172.html#comments</comments>
		<pubDate>Sat, 05 Dec 2009 07:39:24 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[apc]]></category>
		<category><![CDATA[core]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[session]]></category>
		<category><![CDATA[spl_autoload]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1172</guid>
		<description><![CDATA[昨天环境迁移, 脚本出core, 因为之前的环境上运行正常, 所以初步认为是环境问题. 通过对core文件的分析, 初步发现原因和spl_autoload相关, backtrace如下:
<coolcode lang="bash" linenum="off">
#0  zif_spl_autoload (ht=Variable "ht" is not available.)
at /home/huixinchen/package/php-5.2.11/ext/spl/php_spl.c:310
310   if (active_opline->opcode != ZEND_FETCH_CLASS) {

(gdb) bt
#0  zif_spl_autoload (ht=Variable "ht" is not available.
	) at /home/huixinchen/package/php-5.2.11/ext/spl/php_spl.c:310
#1  0x00000000006a5da5 in zend_call_function (fci=0x7fbfffc100, 
		fci_cache=Variable "fci_cache" is not available.)
at /home/huixinchen/package/php-5.2.11/Zend/zend_execute_API.c:1052
.....
</coolcode>
脚本很简单, 通过session_set_save_handler注册了一个类为session的user handler.

去掉spl_autoload以后,  不出core了, 但是每次都会抛出Class not found的异常, 可见core确实和spl_autoload有关, 但是这个Class ** not found的fatal error问题又和什么相关呢, 这个fatal error是否是导致spl_autoload core 的直接原因呢?

代码本身并没有任何问题, 对环境做了对比以后, 初步认定为新环境启用了APC的缘故.

在bug.php中找到了有人报告类似的bug(<a href="http://bugs.php.net/bug.php?id=49867&#038;edit=2" target="_blank">spl_autoload crashes when called in write function of custom sessionSaveHandler</a>), 但没有任何一个人给出原因,或者解决的办法. 

看来, 只能自己分析了....]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/12/05/1172.html"  title="Permanet Link to PHP5.2.x + APC的一个bug的定位" >http://www.laruence.com/2009/12/05/1172.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
昨天环境迁移, 脚本出core, 因为之前的环境上运行正常, 所以初步认为是环境问题. 通过对core文件的分析, 初步发现原因和spl_autoload相关, backtrace如下:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#0  zif_spl_autoload (ht=Variable &quot;ht&quot; is not available.)
at /home/huixinchen/package/php-5.2.11/ext/spl/php_spl.c:310
310   if (active_opline-&gt;opcode != ZEND_FETCH_CLASS) {

(gdb) bt
#0  zif_spl_autoload (ht=Variable &quot;ht&quot; is not available.
	) at /home/huixinchen/package/php-5.2.11/ext/spl/php_spl.c:310
#1  0x00000000006a5da5 in zend_call_function (fci=0x7fbfffc100,
		fci_cache=Variable &quot;fci_cache&quot; is not available.)
at /home/huixinchen/package/php-5.2.11/Zend/zend_execute_API.c:1052
.....
</pre>
<p>脚本很简单, 通过session_set_save_handler注册了一个类为session的user handler.</p>
<p>去掉spl_autoload以后,  不出core了, 但是每次都会抛出Class not found的异常, 可见core确实和spl_autoload有关, 但是这个Class ** not found的fatal error问题又和什么相关呢, 这个fatal error是否是导致spl_autoload core 的直接原因呢?</p>
<p>代码本身并没有任何问题, 对环境做了对比以后, 初步认定为新环境启用了APC的缘故.</p>
<p>在bug.php中找到了有人报告类似的bug(<a href="http://bugs.php.net/bug.php?id=49867&#038;edit=2"  target="_blank" >spl_autoload crashes when called in write function of custom sessionSaveHandler</a>), 但没有任何一个人给出原因,或者解决的办法. </p>
<p>看来, 只能自己分析了&#8230;.
</p>
<p>
精简的代码如下:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
/**
 * PHP5.2.11 with APC Fatal Error example
 * by laruence(http://www.laruence.com)
 */
class Laruence {
	public static function start() {
		session_set_save_handler(array(__CLASS__, &quot;open&quot;),
				array(__CLASS__, &quot;close&quot;), array(__CLASS__, &quot;read&quot;),
				array(__CLASS__, &quot;write&quot;), array(__CLASS__, &quot;destroy&quot;),
				array(__CLASS__, &quot;gc&quot;));
		session_start();
	}
	public static function open($strPath, $strSessName) {
		return true;
	}
	public static function close() {
		var_dump(class_exists(__CLASS__, false));
	}
	public static function read($strSessId) {
	}
	public static function write($strSessId, $strData) {
	}
	public static function destroy($strSessId) {
	}
	public static function gc($intMaxLifeTime) {
		return true;
	}
}
Laruence::start();
?&gt;
</pre>
<p>当第一次请求这个页面的时候, 一切正常, 当再次请求的时候, 就会产生:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
PHP Fatal error:  Class 'Laruence' not found in Unknown on line 0
</pre>
<p>可见, 这个原因一定是和APC缓存了脚本编译结果以后有关.</p>
<p>翻看APC的源码, 发现了一处可怀疑之处, apc_main.c中:</p>
<pre name="code"  class="sh_cpp"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
static void apc_deactivate(TSRMLS_D) //此函数在请求关闭期间被调用
{
while (apc_stack_size(APCG(cache_stack)) &gt; 0) {
...//有省略
	if (cache_entry-&gt;data.file.classes) {
		for (i = 0; cache_entry-&gt;data.file.classes[i].class_entry != NULL; i++) {
			if(zend_hash_find(EG(class_table),
					cache_entry-&gt;data.file.classes[i].name,
					cache_entry-&gt;data.file.classes[i].name_len+1,
					(void**)centry) == FAILURE) {
						continue;
			}
			//注意这里:
			zend_hash_del(EG(class_table),
					cache_entry-&gt;data.file.classes[i].name,
					cache_entry-&gt;data.file.classes[i].name_len+1);
			apc_free_class_entry_after_execution(zce);
		}
	}

	...//有省略
}
}
</pre>
<p>也就是说, APC在模块请求关闭函数时期, 清空了执行全局标量中的类定义表EG(classs_table), 根据我的经验, 问题可能就在这里.</p>
<p>经过反复验证: 改hanlder,  跟踪源码, gdb,, 最后问题定位确定, 确实就是这个原因(对不住女朋友了, 搞到半夜快2点才最终确定问题):</p>
<p>恩, 我之前的文章介绍过PHP的扩展载入过程(<a href="http://www.laruence.com/2009/06/14/945.html"  target="_blank" >深入理解PHP原理之扩展载入过程</a>), 但没有涉及到模块关闭过程.</p>
<p>而这个问题就和模块载入顺序和模块关闭函数很有关系了. 总体来说, 就是PHP会根据模块载入的顺序的反序来在每次请求处理结束后依次调用各个扩展的请求关闭函数.</p>
<p>因为我们环境的Session是静态编译进PHP的, 所以Session模块一定先于动态编译进PHP的APC被载入, 也就是说, 在请求关闭时期, APC的请求关闭函数, 一定会先于Session的请求关闭函数被调用.</p>
<p>所以,当Session的请求关闭函数调用的时候, 执行环境的Class Table已经为空, 当然也就会抛出类找不到的fatalerror了.</p>
<p>而, 第一次请求的时候, 因为页面没有被缓存, 所以apc_stack_size(APCG(cache_stack))的条件判断不成立, 也就不会有清除class table的动作发生.</p>
<p>基于此, 为什么在spl_autoload启用以后, 产生core, 也就很明显了.</p>
<p>因为在zif_spl_autoload中, 对active_opline接引用, 而此时执行已经结束, active_opline为空, 所以,segment fault了.</p>
<p>那么, 如何解决这个问题呢?</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
1. 关闭APC //废话,我也知道, 呵呵
2. 改用函数做为session_set_save_handler的user handler.
3. 把seesion模块做为动态模块载入PHP, 并保证它后于APC被载入. //这个解决方法靠谱.
</pre>
<p>关于APC的执行原理, 大家如果有兴趣, 我过段再单独写篇blog.</p>
<p>最后, APC是好, 但一致没有被做为PHP的标准扩展, 也是有原因的. 它劫持了PHP自身的complie_file, 加入了很多局部性很强的逻辑&#8230;</p>
<p>一句话, APC虽好, 但须慎用.</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_cpp.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/12/05/1172.html#comment-2353" >2009/12/06</a>, 玉丰 writes: 最近也在折腾gdb，看了一下这篇文章，（还不会如何去backtrace PHP的运行），呵呵，继续学习。</li><li><a href="http://www.laruence.com/2009/12/05/1172.html#comment-2354" >2009/12/07</a>, <a href="www.phppan.com"  rel="external nofollow"  class="url" >phppan</a> writes: 围观，学习！</li><li><a href="http://www.laruence.com/2009/12/05/1172.html#comment-2359" >2009/12/16</a>, kimjxie writes: 在代码末 强制执行session_write_close()也可解决问题</li><li><a href="http://www.laruence.com/2009/12/05/1172.html#comment-2374" >2009/12/17</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @kimjxie 赞~, 这是提前了关闭的时机. 这个bug还是依然值得探讨的. ;)</li><li><a href="http://www.laruence.com/2009/12/05/1172.html#comment-2429" >2010/01/15</a>, <a href="http://www.baidu.com"  rel="external nofollow"  class="url" >wakaka</a> writes: 博主的PHP和C的功力实在是国内少有的高手。</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/12/05/1172.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>memory_limit的一个bug</title>
		<link>http://www.laruence.com/2009/11/27/1164.html</link>
		<comments>http://www.laruence.com/2009/11/27/1164.html#comments</comments>
		<pubDate>Fri, 27 Nov 2009 09:40:02 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php bug]]></category>
		<category><![CDATA[php源码分析]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1164</guid>
		<description><![CDATA[<p>
		PHP 5.2x中, 由于错误的选用了zend_atoi, 导致memory_limit不能设置为超过4G的值.

	今天同事分享给我一个问题(thans to yanmi), 一段代码(PHP 5.2.11 Linux/X86_64),设置memory_limit为4096M会导致内存耗尽, 而设置4095M就不会.  奇怪的问题呵.

	那是怎么回事呢?
</p>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/11/27/1164.html"  title="Permanet Link to memory_limit的一个bug" >http://www.laruence.com/2009/11/27/1164.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	PHP 5.2x中, 由于错误的选用了zend_atoi, 导致memory_limit不能设置为超过4G的值.</p>
<p>	今天同事分享给我一个问题(thans to yanmi), 一段代码(PHP 5.2.11 Linux/X86_64),设置memory_limit为4096M会导致内存耗尽, 而设置4095M就不会.  奇怪的问题呵.</p>
<p>	那是怎么回事呢?
</p>
<p>	问题的原因也很简单, 在PHPSRC/main.c中定义的memory_limit设置项的处理器OnChangeMemoryLimit中, 并没有检测当前的机器字长, 而统一使用了zend_atoi来做为字符串数字化, 这个问题在PHP5.3的版本中已经修正(换成了zend_atol):</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
static PHP_INI_MH(OnChangeMemoryLimit)
{
    if (new_value) {
        PG(memory_limit) = zend_atoi(new_value, new_value_length);
    } else {
        PG(memory_limit) = 1&lt;&lt;30;       /* effectively, no limit */
    }
    return zend_set_memory_limit(PG(memory_limit));
}
</pre>
<p>	而, 顾名思义么, atoi是转成整形, 4096M是2的32次方, 发生溢出, 继而环绕成结果为0, zend_atoi代码如下:</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
ZEND_API int zend_atoi(const char *str, int str_len)
{
    int retval;

    if (!str_len) {
        str_len = strlen(str);
    }
    retval = strtol(str, NULL, 0);
    if (str_len&gt;0) {
        switch (str[str_len-1]) {
            case 'g':
            case 'G':
                retval *= 1024;
                /* break intentionally missing */
            case 'm':
            case 'M':
                retval *= 1024;
                /* break intentionally missing */
            case 'k':
            case 'K':
                retval *= 1024;
                break;
        }
    }
    return retval;
}
</pre>
<p>最后在zend_set_memory_limit的时候, 会错误的设置memory_limit为mm_heap的blok_size, 那结果就肯定远远小与你所预期的4096M了</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
....
 AG(mm_heap)-&gt;limit = (memory_limit &gt;= AG(mm_heap)-&gt;block_size) ? memory_limit : AG(mm_heap)-&gt;block_size;
...
</pre>
<p>最后, 如果是32位的机器,  那确实不算bug,  但现在的机器很多都64了, 最大内存也不再是4GB了, PHP也要与时俱进啊.</p>
<p>PS, 多看别人的代码是有好处的, 今天有学会了intentionally这个单词, ^_^.<br/>
<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2338" >2009/11/27</a>, <a href="http://onemouse.cn"  rel="external nofollow"  class="url" >Anders</a> writes: 真的使用了4G内存？

那我们这些开发机只有512M内存的人怎么活啊?</li><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2339" >2009/11/27</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @Anders 呵呵, 现在的服务器都不止4G的内存了..., 不过这个bug确实影响不大..</li><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2340" >2009/11/27</a>, fortruth writes: 果然， 今天我也学到了 intentionally 这个单词。 :)</li><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2342" >2009/11/27</a>, kevin writes: 4个G内存消耗确实不常见，但有时需要遍历一些数据库操作大数据集的时候还是比较容易碰到的。

分析的不错！另：1&lt;&lt;30是多大？</li><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2343" >2009/11/27</a>, kevin writes: 另：1&lt;&lt;30是多大？

--------------------------

应该是pow(2,30)吧,2的30次方。</li><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2345" >2009/11/29</a>, <a href="http://www.xklog.org"  rel="external nofollow"  class="url" >星空泪</a> writes: 占用 4G 内存的程序大概需要优化了……</li><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2348" >2009/12/02</a>, Anonymous writes: 脚本语言估计是不会 要 4G 内存的了。</li><li><a href="http://www.laruence.com/2009/11/27/1164.html#comment-2349" >2009/12/02</a>, laruence writes: @Anonymous 恩, 这个只是就问题而说问题, 再说,设置成4096,不代表就要用4096么, ;_)</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/11/27/1164.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>automake,autoconf使用详解</title>
		<link>http://www.laruence.com/2009/11/18/1154.html</link>
		<comments>http://www.laruence.com/2009/11/18/1154.html#comments</comments>
		<pubDate>Wed, 18 Nov 2009 08:37:50 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[GNU C/C++]]></category>
		<category><![CDATA[转载]]></category>
		<category><![CDATA[aclocal]]></category>
		<category><![CDATA[autoconf]]></category>
		<category><![CDATA[automake]]></category>
		<category><![CDATA[configure]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1154</guid>
		<description><![CDATA[    作为Linux下的程序开发人员,大家一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Makefile,如果要想写出一个符合自由软件惯例的Makefile就不那么容易了.

    在本文中,将给大家介绍如何使用autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的 Makefile,这样就可以象常见的 GNU程序一样,只要使用"./configure","make","make instal"就可以把程序安装到Linux系统中去了.

    这将特别适合想做开放源代码软件的程序开发人员,又或如果你只是自己写些小的Toy程序,那么这个文章对你也会有很大的帮助.
转自:<a href="http://www.linuxcomputer.cn/jishuwendang/xinshourumen/200902/03-3029.html">http://www.linuxcomputer.cn/jishuwendang/xinshourumen/200902/03-3029.html</a>]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>本文地址: <a href="http://www.laruence.com/2009/11/18/1154.html"  title="Permanet Link to automake,autoconf使用详解" >http://www.laruence.com/2009/11/18/1154.html</a></li>
<li>文章转自: <a href="http://www.linuxcomputer.cn/jishuwendang/xinshourumen/200902/03-3029.html" >http://www.linuxcomputer.cn/</a></li>
</ul></div>
<p>	作为Linux下的程序开发人员,大家一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便.一般情况下,大家都是手工写一个简单Makefile,如果要想写出一个符合自由软件惯例的Makefile就不那么容易了.</p>
<p>	在本文中,将给大家介绍如何使用autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的 Makefile,这样就可以象常见的 GNU程序一样,只要使用&#8221;./configure&#8221;,&#8221;make&#8221;,&#8221;make instal&#8221;就可以把程序安装到Linux系统中去了.</p>
<p>       这将特别适合想做开放源代码软件的程序开发人员,又或如果你只是自己写些小的Toy程序,那么这个文章对你也会有很大的帮助.<br/>
　<br/>
<h3>一.Makefile介绍</h3>
<p>　　Makefile是用于自动编译和链接的 ,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是 所有的文件都需要重新编译,Makefile中纪录有文件的信息,在 make时会决定在链接的时候需要重新编译哪些文件.<br/>
　<br/>
　	Makefile的宗旨就是 ：让编译器知道要编译一个文件需要依赖其他的 哪些文件.当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的 模块.<br/>
　　<br/>
	Makefile的 基本结构不是 很复杂,但当一个程序开发人员开始写Makefile时,经常会怀疑自己写的 是 否符合惯例,而且自己写的 Makefile经常和自己的 开发环境相关联,当系统环境变量或路径发生了变化后,Makefile可能还要跟着修改.这样就造成了手工书写Makefile的 诸多问题,automake恰好能很好地帮助我们解决这些问题.<br/>
　　<br/>
	使用automake,程序开发人员只需要写一些简单的 含有预定义宏的 文件,由autoconf根据一个宏文件生成configure,由automake根据另一个宏文件生成Makefile.in,再使用configure依据Makefile.in来生成一个符合惯例的 Makefile.下面我们将详细介绍Makefile的 automake生成方法.<br/>
　　</p>
<h3>二.使用的 环境</h3>
<p>　　本文所提到的 程序是 基于Linux发行版本：Fedora Core release 1,它包含了我们要用到的 autoconf,automake.</p>
<p>　　<br/>
<h3>三.从helloworld入手</h3>
<p>　　我们从大家最常使用的 例子程序helloworld开始.</p>
<p>　　下面的 过程如果简单地说来就是 ：</p>
<p>　　新建三个文件：</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
　　　helloworld.c
　　　configure.in
　　　Makefile.am
</pre>
<p>　　然后执行：</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
aclocal; autoconf; automake --add-missing; ./configure; make; ./helloworld
</pre>
<p>　　就可以看到Makefile被产生出来,而且可以将helloworld.c编译通过.</p>
<p>　　很简单吧,几条命令就可以做出一个符合惯例的 Makefile,感觉如何呀.</p>
<p>　　<b>现在 开始介绍详细的 过程：</b></p>
<p>　　1.建目录</p>
<p>　　在 你的 工作目录下建一个helloworld目录,我们用它来存放helloworld程序及相关文件,如在 /home/my/build下：</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ mkdir helloword
$ cd helloworld
</pre>
<p>　　2. helloworld.c</p>
<p>　　然后用你自己最喜欢的 编辑器写一个hellowrold.c文件,如命令：vi helloworld.c.使用下面的 代码作为helloworld.c的 内容.</p>
<pre name="code"  class="sh_c"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
#include &lt;stdio.h&gt;
int main(int argc, char** argv){
	printf(&quot;%s&quot;, 'Hello, Linux World!\n&quot;);
	return 0;
}
</pre>
<p>　　完成后保存退出.<br/>
　　现在 在 helloworld目录下就应该有一个你自己写的 helloworld.c了.</p>
<p>　　3.生成configure</p>
<p>　　我们使用autoscan命令来帮助我们根据目录下的 源代码生成一个configure.in的 模板文件.<br/>
　　命令：</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ autoscan
$ ls
configure.scan helloworld.c
</pre>
<p>　　执行后在 hellowrold目录下会生成一个文件：configure.scan,我们可以拿它作为configure.in的 蓝本.<br/>
　　现在 将configure.scan改名为configure.in,并且编辑它,按下面的 内容修改,去掉无关的 语句：</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
==========================configure.in内容开始=========================================
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_INIT(helloworld.c)
AM_INIT_AUTOMAKE(helloworld, 1.0)
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_OUTPUT(Makefile)
==========================configure.in内容结束=========================================
</pre>
<p>　　然后执行命令aclocal和autoconf,分别会产生aclocal.m4及configure两个文件：</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ aclocal
$ls
aclocal.m4 configure.in helloworld.c
$ autoconf
$ ls
aclocal.m4 autom4te.cache configure configure.in helloworld.c
</pre>
<p>　　大家可以看到configure.in内容是 一些宏定义,这些宏经autoconf处理后会变成检查系统特性.环境变量.软件必须的 参数的 shell脚本.</p>
<p>　　autoconf 是 用来生成自动配置软件源代码脚本（configure）的 工具.configure脚本能独立于autoconf运行,且在 运行的 过程中,不需要用户的 干预.</p>
<p>　　要生成configure文件,你必须告诉autoconf如何找到你所用的 宏.方式是 使用aclocal程序来生成你的 aclocal.m4.</p>
<p>　　aclocal根据configure.in文件的 内容,自动生成aclocal.m4文件.aclocal是 一个perl 脚本程序,它的 定义是 ：&#8221;aclocal &#8211; create aclocal.m4 by scanning configure.ac&#8221;.</p>
<p>　　autoconf从configure.in这个列举编译软件时所需要各种参数的 模板文件中创建configure.</p>
<p>　　autoconf需要GNU m4宏处理器来处理aclocal.m4,生成configure脚本.</p>
<p>　　m4是 一个宏处理器.将输入拷贝到输出,同时将宏展开.宏可以是 内嵌的 ,也可以是 用户定义的 .除了可以展开宏,m4还有一些内建的 函数,用来引用文件,执行命令,整数运算,文本操作,循环等.m4既可以作为编译器的 前端,也可以单独作为一个宏处理器.</p>
<p>4.新建Makefile.am<br/>
　　新建Makefile.am文件,命令：</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ vi Makefile.am
　　内容如下:
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=helloworld
helloworld_SOURCES=helloworld.c
</pre>
<p>　　automake会根据你写的 Makefile.am来自动生成Makefile.in.</p>
<p>　　Makefile.am中定义的 宏和目标,会指导automake生成指定的 代码.例如,宏bin_PROGRAMS将导致编译和连接的 目标被生成.<br/>
　　5.运行automake:</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ automake --add-missing
configure.in: installing `./install-sh'
configure.in: installing `./mkinstalldirs'
configure.in: installing `./missing'
Makefile.am: installing `./depcomp'
</pre>
<p>　　automake会根据Makefile.am文件产生一些文件,包含最重要的 Makefile.in.</p>
<p>　　6.执行configure生成Makefile</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
$ ls -l Makefile
-rw-rw-r-- 1 yutao yutao 15035 Oct 15 10:40 Makefile
</pre>
<p>你可以看到,此时Makefile已经产生出来了.</p>
<p>7.使用Makefile编译代码</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$make
if gcc -DPACKAGE_NAME=\&quot;FULL-PACKAGE-NAME\&quot; -DPACKAGE_TARNAME=\&quot;full-package-name\&quot; -DPACKAGE_VERSION=\&quot;VERSION\&quot; -DPACKAGE_STRING=\&quot;FULL-PACKAGE-NAME\ VERSION\&quot; -DPACKAGE_BUGREPORT=\&quot;BUG-REPORT-ADDRESS\&quot; -DPACKAGE=\&quot;helloworld\&quot; -DVERSION=\&quot;1.0\&quot; -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDLIB_H=1  -I. -I.     -g -O2 -MT helloworld.o -MD -MP -MF &quot;.deps/helloworld.Tpo&quot; -c -o helloworld.o helloworld.c; \
then mv -f &quot;.deps/helloworld.Tpo&quot; &quot;.deps/helloworld.Po&quot;; else rm -f &quot;.deps/helloworld.Tpo&quot;; exit 1; fi
gcc  -g -O2   -o helloworld  helloworld.o
</pre>
<p>　　运行helloworld</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$ ./helloworld
Hello, Linux World!
</pre>
<p>　　这样helloworld就编译出来了,你如果按上面的 步骤来做的 话,应该也会很容易地编译出正确的 helloworld文件.你还可以试着使用一些其他的 make命令,如make clean,make install,make dist,看看它们会给你什么样的 效果.感觉如何？自己也能写出这么专业的 Makefile,老板一定会对你刮目相看.</p>
<h3>四.深入浅出</h3>
<p>　　针对上面提到的 各个命令,我们再做些详细的 介绍.</p>
<pre  style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
　　1. autoscan
　　autoscan是 用来扫描源代码目录生成configure.scan文件的 .autoscan
可以用目录名做为参数,但如果你不使用参数的 话,那么autoscan将认为使用的是当前目录.
autoscan将扫描你所指定目录中的 源文件,并创建configure.scan文件.
　　2. configure.scan
　　configure.scan包含了系统配置的 基本选项,里面都是 一些宏定义.我们需要将它改名为
configure.in
　　3. aclocal
　　aclocal是 一个perl 脚本程序.aclocal根据configure.in文件的 内容
,自动生成aclocal.m4文件.aclocal的 定义是 ："aclocal - create
aclocal.m4 by scanning configure.ac".
　　4. autoconf
　　autoconf是 用来产生configure文件的 .configure是 一个脚本,它能设置
源程序来适应各种不同的操作系统平台,并且根据不同的 系统来产生合适的 Makefile,从而可以使
你的源代码能在不同的操作系统平台上被编译出来.
　　configure.in文件的 内容是 一些宏,这些宏经过autoconf 处理后会变成检查系统
特性.环境变量.软件必须的 参数的 shell脚本.configure.in文件中的 宏的 顺序并没
有规定,但是 你必须在 所有宏的 最前面和最后面分别加上AC_INIT宏和AC_OUTPUT宏.
　　在 configure.ini中：
　　#号表示注释,这个宏后面的 内容将被忽略.
　　AC_INIT(FILE)
　　这个宏用来检查源代码所在 的 路径.
AM_INIT_AUTOMAKE(PACKAGE, VERSION)
　　 这个宏是 必须的 ,它描述了我们将要生成的 软件包的 名字及其版本号：PACKAGE是软件包
的名字,VERSION是 版本号.当你使用make dist命令时,它会给你生成一个类似
helloworld-1.0.tar.gz的 软件发行包,其中就有对应的 软件包的 名字和版本号.
AC_PROG_CC
　　这个宏将检查系统所用的 C编译器.
AC_OUTPUT(FILE)
　　这个宏是 我们要输出的 Makefile的 名字.
　　我们在 使用automake时,实际上还需要用到其他的 一些宏,但我们可以用aclocal 来帮
我们自动产生.执行aclocal后我们会得到aclocal.m4文件.
　　产生了configure.in和aclocal.m4 两个宏文件后,我们就可以使用autocon
f来产生configure文件了.
　　5. Makefile.am
　　Makefile.am是 用来生成Makefile.in的 ,需要你手工书写.Makefile.
am中定义了一些内容：
AUTOMAKE_OPTIONS
　　这个是 automake的 选项.在 执行automake时,它会检查目录下是 否存在 标准
GNU软件包中应具备的各种文件,例如AUTHORS.ChangeLog.NEWS等文件.
我们将其设置成foreign时,automake会改用一般软件包的 标准来检查.
bin_PROGRAMS
　　这个是 指定我们所要产生的 可执行文件的 文件名.如果你要产生多个可执行文件,
那么在各个名字间用空格隔开.
helloworld_SOURCES
　　这个是 指定产生"helloworld"时所需要的 源代码.如果它用到了多个源文件,
那么请使用空格符号将它们隔开.比如需要helloworld.h,helloworld.c那么请写成:
helloworld_SOURCES= helloworld.h helloworld.c.
　　如果你在 bin_PROGRAMS定义了多个可执行文件,则对应每个可执行文件都要定义相对的
filename_SOURCES.
　　6. automake
　　我们使用automake --add-missing来产生Makefile.in.
　　选项--add-missing的 定义是 "add missing standard files
 to package",它会让automake加入一个标准的 软件包所必须的 一些文件.
　　我们用automake产生出来的 Makefile.in文件是 符合GNU Makefile惯例
的 ,接下来我们只要执行configure这个shell 脚本就可以产生合适的 Makefile 文
件了.
　　7. Makefile
　　在 符合GNU Makefiel惯例的 Makefile中,包含了一些基本的 预先定义的 操作：

make
　　根据Makefile编译源代码,连接,生成目标文件,可执行文件.
make clean
　　清除上次的 make命令所产生的 object文件（后缀为".o"的 文件）及可执行文件.
make install
　　将编译成功的 可执行文件安装到系统目录中,一般为/usr/local/bin目录.
make dist
　　产生发布软件包文件（即distribution package）.这个命令将会将可执行文件及相关
文件打包成一个tar.gz压缩的 文件用来作为发布软件的 软件包.
　　它会在 当前目录下生成一个名字类似"PACKAGE-VERSION.tar.gz"的 文件.PA
CKAGE和VERSION,是 我们在 configure.in中定义的 AM_INIT_AUTOM
AKE(PACKAGE, VERSION).
make distcheck
　　生成发布软件包并对其进行测试检查,以确定发布包的正确性.
</pre>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_c.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/11/18/1154.html#comment-2444" >2010/01/25</a>, Nathan writes: That's awesome!
It would be great help for me.</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/11/18/1154.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>分割GBK中文遭遇乱码的解决</title>
		<link>http://www.laruence.com/2009/11/16/1147.html</link>
		<comments>http://www.laruence.com/2009/11/16/1147.html#comments</comments>
		<pubDate>Mon, 16 Nov 2009 07:57:12 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[随笔]]></category>
		<category><![CDATA[explode]]></category>
		<category><![CDATA[gbk]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1147</guid>
		<description><![CDATA[今天有朋友提到一个问题, 类似如下的字符串(GBK), explode不能得到正确结果:
<coolcode lang="php" linenum="off">
$result = explode("&#124;", "滕华弢&#124;海青"); //(插一句, 蜗居最近很火啊)
</coolcode>
究其原因, 对于"弢"字(读tao,不认识没关系,我也不认识), 因为他的GBK编码值为: 8f7c, 不巧的是, "&#124;"的ASCII值也是7c.

这样的问题, 还有很多...]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/11/16/1147.html"  title="Permanet Link to 分割GBK中文遭遇乱码的解决" >http://www.laruence.com/2009/11/16/1147.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>今天有朋友提到一个问题, 类似如下的字符串(GBK), explode不能得到正确结果:</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
$result = explode(&quot;|&quot;, &quot;滕华弢|海青&quot;); //(插一句, 蜗居最近很火啊)
</pre>
<p>究其原因, 对于&#8221;弢&#8221;字(读tao,不认识没关系,我也不认识), 因为他的GBK编码值为: 8f7c, 不巧的是, &#8220;|&#8221;的ASCII值也是7c.</p>
<p>这样的问题, 还有很多 : 因为GBK编码的编码范围是: 0&#215;8140-0xfefe, 所以, 理论上来说, 任何低字节是7c的字都会有这个问题, 比如:</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
倈(827c), 億(837c), 眧(b17c), 鍇(e57c).......等等等等.
</pre>
<p>对于这样的情况, </p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
第一, 可以采用转码到utf8, 然后explode, 再转回来, 这是比较麻烦的方法.

第二, 我们可以采用正则拿&quot;匹配出&quot;来代替&quot;分离出&quot;:
    preg_match_all(&quot;/([\x81-\xfe][\x40-\xfe])+/&quot;, $gbk_str, $matches);//写死编码值
</pre>
<p>这样, $matches中0号索引对应的数组就是结果词的数组了..<script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2317" >2009/11/16</a>, <a href="http://www.sina.com.cn"  rel="external nofollow"  class="url" >zorro</a> writes: 用了第一种方法  谢谢鸟哥</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2318" >2009/11/16</a>, <a href="http://www.xiaoxiaozi.com"  rel="external nofollow"  class="url" >simaopig</a> writes: GBK编码：0×8040-0xffff, 
正则：[\\\\x80-\\\\xff][\\\\x40-\\\\xff]+
这样的组合就是前两位的80-ff结合后两位40-ff之间的所有字符，+表示出现一次或多次，贪婪模式，所以就是按非汉字分隔
赞，相当帅了，鸟哥，我爱死你了。</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2319" >2009/11/16</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @simaopig  ...你的头像双人照.....</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2320" >2009/11/16</a>, cody writes: 还是第一种方法有通用性，第二种方法除了中文外要考虑其他字符太多。</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2322" >2009/11/17</a>, PeterYu writes: 如果不是gbk，倒可以使用mb_split来分割。
可惜mb的正则库只接受gb2312,不接受cp936即gbk.
UTF8也能直接使用。这时就体现出UTF8的好处了。。</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2323" >2009/11/17</a>, gently writes: 吼吼，可以把分割符换了，例如："&gt;|&lt;"，即用3个字符来分隔</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2324" >2009/11/17</a>, <a href="http://b.freefcw.cn"  rel="external nofollow"  class="url" >巫山霏云</a> writes: 我觉得还是utf-8比较靠谱一点</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2325" >2009/11/19</a>, 关注者 writes: 弱弱的问一句：如何得到汉字的编码，呵呵</li><li><a href="http://www.laruence.com/2009/11/16/1147.html#comment-2326" >2009/11/20</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @关注着 1,查编码表 2,用16位编辑器, 3,在php中使用unpack, 4, 在js中使用charCodeAt .... 等等等等</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/11/16/1147.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Nginx(PHP/fastcgi)的PATH_INFO问题</title>
		<link>http://www.laruence.com/2009/11/13/1138.html</link>
		<comments>http://www.laruence.com/2009/11/13/1138.html#comments</comments>
		<pubDate>Fri, 13 Nov 2009 06:48:15 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[Linux/Unix]]></category>
		<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[path_info]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1138</guid>
		<description><![CDATA[PATH_INFO是一个CGI 1.1的标准，经常用来做为传参载体.

在Apache中, 当不加配置的时候, 对于PHP脚本, AcceptPathInfo是默认接受的, 也就是说:


如果在服务器在存在一个/laruence/info.php

那么, 对于如下请求, Apache都接受:
<coolcode lang="bash" linenum="off">
/laruence/info.php/dummy
/laruence/info.php/pathinfo
</coolcode>
而对于Nginx下, 默认Nginx是不支持PATH INFO的, 也就是说, 对于上面的访问, 会是404, 提示找不到文件出错.]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/11/13/1138.html"  title="Permanet Link to Nginx(PHP/fastcgi)的PATH_INFO问题" >http://www.laruence.com/2009/11/13/1138.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>PATH_INFO是一个CGI 1.1的标准，经常用来做为传参载体. </p>
<p>比如, 我们可以使用PATH_INFO来代替Rewrite来实现伪静态页面, 另外不少PHP框架也使用PATH_INFO来作为路由载体.</p>
<p>在Apache中, 当不加配置的时候, 对于PHP脚本, AcceptPathInfo是默认接受的, 也就是说:</p>
<p>如果在服务器在存在一个/laruence/index.php</p>
<p>那么, 对于如下请求, </p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
/laruence/index.php/dummy
/laruence/dummy
</pre>
<p>Apache都接受,  都会认为是对info.php的访问, 并会设置PATH_INFO为dummy</p>
<p>而对于Nginx下, 是不支持PATH INFO的, 也就是它不会默认设置PATH_INFO. </p>
<p>而因为默认的配置文件对PHP的支持只是很基础的, 所以对于默认配置来说对于上面的访问也会是404, 提示找不到文件出错.</p>
<p>这对于一些使用PATH_INFO来传递关键信息的PHP框架来说(比如Kohana, Thinkphp), 简直是致命的.</p>
<p>对于这个问题, 一般来说有俩种解决方法, 第一种就是使用rewrite, 但是这个方法的缺点也是很明显的, 需要把PATH_INFO转换成Query String. 此处就不说明这种方法了~</p>
<p>而, 第二种方法就是我今天要提的, 模拟PATH_INFO:</p>
<p>首先 , 我们知道在Nginx中, 是通过对文件名的扩展名匹配, 来决定是否要交给php cgi服务器去解释的. 在nginx.conf中一般都有如下的默认配置段:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
location ~ .php$ {
	fastcgi_index  index.php;
	fastcgi_pass   127.0.0.1:9000;
	include        fastcgi_params;
}
</pre>
<p>所以,对于形如/laruence/info.php/pathinfo这样的文件路径, Nginx是不会正确的交给php cgi服务器的. 所以我们需要改写这段配置为:</p>
<pre name="code"  class="sh_sh"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
	location ~ .php {//片段匹配
	fastcgi_index  index.php;
	fastcgi_pass   127.0.0.1:9000;
	include        fastcgi_params;
}
</pre>
<p>现在, 脚本路径已经交由PHP自己处理了. 那怎么增加PATH_INFO呢?</p>
<p>首先, 我们需要打开PHP中cgi.fix_pathinfo配置项, 打开这个配置项以后, PHP会去根据CGI规范来检查SCRIPT_FILENAME中那部分是访问脚本和PATH_INFO(<a href="http://cn.php.net/manual/en/ini.core.php" >ini配置解释</a>), 并根据SCRIPT_NAME来修改PATH_INFO(和PATH_TRANSLATED)为正确的值(其实也就是说明, PHP最初对CGI 1.1的支持并不到位)</p>
<p>然后, 就只要添加一个FASTCGI_PARAM项就好了:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
location ~ .php {
	fastcgi_index  index.php;
	fastcgi_pass   127.0.0.1:9000;
	include        fastcgi_params;
	fastcgi_param  PATH_INFO $fastcgi_script_name;
}
</pre>
<p>现在试试吧&#8230;</p>
<p>btw: 当然, 上面的解决方法, 把对路径的分析交给了PHP去处理, 网上也有朋友给出了另外一种配置方法, 这个方法是由Nginx来分析路径(也就不需要fix_pathinfo):</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
location ~ \.php
{
	fastcgi_index index.php;
	fastcgi_pass 127.0.0.1:9000;
	include      fastcgi_params;
	set $path_info &quot;&quot;;
	set $real_script_name $fastcgi_script_name;
	if ($fastcgi_script_name ~ &quot;^(.+?\.php)(/.+)$&quot;) {
	set $real_script_name $1;
	set $path_info $2;
}
fastcgi_param SCRIPT_FILENAME /var/html/$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $path_info;
}
</pre>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_sh.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2307" >2009/11/13</a>, <a href="http://www.zvv.cn"  rel="external nofollow"  class="url" >zwws</a> writes: 按上文修改conf后
访问/p.php/
得到的结果是
/p.php/index.php</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2308" >2009/11/13</a>, <a href="http://phpv.net"  rel="external nofollow"  class="url" >esayr</a> writes: 得到的结果
/p.php/index.php

是正常的.相当于一个文件夹.

文章转载请求.:)</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2309" >2009/11/13</a>, <a href="http://www.zvv.cn"  rel="external nofollow"  class="url" >zwws</a> writes: 纠正下, 我访问/p.php/
PATH_INFO是/index.php
访问/p.php/aa
PATH_INFO是/aa
不明白了</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2310" >2009/11/13</a>, <a href="http://www.zvv.cn"  rel="external nofollow"  class="url" >zwws</a> writes: @esayr
大概理解你的意思了, 可是问题是apache下访问/p.php/返回的是/
难道只能通过程序去"智能"判断么?
能否通过调整nginx的配置来解决呢?</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2311" >2009/11/14</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @zwws 我已补充自己判断的配置, ;)</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2313" >2009/11/15</a>, <a href="http://www.zvv.cn"  rel="external nofollow"  class="url" >zwws</a> writes: 反复折腾了三次到现在, 结果依旧如下:

访问http://localhost/p.php/

PATH_INFO 为 /index.php
PHP_SELF 为 /p.php/index.php


配置文件和http://localhost/p.php/的phpinfo()截图放在这了:

http://www.zvv.cn/nginx_conf.rar</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2314" >2009/11/15</a>, <a href="http://www.zvv.cn"  rel="external nofollow"  class="url" >zwws</a> writes: 有空的话帮忙瞅瞅, thanks. :)</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2315" >2009/11/15</a>, <a href="http://www.zvv.cn"  rel="external nofollow"  class="url" >zwws</a> writes: 解决了.

http://www.zvv.cn/blog/show-110-1.html</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2316" >2009/11/16</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @zwws con~~ ;)</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2321" >2009/11/17</a>, <a href="http://deving.cn"  rel="external nofollow"  class="url" >Torr</a> writes: 好文章，转载到 deving.cn 了，希望可以和更多的人分享</li><li><a href="http://www.laruence.com/2009/11/13/1138.html#comment-2438" >2010/01/20</a>, <a href="http://www.laruence.com/2010/01/20/1247.html"  rel="external nofollow"  class="url" >Nginx/PHP Fastcgi PATH_INFO的一个问题 | 风雪之隅</a> writes: [...] 通过在nginx.conf中模拟PATH_INFO的方法会有一个bug. 那就是PATH_INFO不会被urldecode. [...]</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/11/13/1138.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>提升PHP性能之改变Zend引擎分发方式</title>
		<link>http://www.laruence.com/2009/10/15/1131.html</link>
		<comments>http://www.laruence.com/2009/10/15/1131.html#comments</comments>
		<pubDate>Thu, 15 Oct 2009 08:21:19 +0000</pubDate>
		<dc:creator>雪候鸟</dc:creator>
				<category><![CDATA[PHP应用]]></category>
		<category><![CDATA[PHP源码分析]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php源码分析]]></category>
		<category><![CDATA[ZE]]></category>
		<category><![CDATA[性能]]></category>
		<category><![CDATA[效率]]></category>

		<guid isPermaLink="false">http://www.laruence.com/?p=1131</guid>
		<description><![CDATA[	从PHP5.1开始,PHP提供了用户对Zend VM执行分发方式的选择接口. 

	之前的文章中, 我也提过这方面的内容, Zend虚拟机在执行的时候, 对于编译生成的op_array中的每一条opline的opcode都会分发到相应的处理器(zend_vm_def.h定义)执行, 而按照分发的方式不同, 分发过程可以分为CALL, SWITCH, 和GOTO三种类型.

默认是CALL方式, 也就是所有的opcode处理器都定义为函数, 然后虚拟机调用. 这种方式是传统的方式, 也一般被认为是最稳定的方式.
	
SWITCH方式和GOTO方式则和其命名的意义相同, 分别通过switch和goto来分发.官方给出的描述说GOTO方式最快.

   那么如果使用GOTO方式, 效率上到底能提高多少呢? 今天我就分别使用各种方式来测试一番:]]></description>
			<content:encoded><![CDATA[<div class="copyright" >
<ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;">
<li>作者: laruence(<a href="http://www.laruence.com"  title="风雪之隅"  target="_blank" >http://www.laruence.com</a>)</li>
<li>本文地址: <a href="http://www.laruence.com/2009/10/15/1131.html"  title="Permanet Link to 提升PHP性能之改变Zend引擎分发方式" >http://www.laruence.com/2009/10/15/1131.html</a></li>
<li>转载请注明出处 </li>
</ul></div>
<p>
	从PHP5.1开始,PHP提供了用户对Zend VM执行分发方式的选择接口. </p>
<p>	之前的文章中, 我也提过这方面的内容, Zend虚拟机在执行的时候, 对于编译生成的op_array中的每一条opline的opcode都会分发到相应的处理器(zend_vm_def.h定义)执行, 而按照分发的方式不同, 分发过程可以分为CALL, SWITCH, 和GOTO三种类型.</p>
<p>	默认是CALL方式, 也就是所有的opcode处理器都定义为函数, 然后虚拟机调用. 这种方式是传统的方式, 也一般被认为是最稳定的方式.</p>
<p>	SWITCH方式和GOTO方式则和其命名的意义相同, 分别通过switch和goto来分发.</p>
<p>	官方给出的描述是:</p>
<blockquote><p>
<span><br/>
CALL &#8211; Uses function handlers for opcodes<br/>
SWITCH &#8211; Uses switch() statement for opcode dispatch<br/>
GOTO &#8211; Uses goto for opcode dispatch (threaded opcodes architecture)<br/>
GOTO is usually (depends on CPU and compiler) faster than SWITCH, which<br/>
tends to be slightly faster than CALL.<br/>
CALL is default because it doesn&#8217;t take very long to compile as opposed<br/>
to the other two and in general the speed is quite close to the others.<br/>
</span>
</p></blockquote>
<p>   那么如果使用GOTO方式, 效率上到底能提高多少呢?</p>
<p>   今天我就分别使用各种方式来测试一番, 测试脚本<a href="http://www.laruence.com/2009/10/15/1131.html#bench" >bench.php</a>.</p>
<p>   第一点被证明的就是, 官方说的GOTO方式编译耗时显著高于其他俩种方式, 我一开始在虚拟机上编译, 每次都Hangup(囧), 最后只好换了个强劲点的物理机, 大约3分钟后, 编译成功..</p>
<p>   测试环境:</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
PHP 5.3.0   Linux
AMD Opteron(tm) Processor 270(2G) X 4  6G Memory
</pre>
<p>   编译参数:</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
./configure --with-zend-vm=CALL/GOTO/SWITCH
</pre>
<p>  测试结果如下(都是三次取中值):</p>
<p>CALL方式:</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
laruence@dev01.tc$ sapi/cli/php bench.php
simple             0.358
simplecall         0.418
simpleucall        0.405
simpleudcall       0.424
mandel             1.011
mandel2            1.238
ackermann(7)       0.375
ary(50000)         0.083
ary2(50000)        0.075
ary3(2000)         0.561
fibo(30)           1.156
hash1(50000)       0.114
hash2(500)         0.091
heapsort(20000)    0.270
matrix(20)         0.276
nestedloop(12)     0.599
sieve(30)          0.350
strcat(200000)     0.039
------------------------
Total              7.844
</pre>
<p>SWITCH方式:</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
laruence@dev01.tc$ sapi/cli/php bench.php
simple             0.393
simplecall         0.414
simpleucall        0.424
simpleudcall       0.445
mandel             1.007
mandel2            1.254
ackermann(7)       0.392
ary(50000)         0.084
ary2(50000)        0.073
ary3(2000)         0.593
fibo(30)           1.185
hash1(50000)       0.120
hash2(500)         0.092
heapsort(20000)    0.285
matrix(20)         0.295
nestedloop(12)     0.678
sieve(30)          0.359
strcat(200000)     0.042
------------------------
Total              8.138
</pre>
<p>GOTO方式 :</p>
<pre name="code"  class="sh_shell"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
laruence@dev01.tc$ sapi/cli/php bench.php
simple             0.306
simplecall         0.373
simpleucall        0.369
simpleudcall       0.385
mandel             0.879
mandel2            1.132
ackermann(7)       0.356
ary(50000)         0.081
ary2(50000)        0.073
ary3(2000)         0.525
fibo(30)           1.043
hash1(50000)       0.111
hash2(500)         0.088
heapsort(20000)    0.247
matrix(20)         0.247
nestedloop(12)     0.519
sieve(30)          0.331
strcat(200000)     0.037
------------------------
Total              7.103
</pre>
<p>可见, <b>GOTO方式最快, SWITCH方式最慢.</b>和官方的描述稍有不符.</p>
<p>GOTO方式比其默认的CALL方式, 性能提升还是比较明显的. </p>
<p>所以, 如果你希望让PHP发挥到机制, 改变Zend VM的分发方式, 也可以做为一个考虑因素.
</p>
<p>
附:</p>
<p>使用GOTO方式的configure选项:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
--with-zend-vm=GOTO
</pre>
<p>也可以在Zend目录下使用:</p>
<pre name="code"  class="sh_bash"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
php zend_vm_gen.php --with-vm-kind=[CALL|GOTO|SWITH]
</pre>
<p><a name="bench" > </a>测试脚本bench.php</p>
<pre name="code"  class="sh_php"  linenum="off"   style="background: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:Monacobackground: #333; color: #d9d9d9; border-left: 15px solid #c9c9c9; padding: 9px; font-size: 1em; overflow-x: auto;font-family:MonacoConsolasConsolasCourierCouriermonospace;monospace;">
&lt;?php
/**
 * PHP Perf Bench Test Script
 */
function simple() {
  $a = 0;
  for ($i = 0; $i &lt; 1000000; $i++)
    $a++;

  $thisisanotherlongname = 0;
  for ($thisisalongname = 0; $thisisalongname &lt; 1000000; $thisisalongname++)
    $thisisanotherlongname++;
}

/****/

function simplecall() {
  for ($i = 0; $i &lt; 1000000; $i++)
    strlen(&quot;hallo&quot;);
}

/****/

function hallo($a) {
}

function simpleucall() {
  for ($i = 0; $i &lt; 1000000; $i++)
    hallo(&quot;hallo&quot;);
}

/****/

function simpleudcall() {
  for ($i = 0; $i &lt; 1000000; $i++)
    hallo2(&quot;hallo&quot;);
}

function hallo2($a) {
}

/****/

function mandel() {
  $w1=50;
  $h1=150;
  $recen=-.45;
  $imcen=0.0;
  $r=0.7;
  $s=0;  $rec=0;  $imc=0;  $re=0;  $im=0;  $re2=0;  $im2=0;
  $x=0;  $y=0;  $w2=0;  $h2=0;  $color=0;
  $s=2*$r/$w1;
  $w2=40;
  $h2=12;
  for ($y=0 ; $y&lt;=$w1; $y=$y+1) {
    $imc=$s*($y-$h2)+$imcen;
    for ($x=0 ; $x&lt;=$h1; $x=$x+1) {
      $rec=$s*($x-$w2)+$recen;
      $re=$rec;
      $im=$imc;
      $color=1000;
      $re2=$re*$re;
      $im2=$im*$im;
      while( ((($re2+$im2)&lt;1000000) &amp;&amp; $color&gt;0)) {
        $im=$re*$im*2+$imc;
        $re=$re2-$im2+$rec;
        $re2=$re*$re;
        $im2=$im*$im;
        $color=$color-1;
      }
      if ( $color==0 ) {
        print &quot;_&quot;;
      } else {
        print &quot;#&quot;;
      }
    }
    print &quot;&lt;br&gt;&quot;;
    flush();
  }
}

/****/

function mandel2() {
  $b = &quot; .:,;!/&gt;)|&amp;IH%*#&quot;;
  //float r, i, z, Z, t, c, C;
  for ($y=30; printf(&quot;\n&quot;), $C = $y*0.1 - 1.5, $y--;){
    for ($x=0; $c = $x*0.04 - 2, $z=0, $Z=0, $x++ &lt; 75;){
      for ($r=$c, $i=$C, $k=0; $t = $z*$z - $Z*$Z + $r, $Z = 2*$z*$Z + $i, $z=$t, $k&lt;5000; $k++)
        if ($z*$z + $Z*$Z &gt; 500000) break;
      echo $b[$k%16];
    }
  }
}

/****/

function Ack($m, $n){
  if($m == 0) return $n+1;
  if($n == 0) return Ack($m-1, 1);
  return Ack($m - 1, Ack($m, ($n - 1)));
}

function ackermann($n) {
  $r = Ack(3,$n);
  print &quot;Ack(3,$n): $r\n&quot;;
}

/****/

function ary($n) {
  for ($i=0; $i&lt;$n; $i++) {
    $X[$i] = $i;
  }
  for ($i=$n-1; $i&gt;=0; $i--) {
    $Y[$i] = $X[$i];
  }
  $last = $n-1;
  print &quot;$Y[$last]\n&quot;;
}

/****/

function ary2($n) {
  for ($i=0; $i&lt;$n;) {
    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;

    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;
    $X[$i] = $i; ++$i;
  }
  for ($i=$n-1; $i&gt;=0;) {
    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;

    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;
    $Y[$i] = $X[$i]; --$i;
  }
  $last = $n-1;
  print &quot;$Y[$last]\n&quot;;
}

/****/

function ary3($n) {
  for ($i=0; $i&lt;$n; $i++) {
    $X[$i] = $i + 1;
    $Y[$i] = 0;
  }
  for ($k=0; $k&lt;1000; $k++) {
    for ($i=$n-1; $i&gt;=0; $i--) {
      $Y[$i] += $X[$i];
    }
  }
  $last = $n-1;
  print &quot;$Y[0] $Y[$last]\n&quot;;
}

/****/

function fibo_r($n){
    return(($n &lt; 2) ? 1 : fibo_r($n - 2) + fibo_r($n - 1));
}

function fibo($n) {
  $r = fibo_r($n);
  print &quot;$r\n&quot;;
}

/****/

function hash1($n) {
  for ($i = 1; $i &lt;= $n; $i++) {
    $X[dechex($i)] = $i;
  }
  $c = 0;
  for ($i = $n; $i &gt; 0; $i--) {
    if ($X[dechex($i)]) { $c++; }
  }
  print &quot;$c\n&quot;;
}

/****/

function hash2($n) {
  for ($i = 0; $i &lt; $n; $i++) {
    $hash1[&quot;foo_$i&quot;] = $i;
    $hash2[&quot;foo_$i&quot;] = 0;
  }
  for ($i = $n; $i &gt; 0; $i--) {
    foreach($hash1 as $key =&gt; $value) $hash2[$key] += $value;
  }
  $first = &quot;foo_0&quot;;
  $last  = &quot;foo_&quot;.($n-1);
  print &quot;$hash1[$first] $hash1[$last] $hash2[$first] $hash2[$last]\n&quot;;
}

/****/

function gen_random ($n) {
    global $LAST;
    return( ($n * ($LAST = ($LAST * IA + IC) % IM)) / IM );
}

function heapsort_r($n, &amp;$ra) {
    $l = ($n &gt;&gt; 1) + 1;
    $ir = $n;

    while (1) {
        if ($l &gt; 1) {
            $rra = $ra[--$l];
        } else {
            $rra = $ra[$ir];
            $ra[$ir] = $ra[1];
            if (--$ir == 1) {
                $ra[1] = $rra;
                return;
            }
        }
        $i = $l;
        $j = $l &lt;&lt; 1;
        while ($j &lt;= $ir) {
            if (($j &lt; $ir) &amp;&amp; ($ra[$j] &lt; $ra[$j+1])) {
                $j++;
            }
            if ($rra &lt; $ra[$j]) {
                $ra[$i] = $ra[$j];
                $j += ($i = $j);
            } else {
                $j = $ir + 1;
            }
        }
        $ra[$i] = $rra;
    }
}

function heapsort($N) {
  global $LAST;

  define(&quot;IM&quot;, 139968);
  define(&quot;IA&quot;, 3877);
  define(&quot;IC&quot;, 29573);

  $LAST = 42;
  for ($i=1; $i&lt;=$N; $i++) {
    $ary[$i] = gen_random(1);
  }
  heapsort_r($N, $ary);
  printf(&quot;%.10f\n&quot;, $ary[$N]);
}

/****/

function mkmatrix ($rows, $cols) {
    $count = 1;
    $mx = array();
    for ($i=0; $i&lt;$rows; $i++) {
        for ($j=0; $j&lt;$cols; $j++) {
            $mx[$i][$j] = $count++;
        }
    }
    return($mx);
}

function mmult ($rows, $cols, $m1, $m2) {
    $m3 = array();
    for ($i=0; $i&lt;$rows; $i++) {
        for ($j=0; $j&lt;$cols; $j++) {
            $x = 0;
            for ($k=0; $k&lt;$cols; $k++) {
                $x += $m1[$i][$k] * $m2[$k][$j];
            }
            $m3[$i][$j] = $x;
        }
    }
    return($m3);
}

function matrix($n) {
  $SIZE = 30;
  $m1 = mkmatrix($SIZE, $SIZE);
  $m2 = mkmatrix($SIZE, $SIZE);
  while ($n--) {
    $mm = mmult($SIZE, $SIZE, $m1, $m2);
  }
  print &quot;{$mm[0][0]} {$mm[2][3]} {$mm[3][2]} {$mm[4][4]}\n&quot;;
}

/****/

function nestedloop($n) {
  $x = 0;
  for ($a=0; $a&lt;$n; $a++)
    for ($b=0; $b&lt;$n; $b++)
      for ($c=0; $c&lt;$n; $c++)
        for ($d=0; $d&lt;$n; $d++)
          for ($e=0; $e&lt;$n; $e++)
            for ($f=0; $f&lt;$n; $f++)
             $x++;
  print &quot;$x\n&quot;;
}

/****/

function sieve($n) {
  $count = 0;
  while ($n-- &gt; 0) {
    $count = 0;
    $flags = range (0,8192);
    for ($i=2; $i&lt;8193; $i++) {
      if ($flags[$i] &gt; 0) {
        for ($k=$i+$i; $k &lt;= 8192; $k+=$i) {
          $flags[$k] = 0;
        }
        $count++;
      }
    }
  }
  print &quot;Count: $count\n&quot;;
}

/****/

function strcat($n) {
  $str = &quot;&quot;;
  while ($n-- &gt; 0) {
    $str .= &quot;hello\n&quot;;
  }
  $len = strlen($str);
  print &quot;$len\n&quot;;
}

/*****/

function getmicrotime()
{
  $t = gettimeofday();
  return ($t['sec'] + $t['usec'] / 1000000);
}

function start_test()
{
        ob_start();
  return getmicrotime();
}

function end_test($start, $name)
{
  global $total;
  $end = getmicrotime();
  ob_end_clean();
  $total += $end-$start;
  $num = number_format($end-$start,3);
  $pad = str_repeat(&quot; &quot;, 24-strlen($name)-strlen($num));

  echo $name.$pad.$num.&quot;\n&quot;;
        ob_start();
  return getmicrotime();
}

function total()
{
  global $total;
  $pad = str_repeat(&quot;-&quot;, 24);
  echo $pad.&quot;\n&quot;;
  $num = number_format($total,3);
  $pad = str_repeat(&quot; &quot;, 24-strlen(&quot;Total&quot;)-strlen($num));
  echo &quot;Total&quot;.$pad.$num.&quot;\n&quot;;
}

$t0 = $t = start_test();
simple();
$t = end_test($t, &quot;simple&quot;);
simplecall();
$t = end_test($t, &quot;simplecall&quot;);
simpleucall();
$t = end_test($t, &quot;simpleucall&quot;);
simpleudcall();
$t = end_test($t, &quot;simpleudcall&quot;);
mandel();
$t = end_test($t, &quot;mandel&quot;);
mandel2();
$t = end_test($t, &quot;mandel2&quot;);
ackermann(7);
$t = end_test($t, &quot;ackermann(7)&quot;);
ary(50000);
$t = end_test($t, &quot;ary(50000)&quot;);
ary2(50000);
$t = end_test($t, &quot;ary2(50000)&quot;);
ary3(2000);
$t = end_test($t, &quot;ary3(2000)&quot;);
fibo(30);
$t = end_test($t, &quot;fibo(30)&quot;);
hash1(50000);
$t = end_test($t, &quot;hash1(50000)&quot;);
hash2(500);
$t = end_test($t, &quot;hash2(500)&quot;);
heapsort(20000);
$t = end_test($t, &quot;heapsort(20000)&quot;);
matrix(20);
$t = end_test($t, &quot;matrix(20)&quot;);
nestedloop(12);
$t = end_test($t, &quot;nestedloop(12)&quot;);
sieve(30);
$t = end_test($t, &quot;sieve(30)&quot;);
strcat(200000);
$t = end_test($t, &quot;strcat(200000)&quot;);
total($t0, &quot;Total&quot;);
?&gt;
</pre>
</p>
<p><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_shell.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_bash.js" ></script><script type="text/javascript"  src="http://www.laruence.com/wp-content/plugins/shjs-syntax-hiliter/shjs/lang/sh_php.js" ></script></p>
<hr/><h2>Comments</h2><ul  style="padding-left:1em;font-size:85%;padding-left:1em;font-size:85%;"><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2266" >2009/10/15</a>, <a href="http://www.codytan.com"  rel="external nofollow"  class="url" >cody</a> writes: 好文，不过有些疑问
1.“对于每个Opcode都会分发执行”，这里的“个"指的是？是一条opcode语句还是一个php文件中所有的opcode语句？
2.有个问题，php的错误检查阶段是哪个？不是语法检查。如include一个不存在的问题，php会报错，这个报错是在opcode-&gt;compile-&gt;执行中的哪个环节报错的？是compile环节还是执行环节呢？
3.其实问题二是基于对php运行机制还不太清楚，我测试过一个文件 include 20个php文件和直接写成一个php文件性能上的差异很大（20文件并不执行），想知道是在哪个环境造成了这种差异。

如果能回答我，感激不尽！ :)</li><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2267" >2009/10/15</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @cody 应该是对于每条opline中的opcode. 都会通过分发对应到相应的处理器执行(zend_vm_def.h定义).
include也是一条opcode,ZEND_INCLUDE_OR_EVAL, 相应的出错检查也就是在它的处理器中.</li><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2268" >2009/10/15</a>, <a href="http://www.codytan.com"  rel="external nofollow"  class="url" >cody</a> writes: 补充一下，”opcode-&gt;compile-&gt;执行“ 我这里的compile指的其实是由opcode到c 这个过程。</li><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2269" >2009/10/15</a>, cody writes: thanks</li><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2272" >2009/10/17</a>, fybird writes: 请问你是用那个ide编程，平常。</li><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2273" >2009/10/17</a>, <a href="http://www.laruence.com"  rel="external nofollow"  class="url" >雪候鸟</a> writes: @fybird vim</li><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2285" >2009/10/24</a>, <a href="http://www.05sky.cn"  rel="external nofollow"  class="url" >CrossYou</a> writes: 我也使用了你同样的主题，呵呵

你的文章写的很深，我才刚刚接触php，学习中，楼主加油。</li><li><a href="http://www.laruence.com/2009/10/15/1131.html#comment-2290" >2009/10/26</a>, zhangyufeng writes: http://twiki.laruence.com/ 打不开啦……</li></ul><hr/><small  style="font-size:85%;font-size:85%;">Copyright &copy; 2010 <a href="http://www.laruence.com"  target="_blank" >风雪之隅</a> 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)</small>]]></content:encoded>
			<wfw:commentRss>http://www.laruence.com/2009/10/15/1131.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
