﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-庄周梦蝶-随笔分类-linux &amp; C</title><link>http://www.blogjava.net/killme2008/category/23659.html</link><description>天行健，君子以自强不息</description><language>zh-cn</language><lastBuildDate>Mon, 19 Apr 2010 01:12:12 GMT</lastBuildDate><pubDate>Mon, 19 Apr 2010 01:12:12 GMT</pubDate><ttl>60</ttl><item><title>Google protocol buffers的Emacs扩展</title><link>http://www.blogjava.net/killme2008/archive/2010/01/20/310206.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 20 Jan 2010 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2010/01/20/310206.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/310206.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2010/01/20/310206.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/310206.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/310206.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 通讯层的改造使用了<a href="http://code.google.com/p/protobuf/">google protocol buffers</a>作为协议体，效率还是挺让人满意。编辑以.proto结尾的语法文件，没有语法高亮很不习惯，幸好protocolbuf提供了vim和emacs的扩展。下载非win32版本的protocol buffers的压缩包里，解压后有个editors目录，里面就是两个扩展文件：proto.vim是提供给vim爱好者的，而<a href="http://protobuf.googlecode.com/svn/trunk/editors/protobuf-mode.el">protobuf-mode.el</a>就是提供给emacs控的。<br />
&nbsp;&nbsp;&nbsp; 安装很简单，将protobuf-mode.el加入你的Emacs加载路径，然后在.emacs配置文件里加上这么两行代码：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">protobuf-mode)</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(setq&nbsp;auto</span><span style="color: #000000;">-</span><span style="color: #000000;">mode</span><span style="color: #000000;">-</span><span style="color: #000000;">alist&nbsp;&nbsp;(cons&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">(".proto$"&nbsp;.&nbsp;protobuf-mode)&nbsp;auto-mode-alist))</span></div>
&nbsp;&nbsp;&nbsp; require是不够的，第二行将自动把.proto结尾的打开文件以protobuf-mode模式运行。运行时截图：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://www.blogjava.net/images/blogjava_net/killme2008/protocol-buf-mode.png" width="480" height="509" /><br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 工具栏上多了个ProtocolBuffers菜单，有一些简单功能，如注释某段代码，代码跳转等等。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/310206.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2010-01-20 11:47 <a href="http://www.blogjava.net/killme2008/archive/2010/01/20/310206.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>指针与数组</title><link>http://www.blogjava.net/killme2008/archive/2009/02/17/254503.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 16 Feb 2009 16:05:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/02/17/254503.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/254503.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/02/17/254503.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/254503.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/254503.html</trackback:ping><description><![CDATA[一、什么时候数组和指针是相同的<br />
1、表达式中的数组名（与声明不同）被编译器当作一个指向该数组第一个元素的指针<br />
因此如a[i]这样的访问都被编译器改写或解释为*(a+i)的形式，同样取下标操作符的操作数是可交换的，所以a[3]可以写成3[a]，不过通常你不会这样做。<br />
<br />
2、下标总是与指针的偏移量相同，下标*sizeof(元素类型)就是偏移数组起始地址的实际字节数。<br />
<br />
3、&#8220;作为函数参数的数组名&#8221;等同于指针，任何传递给函数的数组参数都会被转换成指针，这是基于效率考虑，避免了数组的拷贝。在函数内部，数组参数都将被转换成一个指针，要牢记这一点，因此如：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;test(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;a[</span><span style="color: #000000;">10</span><span style="color: #000000;">])<br />
{<br />
&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">%d\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #0000ff;">sizeof</span><span style="color: #000000;">(a));<br />
}</span></div>
<br />
显然应该打印指针大小4，而非数组大小。另外，注意数组参数的地址跟数组参数第一个元素的地址并不相等，在表达式中两者一致，但是在函数调用中，由于数组参数指针也是临时变量，因此两者的地址是不一样的。<br />
可以通过下列程序观察：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
#include&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdlib.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;test1(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;a[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">&amp;a=%x,&amp;(a[0])=%x,&amp;(a[1])=%x\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">a,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">(a[</span><span style="color: #000000;">0</span><span style="color: #000000;">]),</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">(a[</span><span style="color: #000000;">1</span><span style="color: #000000;">]));<br />
}<br />
</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;test2(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">b)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">&amp;b=%x,&amp;(b[0])=%x,&amp;(b[1])=%x\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">b,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">(b[</span><span style="color: #000000;">0</span><span style="color: #000000;">]),</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">(b[</span><span style="color: #000000;">1</span><span style="color: #000000;">]));&nbsp;<br />
}<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;argc,&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">argv[])<br />
{<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;ga[]</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">hello</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">&amp;ga=%x,&amp;(ga[0])=%x,&amp;(ga[1])=%x\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">ga,</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">(ga[</span><span style="color: #000000;">0</span><span style="color: #000000;">]),</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">(ga[</span><span style="color: #000000;">1</span><span style="color: #000000;">]));&nbsp;<br />
&nbsp;&nbsp;test1(ga);<br />
&nbsp;&nbsp;test2(ga);<br />
&nbsp;&nbsp;system(</span><span style="color: #000000;">"</span><span style="color: #000000;">pause</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
}<br />
</span></div>
<br />
<br />
二、指针跟数组什么时候不同<br />
1、如果定义了一个数组，在其他文件对它进行声明也必须声明为数组，定义和声明必须匹配，指针也是如此。<br />
2、指针始终是指针，它绝不可以写成数组。可以用下标形式访问指针的时候，一般都是指针作为函数参数时，并且你知道传递给函数的实际是一个数组。<br />
3、数组名是不可改变的左值，因此如<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;array[</span><span style="color: #000000;">100</span><span style="color: #000000;">],array2[</span><span style="color: #000000;">100</span><span style="color: #000000;">];<br />
array</span><span style="color: #000000;">=</span><span style="color: #000000;">array2;<br />
array++;<br />
array--;<br />
</span></div>
&nbsp; <br />
都将出错，但是在函数内部：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;array2[</span><span style="color: #000000;">100</span><span style="color: #000000;">];<br />
</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;fun(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;array[])<br />
{<br />
&nbsp;&nbsp;array</span><span style="color: #000000;">=</span><span style="color: #000000;">array2;<br />
}</span></div>
<br />
却可以，因为在函数内部array虽然被声明为数组实际上却是指针。<br />
<br />
<br />
<br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/254503.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-02-17 00:05 <a href="http://www.blogjava.net/killme2008/archive/2009/02/17/254503.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再谈Selector的wakeup方法</title><link>http://www.blogjava.net/killme2008/archive/2009/02/01/252835.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 01 Feb 2009 03:15:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2009/02/01/252835.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/252835.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2009/02/01/252835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/252835.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/252835.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 过去推荐过两篇blog《Java NIO类库Selector机制解析》（<a href="http://blog.csdn.net/haoel/archive/2008/03/27/2224055.aspx">上</a>，<a href="http://blog.csdn.net/haoel/archive/2008/03/27/2224069.aspx">下</a>），感叹java为了跨平台似乎&#8220;很傻很天真&#8221;。最近学习使用ACE，才知道这个解决办法倒不是java开创的，ACE也是这样搞的。java nio中Selector的wakeup方法，类似于ACE_Select_Reactor的notify机制，可以从非select调用的线程去唤醒阻塞在select调用上的select线程，当然ACE_Select_Reactor的notify强大多了，可以实现event handler的无限扩容。ACE_Select_Reactor的notify的实现是通过ACE_Pipe，在ACE_Pipe中可以清晰地看到针对win32平台是采用了TCP连接：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">#if</span><span style="color: #000000;">&nbsp;defined&nbsp;(ACE_LACKS_SOCKETPAIR)&nbsp;||&nbsp;defined&nbsp;(__Lynx__)</span><span style="color: #000000;"><br />
&nbsp;&nbsp;ACE_INET_Addr&nbsp;my_addr;<br />
&nbsp;&nbsp;ACE_SOCK_Acceptor&nbsp;acceptor;<br />
&nbsp;&nbsp;ACE_SOCK_Connector&nbsp;connector;<br />
&nbsp;&nbsp;ACE_SOCK_Stream&nbsp;reader;<br />
&nbsp;&nbsp;ACE_SOCK_Stream&nbsp;writer;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
#&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;defined&nbsp;(ACE_WIN32)<br />
&nbsp;&nbsp;ACE_INET_Addr&nbsp;local_any&nbsp;&nbsp;(static_cast</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">u_short</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">0</span><span style="color: #000000;">),&nbsp;ACE_LOCALHOST);<br />
#&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;ACE_Addr&nbsp;local_any&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;ACE_Addr::sap_any;<br />
#&nbsp;endif&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;ACE_WIN32&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Bind&nbsp;listener&nbsp;to&nbsp;any&nbsp;port&nbsp;and&nbsp;then&nbsp;find&nbsp;out&nbsp;what&nbsp;the&nbsp;port&nbsp;was.</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(acceptor.open&nbsp;(local_any)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">||</span><span style="color: #000000;">&nbsp;acceptor.get_local_addr&nbsp;(my_addr)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_INET_Addr&nbsp;sv_addr&nbsp;(my_addr.get_port_number&nbsp;(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACE_LOCALHOST);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Establish&nbsp;a&nbsp;connection&nbsp;within&nbsp;the&nbsp;same&nbsp;process.</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(connector.connect&nbsp;(writer,&nbsp;sv_addr)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(acceptor.accept&nbsp;(reader)&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writer.close&nbsp;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Close&nbsp;down&nbsp;the&nbsp;acceptor&nbsp;endpoint&nbsp;since&nbsp;we&nbsp;don't&nbsp;need&nbsp;it&nbsp;anymore.</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;acceptor.close&nbsp;();</span></div>
<br />
&nbsp;&nbsp;&nbsp; 在类unix平台是采用STREAMS管道，在一些遗留的unix平台上是socketpair()。为什么在win32上采用TCP连接的方式呢？原因不是什么性能、资源问题，也不是因为windows管道消耗的资源比tcp多，而是由于winsock的select函数（java nio的select在win32下是使用select实现的）是无法监测管道事件的，也就是说无法将windows管道加入到fd_set中,为了做到可移植，才在win32上采用了TCP连接的方式来实现。这一点在blog上篇的新回复中已经有人提到。<br /><img src ="http://www.blogjava.net/killme2008/aggbug/252835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2009-02-01 11:15 <a href="http://www.blogjava.net/killme2008/archive/2009/02/01/252835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>安装配置Emacs-rails</title><link>http://www.blogjava.net/killme2008/archive/2008/11/23/242067.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 22 Nov 2008 18:22:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/23/242067.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/242067.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/23/242067.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/242067.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/242067.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 首先你的机器上肯定要安装emacs啦，此步略过不表。<br />
&nbsp;1、从 http://rubyforge.org/projects/emacs-rails 下载最新emacs-rails，解压文件到~/.emacs.d/rails 目录<br />
&nbsp;2、根据README，你需要下载三个依赖库：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">cd&nbsp;</span><span style="color: #000000;">~/</span><span style="color: #000000;">.emacs.d</span><span style="color: #000000;">/</span><span style="color: #000000;">rails<br />
wget&nbsp;http:</span><span style="color: #000000;">//</span><span style="color: #000000;">www.kazmier.com</span><span style="color: #000000;">/</span><span style="color: #000000;">computer</span><span style="color: #000000;">/</span><span style="color: #000000;">snippet.el<br />
wget&nbsp;http:</span><span style="color: #000000;">//</span><span style="color: #000000;">www.webweavertech.com</span><span style="color: #000000;">/</span><span style="color: #000000;">ovidiu</span><span style="color: #000000;">/</span><span style="color: #000000;">emacs</span><span style="color: #000000;">/</span><span style="color: #000000;">find</span><span style="color: #000000;">-</span><span style="color: #000000;">recursive.txt<br />
mv&nbsp;find</span><span style="color: #000000;">-</span><span style="color: #000000;">recursive.txt&nbsp;find</span><span style="color: #000000;">-</span><span style="color: #000000;">recursive.el<br />
<br />
wget&nbsp;http:</span><span style="color: #000000;">//</span><span style="color: #000000;">svn.ruby</span><span style="color: #000000;">-</span><span style="color: #000000;">lang.org</span><span style="color: #000000;">/</span><span style="color: #000000;">cgi</span><span style="color: #000000;">-</span><span style="color: #000000;">bin</span><span style="color: #000000;">/</span><span style="color: #000000;">viewvc.cgi</span><span style="color: #000000;">/</span><span style="color: #000000;">trunk</span><span style="color: #000000;">/</span><span style="color: #000000;">misc</span><span style="color: #000000;">/</span><span style="color: #000000;">inf</span><span style="color: #000000;">-</span><span style="color: #000000;"><a title="" href="http://www.ruby-lang.org" >ruby</a>.el?view</span><span style="color: #000000;">=</span><span style="color: #000000;">co<br />
mv&nbsp;inf</span><span style="color: #000000;">-</span><span style="color: #000000;"><a title="" href="http://www.ruby-lang.org" >ruby</a>.el\?view</span><span style="color: #000000;">=</span><span style="color: #000000;">co&nbsp;inf</span><span style="color: #000000;">-</span><span style="color: #000000;"><a title="" href="http://www.ruby-lang.org" >ruby</a>.el</span></div>
<br />
3、将ruby源代码目录下的/misc子目录中的emacs扩展文件拷贝到/usr/share/emacs/site-lisp/目录下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">sudo&nbsp;cp&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">home</span><span style="color: #000000;">/</span><span style="color: #000000;">dennis</span><span style="color: #000000;">/</span><span style="color: #000000;">backup</span><span style="color: #000000;">/</span><span style="color: #000000;"><a title="" href="http://www.ruby-lang.org" >ruby</a></span><span style="color: #000000;">-</span><span style="color: #000000;">1.8</span><span style="color: #000000;">.</span><span style="color: #000000;">7</span><span style="color: #000000;">-</span><span style="color: #000000;">p72</span><span style="color: #000000;">/</span><span style="color: #000000;">misc</span><span style="color: #000000;">/*</span><span style="color: #000000;">.el&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">usr</span><span style="color: #000000;">/</span><span style="color: #000000;">share</span><span style="color: #000000;">/</span><span style="color: #000000;">emacs</span><span style="color: #000000;">/</span><span style="color: #000000;">site</span><span style="color: #000000;">-</span><span style="color: #000000;">lisp</span><span style="color: #000000;">/</span><span style="color: #000000;"><br />
</span></div>
<br />
4、在~/.emacs添加两行代码，加载emacs-rails<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(setq&nbsp;load</span><span style="color: #000000;">-</span><span style="color: #000000;">path&nbsp;(cons&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">~/.emacs.d/rails</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;load</span><span style="color: #000000;">-</span><span style="color: #000000;">path))<br />
(require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">rails)</span></div>
<br />
&nbsp;&nbsp;&nbsp; 搞定，看起来挺强悍的，在菜单兰多了个ROR菜单，需要熟悉下快捷键。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/242067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-23 02:22 <a href="http://www.blogjava.net/killme2008/archive/2008/11/23/242067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ubuntu下解决Ruby安装后缺少openssl的问题</title><link>http://www.blogjava.net/killme2008/archive/2008/11/23/242066.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 22 Nov 2008 17:34:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/11/23/242066.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/242066.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/11/23/242066.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/242066.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/242066.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 一开始尝试使用<br />
&nbsp;&nbsp;&nbsp; sudo apt-get install libopenssl-ruby1.8<br />
&nbsp;&nbsp;&nbsp; 安装是安装成功了，但是仍然提示找不到openssl。还是决定从源码安装，首先确保ubuntu安装了openssl：<br />
&nbsp;&nbsp;&nbsp; sudo apt-get install openssl<br />
&nbsp;&nbsp;&nbsp; sudo apt-get install libssl-dev<br />
&nbsp;&nbsp;&nbsp; sudo apt-get install libssl0.9.8<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 然后进入ruby源码目录下的/ext/openssl<br />
&nbsp;&nbsp;&nbsp; cd RUBY_SOURCE/ext/openssl<br />
&nbsp;&nbsp;&nbsp; <a title="" href="http://www.ruby-lang.org" >ruby</a> extconf.rb<br />
&nbsp;&nbsp;&nbsp; make <br />
&nbsp;&nbsp;&nbsp; sudo make install<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/242066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-11-23 01:34 <a href="http://www.blogjava.net/killme2008/archive/2008/11/23/242066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>memcached1.2新增启动参数初探</title><link>http://www.blogjava.net/killme2008/archive/2008/08/07/220774.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 07 Aug 2008 14:16:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/08/07/220774.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/220774.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/08/07/220774.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/220774.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/220774.html</trackback:ping><description><![CDATA[<br />
&nbsp;&nbsp;&nbsp; memcached 1.2新增加了几个参数，试着做下总结，有错误请指正：<br />
-U &lt;num&gt; 监听UDP端口，默认是11211端口<br />
<br />
-f &lt;factor&gt; 这个参数很重要，用于设置chunk大小的递增因子。memcached的存储模型类似一个二维数组：slab-&gt;chunk-&gt;item，每个slab大小是1M，slab中的chunk的大小等于chunk的初始大小乘以f^sid（f的sid次方），其中sid是当前slab的id，chunk的默认大小在1.1是1字节，在1.2是80字节。f就是chunk的递增倍数，在1.1固定为2，在1.2可通过-f参数设置，默认为1.25。memcachd存储的item大小一般会比存储的chunk size小，那么就有部分空间被浪费，为了尽量节省内存，正确设置-f参数就显的非常重要，通过计算尽量让chunk的大小接近或者略大于存储的item的大小。<br />
<br />
-M 这个参数在1.1中就有了。这个参数用于在内存溢出的时候，禁止自动移除缓存数据（LRU），替代的是返回一个error。<br />
<br />
-s &lt;size&gt; 设置分配给item的key、value和flag的最小字节数，默认是48字节。根据你存储的item大小适当调整这个值，可以更有效地利用内存。<br />
<br />
-t &lt;num&gt; 设置处理请求的线程数。这个参数仅在编译memcached启用线程时有效。这个参数通常设置的大小等于CPU个数。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/220774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-08-07 22:16 <a href="http://www.blogjava.net/killme2008/archive/2008/08/07/220774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>lua 5.0的实现（翻译)4,5</title><link>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 07 Apr 2008 09:55:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/191324.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/191324.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/191324.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">4</span><span style="font-size: 9pt; font-family: 宋体;">、</span><span style="font-size: 9pt; font-family: CMR9;"> </span><span style="font-size: 9pt; font-family: 宋体;">表</span></strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>Table</span><span style="font-size: 9pt; font-family: 宋体;">是</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">的主要——实际上，也是唯一的——数据结构。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Table</span><span style="font-size: 9pt; font-family: 宋体;">不仅在语言中，同时也在语言的实现中扮演着重要角色。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Effort spent on a good implementation of tables is
rewarded in the language,because tables are used
for several internal tasks, with no qualms about performance</span><span style="font-size: 10pt; font-family: 宋体;">。这有助于保持实现的小巧。相反的，</span><span style="font-family: 宋体;">任何其他数据结构的机制的缺乏也为</span><span lang="EN-US">table</span><span style="font-family: 宋体;">的高效实现带来了很大压力</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Lua</span><span style="font-family: 宋体;">中的</span><span lang="EN-US">table</span><span style="font-family: 宋体;">是关联数组，也就是可以用任何值做索引（除了</span><span lang="EN-US">nil</span><span style="font-family: 宋体;">），也可以持有任何值。另外，</span><span lang="EN-US">table</span><span style="font-family: 宋体;">是动态的，也就是说当加进数据的时候它们将增长（给迄今不存在的域赋值）而移除数据的时候将萎缩（给域赋</span><span lang="EN-US">nil</span><span style="font-family: 宋体;">值）。</span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 21.75pt;" align="left"><span style="font-family: 宋体;">不像大多数其他脚本语言，</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">没有数组类型。数组被表示为以整数做键的</span><span lang="EN-US">table</span><span style="font-family: 宋体;">。用</span><span lang="EN-US">table</span><span style="font-family: 宋体;">作为数组对于语言是有益的。主要的（益处）显而易见：</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">并不需要操纵表和数组的两套不同的运算符。另外，程序员不用对两种实现做出艰难选择。在</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">中实现稀疏数组是轻而易举的。例如，在</span><span lang="EN-US">Perl</span><span style="font-family: 宋体;">里面，如果你尝试去跑</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">$a[1000000000]=1 </span><span style="font-size: 10pt; font-family: 宋体;">这样的程序，你能跑出个内存溢出！（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">you can run out of memory</span><span style="font-size: 10pt; font-family: 宋体;">），因为它触发了一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">10</span><span style="font-size: 10pt; font-family: 宋体;">亿个元素的数组的创建（译注，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Perl</span><span style="font-size: 10pt; font-family: 宋体;">的哲学是：去除不必要的限制）。而等价的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序</span><span style="font-size: 10pt; font-family: CMR10;"> </span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">a={[1000000000]=1}</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: 宋体;">（只是）创建了有一个单独的项的表（而已）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua01.jpg" alt="" border="0" /><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter" />
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0" />
<v:f eqn="sum @0 1 0" />
<v:f eqn="sum 0 0 @1" />
<v:f eqn="prod @2 1 2" />
<v:f eqn="prod @3 21600 pixelWidth" />
<v:f eqn="prod @3 21600 pixelHeight" />
<v:f eqn="sum @0 0 1" />
<v:f eqn="prod @6 1 2" />
<v:f eqn="prod @7 21600 pixelWidth" />
<v:f eqn="sum @8 21600 0" />
<v:f eqn="prod @7 21600 pixelHeight" />
<v:f eqn="sum @10 21600 0" />
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />
<o:lock v:ext="edit" aspectratio="t" />
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:414.75pt;
height:198pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image001.gif" o:title="2007-12-04_152712" />
</v:shape><![endif]--><!--[if !vml]--><br />
<!--[endif]--><o:p></o:p></span>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: 宋体;">直到</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 4.0</span><span style="font-size: 9pt; font-family: 宋体;">，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">都是作为</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">hash</span><span style="font-size: 9pt; font-family: 宋体;">表严格地实现：所有的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">pair</span><span style="font-size: 9pt; font-family: 宋体;">都被显式地保存。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua5.0</span><span style="font-size: 9pt; font-family: 宋体;">引入了一个新算法来优化作为数组的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">：它将以整数为键的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">pair</span><span style="font-size: 9pt; font-family: 宋体;">不再是存储键而是优化成存储值在真正的数组中。更精确地说，在</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">中，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">被实现为一个混合数据结构：它们包括一个</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">hash</span><span style="font-size: 9pt; font-family: 宋体;">部分和一个数组部分。图</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体;">展示了一个有</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">"x"</span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">9.3, 1 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100,2 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">200, 3 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">300</span><span style="font-size: 10pt; font-family: 宋体;">对子的表的一种可能结构。注意到数组部分在右边，并没有存储整数的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">key</span><span style="font-size: 10pt; font-family: 宋体;">。这个划分仅仅是在一个低的实现层次进行的，访问</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">仍然是透明的，甚至在虚拟机内部（访问</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">）也是如此。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Table</span><span style="font-size: 10pt; font-family: 宋体;">根据内容自动并且动态地对两个部分进行适配：数组部分试图从</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的相应地存储值，关联非整数键或者整数键超过数组范围的值被存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">需要增长时，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">重新计算</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分和数组部分的大小。任一部分都可能是空的。重新计算后的数组大小是至少是当前使用的数组部分从</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的一半情况下的最大</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">值（原文：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">The computed
size of the array part is the largest </span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">such that at least half the slots between 1 and </span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">are in use</span><span style="font-size: 10pt; font-family: 宋体;">）（稀疏数组时避免浪费空间），并至少有一个（元素）处在</span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n/</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2+1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的槽中（当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">被</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2</span><span style="font-size: 10pt; font-family: 宋体;">整除时，避免</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的这样的数组大小）。计算完大小后，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">创建了&#8220;新&#8221;的部分并将&#8220;旧&#8221;的部分的元素重新插入到的&#8220;新&#8221;的部分。作为一个例子，假设</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">a</span><span style="font-size: 10pt; font-family: 宋体;">是一个空表；它的数组部分和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分的大小都是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">0</span><span style="font-size: 10pt; font-family: 宋体;">。当我们执行</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">a[1]=v</span><span style="font-size: 10pt; font-family: 宋体;">时，这个表需要增长到足够容纳新的键。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">将为新的数组部分的大小选择</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n=1</span><span style="font-size: 10pt; font-family: 宋体;">（带有一个项</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分仍然保持为空。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">这个混合的方案有两个优点。首先，访问以整数为键的值加快了，因为不再需要任何的散列行为。其次，也是最重要的，数组部分占用的内存大概是将数组部分存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分时的一半，因为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">key</span><span style="font-size: 10pt; font-family: 宋体;">在数组中是隐式的（译注：也就是数组的下标）而在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分却是显式的。因而，当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用作数组的时，它表现的就像一个数组，只要整数键是密集。另外，不用为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分付出任何内存和时间上的惩罚，因为它（译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分）甚至都不存在。相反的控制：如果</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用作关联数组而非一个数组，数组部分可能就是空的。这些内存上的节省是比较重要的，因为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序经常创建一些小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用来实现对象（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Object</span><span style="font-size: 10pt; font-family: 宋体;">）（译注，也就是用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">来模仿对象，有点类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">javascript</span><span style="font-size: 10pt; font-family: 宋体;">中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">json</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Hash</span><span style="font-size: 10pt; font-family: 宋体;">部分采用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Brent's
variation[3]</span><span style="font-size: 10pt; font-family: 宋体;">的组合的链状发散表。这些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的主要不变式是如果一个元素没有在它的主要位置上（也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值的原始位置），则冲突的元素在它自己的主要位置上。换句话说，仅当两个元素有相同的主要位置（也就是在当时</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">大小情况下的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值）时才有冲突的。没有二级冲突。正因为那样，这些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的加载因子可以是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100%</span><span style="font-size: 10pt; font-family: 宋体;">而没有性能上的损失。这部分不是很明白，附上原文：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 20pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">The hash part uses a mix of chained scatter table with
Brent's variation [3].<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">A main invariant of
these tables is that if an element is not in its main position<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(i.e., the original
position given by its hash value), then the colliding element<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">is in its own main
position. In other words, there are collisions only when two<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">elements have the same
main position (i.e., the same hash values for that table<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">size). There are no
secondary collisions. Because of that, the load factor of these<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">tables can be 100% without performance penalties.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">5</span></strong><strong><span style="font-size: 10pt; font-family: 宋体;">、函数和闭包</span></strong><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">编译一个函数的时候，它产生一个模型（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">prototype</span><span style="font-size: 10pt; font-family: 宋体;">），包括了函数的虚拟机指令、常量值（数字，字符串字面量等）和一些调试信息。运行的时候，无论何时</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">执行一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">function&#8230;end</span><span style="font-size: 10pt; font-family: 宋体;">表达式，它都创建一个新的闭包。每个闭包都有一个引用指向相应的模型，一个引用指向环境（</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">environment</span><span style="font-size: 10pt; font-family: 宋体;">）（一张查找全局变量的表，译注：指所谓环境就是这样一张表），和一组用来访问外部</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的指向</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">的引用。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US"><o:p></o:p></span></p>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;">
<p class="MsoNormal" style="border: medium none ; padding: 0cm; text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">词法范围以及</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class</span><span style="font-size: 10pt; font-family: 宋体;">函数的组合导致一个关于（如何）访问外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的著名难题。考虑图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3</span><span style="font-size: 10pt; font-family: 宋体;">中的例子。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">被调用的时候，它的函数体（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">body</span><span style="font-size: 10pt; font-family: 宋体;">）部分引用了外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x (</span><span style="font-size: 10pt; font-family: 宋体;">函数参数在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">里是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量，译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">就是所谓的自由变量，这里形成了闭包</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">)</span><span style="font-size: 10pt; font-family: 宋体;">。尽管如此，当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">被调用时，生成</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">的函数</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">已经返回。如果在栈中生成变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">，（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">在栈的）其栈槽将不复存在。（译注，此处的意思应该是说如果在栈保存变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">，那么在调用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">的时候，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">函数早已经返回，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">也在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">调用前就不在栈里头了，这就是那个著名难题）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><!--[if gte vml 1]><v:shape id="_x0000_i1026" type="#_x0000_t75" style='width:415.5pt;height:141pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image002.gif" o:title="2" />
</v:shape><![endif]--><!--[if !vml]--><img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua02.jpg" alt="" border="0" /><br />
<!--[endif]--><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><span style="font-size: 9pt; font-family: 宋体;">大多数过程语言通过限制词法范围（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">python</span><span style="font-size: 9pt; font-family: 宋体;">），不提供</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">first-class</span><span style="font-size: 9pt; font-family: 宋体;">函数（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Pascal</span><span style="font-size: 9pt; font-family: 宋体;">），或者都两者都采用（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c,</span><span style="font-size: 9pt; font-family: 宋体;">译注：也就是说</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c</span><span style="font-size: 9pt; font-family: 宋体;">既不把函数当一等公民，也限制词法范围）来回避这个问题。函数式语言就没有那些限制。围绕着非纯粹函数语言比如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Scheme</span><span style="font-size: 9pt; font-family: 宋体;">和</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">ML</span><span style="font-size: 9pt; font-family: 宋体;">的研究已经产生了大量的关于闭包的编译技术的知识（参见</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">[19, 1, 21]</span><span style="font-size: 10pt; font-family: 宋体;">）。尽管如此，这些工作并没有尽力去限制编译器的复杂性。以优化的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Scheme</span><span style="font-size: 10pt; font-family: 宋体;">编译器</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Bigloo</span><span style="font-size: 10pt; font-family: 宋体;">的控制流分</span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua03.jpg" alt="" border="0" /><br />
</p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">析阶段为例，（它的实现）比</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">实现的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">10</span><span style="font-size: 10pt; font-family: 宋体;">倍还大：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Bigloo <st1:chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2.6" unitname="F" w:st="on">2.6f</st1:chmetcnv></span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Cfa</span><span style="font-size: 10pt; font-family: 宋体;">模块源码有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">106,350</span><span style="font-size: 10pt; font-family: 宋体;">行</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> VS. 10,155</span><span style="font-size: 10pt; font-family: 宋体;">行的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua5.0</span><span style="font-size: 10pt; font-family: 宋体;">核心。正如第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2</span><span style="font-size: 10pt; font-family: 宋体;">部分已经解释过的（原因），</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">需要简单。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><!--[if gte vml 1]><v:shape id="_x0000_i1027" type="#_x0000_t75" style='width:415.5pt;height:285.75pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image003.png" o:title="3" />
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个称为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">的结构来实现闭包。任何外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的访问都是通过一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">间接进行的。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Upvalue</span><span style="font-size: 10pt; font-family: 宋体;">初始指向的是变量存活位置的栈槽（参见图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">的左半部分）。当变量（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">）已经离开作用域（译注，也就是这里的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">函数返回时），它就迁移到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构本身一个槽中（参见图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">的右半部分）。因为（对变量的）访问是间接地通过</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构中的一个指针进行的，因此这个迁移对于任何写或者读该变量的代码都是透明的。不像它的内嵌函数（译注：例子的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">，它是指外部函数</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">），声明变量的函数访问该变量就像访问它的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量一样：直接到栈。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">通过每个变量最多创建一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构并且在必要的时候复用它们，可变状态得以在闭包之间正确地共享。为了保证这一约束，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">维持一个链表，里面是一个栈里（图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">pending vars</span><span style="font-size: 10pt; font-family: 宋体;">列表）的所有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">（所谓</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">，是指仍然指向栈的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构）。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">创建一个新的闭包的时候，它遍历所有的外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量。对于每个（外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">）变量，如果它在列表中找到一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">，那么它就复用这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构。否则，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">就创建一个新的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">并将它放入链表。注意到列表搜索只是探测了少数几个节点，因为列表最多包含一个被内嵌函数使用的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的项。当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">closed
upvalue</span><span style="font-size: 10pt; font-family: 宋体;">不再被任何闭包引用的时候，它最后将被当作垃圾并回收。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">一个函数允许访问一个不是它的直接外围函数的外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量，只要（这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量）是外部函数的（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">outer function</span><span style="font-size: 10pt; font-family: 宋体;">）。在那种情况下，甚至在闭包被创建的时候，（外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">）变量可能就不在栈里了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用扁平闭包（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">flat
</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">closures</span><span style="font-size: 10pt; font-family: 宋体;">）解决这种情况</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">[5]</span><span style="font-size: 10pt; font-family: 宋体;">。通过扁平闭包，一个函数无论何时去访问一个不属于它的外围函数的外部变量，这个变量都将进入外围函数的闭包。从而当一个函数被实例化的时候，所有进入它闭包的变量要么在外围函数的栈里面，要么在外围函数的闭包里。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p><img src ="http://www.blogjava.net/killme2008/aggbug/191324.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-07 17:55 <a href="http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>lua 5.0的实现（翻译)1,2,3</title><link>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 07 Apr 2008 09:25:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/191314.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/191314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/191314.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">三个多月前翻译的，今天又找出来看看,后面的待整理下继续发,有错误的地方请不吝赐教。<br />
</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">原文：http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf<br />
</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">翻译：dennis zhuang</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#107;&#105;&#108;&#108;&#109;&#101;&#50;&#48;&#48;&#56;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">killme2008@gmail.com</a>)<span>&nbsp; </span><a href="http://www.blogjava.net/killme2008">http://www.blogjava.net/killme2008</a><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">转载请注明出处，谢谢。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">摘要：我们讨论了</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">实现的主要新特性：基于寄存器的虚拟机，优化表的新算法以便（将表）用作数组，闭包的实现，以及</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">（译注：协程）</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">关键字</span><span style="font-size: 9pt; font-family: CMBX9;" lang="EN-US">: </span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">compilers, virtual machines, hash tables, closures, coroutines<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 17.85pt; text-indent: -17.85pt;"><!--[if !supportLists]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><span>1.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp; </span></span></span></strong><!--[endif]--><strong><span style="font-size: 16pt; font-family: 宋体;">介绍</span></strong><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">作为内部使用的开发工具诞生于学术实验室中，现在却已经被世界范围内许多工业级项目所采用，广泛应用于游戏领域。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">为什么能获得这样广泛的应用呢？我们认为答案就来源于我们的设计和实现目标上：提供一种简单、高效、可移植和轻量级的嵌入式脚本语言。这是</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">自</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">1993</span><span style="font-size: 9pt; font-family: 宋体;">年诞生以来我们一直追求的目标，并在（语言的）演化过程中遵守。</span><span style="font-size: 10pt; font-family: 宋体;">这些特性，以及</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">一开始就被设计成嵌入大型应用的事实，才使它在早期被工业界所接受。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">广泛的应用产生了对（新的）语言的特性的需求。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">的许多特性来自于工业需求和用户反馈的推动。重要的例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">引入的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">和即将到来的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua 5.1</span><span style="font-size: 9pt; font-family: 宋体;">改进的垃圾收集实现，这些特性对于游戏（编程）特别重要。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">在这篇论文中，我们讨论了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">相比于</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 4.0</span><span style="font-size: 9pt; font-family: 宋体;">的主要新特性：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">基于寄存器的的虚拟机：传统上，绝大多数虚拟机的实际执行都是基于栈，这个趋势开始于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pascal</span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pmachine,</span><span style="font-size: 10pt; font-family: 宋体;">延续到今天的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">java</span><span style="font-size: 10pt; font-family: 宋体;">虚拟机和微软的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">.net</span><span style="font-size: 10pt; font-family: 宋体;">环境。目前，尽管对于基于寄存器的虚拟机的兴趣逐渐增多（比如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Perl6</span><span style="font-size: 10pt; font-family: 宋体;">计划中的新的虚拟机（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Parrot</span><span style="font-size: 10pt; font-family: 宋体;">）将是基于寄存器的），但是就我们所知，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">是第一个被广泛使用的基于寄存器的虚拟机。我们将在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">7</span><span style="font-size: 10pt; font-family: 宋体;">部分描述这个虚拟机。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">优化表的新算法以便作为数组：</span><span style="font-size: 10pt; font-family: CMR10;"> </span><span style="font-size: 10pt; font-family: 宋体;">不像其他脚本语言，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">并没有提供数组类型。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用整数索引的普通表来实现数组作为替代。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个新的算法，可以检测表是否被作为数组使用，并且可以自动将关联着数字索引的值存储进一个真实的数组，而不是将它们放进</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Hash</span><span style="font-size: 10pt; font-family: 宋体;">表。在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">部分我们将讨论这个算法。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">闭包的实现：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">在词法层次上支持</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class
</span><span style="font-size: 10pt; font-family: 宋体;">函数（译注：将函数作为一等公民）。这个机制导致一个著名的语言难题：使用基于数组的栈来存储激活记录。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua </span><span style="font-size: 10pt; font-family: 宋体;">使用了一个新办法来实现函数闭包，保存局部变量在（基于数组）的栈</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(stack)</span><span style="font-size: 10pt; font-family: 宋体;">上，当它们被内嵌函数引用而从作用域逸出的时候才将它们转移到堆</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(heap)</span><span style="font-size: 10pt; font-family: 宋体;">上。闭包的实现将在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">5</span><span style="font-size: 10pt; font-family: 宋体;">部分讨论。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">添加</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"> lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">语言引入了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">。尽管</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">的实现较为传统，但为了完整性我们将在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">6</span><span style="font-size: 9pt; font-family: 宋体;">部分做个简短的概况介绍。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">其他部分是为了讨论的完整性或者提供背景资料。在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体;">部分我们介绍了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">的设计目标以及这个目标如何驱动实现的概况。在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">3</span><span style="font-size: 9pt; font-family: 宋体;">部分我们介绍了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">是如何表示值的。尽管就这个过程本身没有什么新意，但是为了（理解）其他部分我们需要这些资料。最后，在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">8</span><span style="font-size: 9pt; font-family: 宋体;">部分，我们介绍了一个小型的基准测试来得到一些结论。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><span>2.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp; </span></span></span></strong><!--[endif]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US">lua</span></strong><strong><span style="font-size: 16pt; font-family: 宋体;">设计和实现概况</span></strong><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">在介绍部分提到过的，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">实现的主要目标是：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">简单性：我们探索我们能提供的最简单的语言，以及实现（这样的）语言的最简单的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">C</span><span style="font-size: 9pt; font-family: 宋体;">代码。这就意味着（需要）不会偏离传统很远的拥有很少语言结构的简单语法。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">效率：我们探索编译和执行</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">程序的最快方法，这就意味着（需要）一个高效的、聪明的一遍扫描编译器和一个高效的虚拟机。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">可移植性：我们希望</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">能跑在尽可能多的平台上。我们希望能在任何地方不用修改地编译</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">核心，在任何一个带有合适的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">解释器的平台上不用修改地运行</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">程序。这就意味着一个对可移植性特别关注的干净的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">ANSI C</span><span style="font-size: 9pt; font-family: 宋体;">的实现，例如避开</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">C</span><span style="font-size: 9pt; font-family: 宋体;">和标准库库中的陷阱缺陷，并确保能以</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c++</span><span style="font-size: 9pt; font-family: 宋体;">方式干净地编译。我们追求</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">w</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">arning-free</span><span style="font-size: 10pt; font-family: 宋体;">的编译（实现）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: 宋体;">嵌入性：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门扩展语言，它被设计用来为大型程序提供脚本设施。这个以及其他目标就意味着一个简单并且强大的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C API</span><span style="font-size: 10pt; font-family: 宋体;">实现，但这样将更多地依赖内建的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">类型。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: 宋体;">嵌入的低成本：我们希望能容易地将</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">添加进一个应用，而不会使应用变的臃肿。这就意味着（需要）紧凑的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">代码和一个小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">核心，扩展将作为用户库来添加。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">这些目标是有所权衡的。例如，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">经常被用作数据描述语言，用于保存和加载文件，有时是非常大的数据库</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(</span><span style="font-size: 10pt; font-family: 宋体;">几</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">M</span><span style="font-size: 10pt; font-family: 宋体;">字节的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序不常见</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">)</span><span style="font-size: 10pt; font-family: 宋体;">。这就意味着我们需要一个快速的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">编译器。另一方面，我们想让</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序运行快速，这就意味着（需要）一个可以为虚拟机产生优秀代码的聪明的编译器。因此，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">LUA</span><span style="font-size: 10pt; font-family: 宋体;">编译器的实现必须在这两种需求中寻找平衡。尽管如此，编译器还是不能太大，否则将使整个发行包变的臃肿。目前编译器大约占</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">核心大小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">30%</span><span style="font-size: 10pt; font-family: 宋体;">。在内存受限的应用中，比如嵌入式系统，嵌入不带有编译器的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">是可能的，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">程序将被离线预编译，然后被一个小模块（这个小模块也是快速的，因为它加载的是二进制文件）在运行时加载。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个手写的扫描器和一个手写的递归下降解释器。直到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3.0</span><span style="font-size: 10pt; font-family: 宋体;">版本，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">还在使用一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">YACC</span><span style="font-size: 10pt; font-family: 宋体;">产生的解释器，这在语言的语法不够稳定的时候很有价值的。然而，手写的解释器更小、更高效、更轻便以及完全可重入，也能提供更好的出错信息（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">error message</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">编译器没有使用中间代码表示（译注：也就是不生成中间代码）。当解释一个程序的时候，它以&#8220;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">on-the-fly&#8221;</span><span style="font-size: 10pt; font-family: 宋体;">的方式给虚拟机发出指令。不过，它会进行一些优化。例如，它会推迟像变量和常量这样的基本表达式的代码生成。当它解释这样的表达式的时候，没有产生任何代码，而是使用一种简单的结构来表示它们。所以，判断一个给定指令的操作数是常量还是变量以及将它们的值直接应用在指令都变的非常容易，避免了不必要的和昂贵的移动。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: 宋体;">为了轻便地在许许多多不同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">编译器和平台之间移植，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">不能使用许多解释器通常使用的技巧，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">direct threaded code [8, 16]</span><span style="font-size: 10pt; font-family: 宋体;">。作为替代，它（译注：指</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">解释器）使用了标准的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">while-switch</span><span style="font-size: 10pt; font-family: 宋体;">分发循环。此处的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">代码看起来过于复杂，但是复杂性也是为了确保可移植性。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">在许多不同的平台上（包括</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">64</span><span style="font-size: 10pt; font-family: 宋体;">位平台和一些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">16</span><span style="font-size: 10pt; font-family: 宋体;">位平台）被很多不同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">编译器编译，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">实现的可移植性一直以来变的越来越稳定了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">我们认为我们已经达到我们的设计和实现目标了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门非常轻便的语言，它能跑在任何一个带有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">编译器的平台上，从嵌入式系统到大型机。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">确实是轻量级的：例如，它在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">linux</span><span style="font-size: 10pt; font-family: 宋体;">平台上的独立解释器包括所有的标准库，占用的空间小于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">150K;</span><span style="font-size: 10pt; font-family: 宋体;">核心更是小于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100K</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是高效的：独立的基准测试表明</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是脚本语言（解释的、动态类型的语言）领域中最快的语言之一。主观上我们也认为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门简单的语言，语法上类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pascal</span><span style="font-size: 10pt; font-family: 宋体;">，语义上类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Scheme</span><span style="font-size: 10pt; font-family: 宋体;">（译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lisp</span><span style="font-size: 10pt; font-family: 宋体;">的一种方言）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">3</span></strong><strong><span style="font-size: 9pt; font-family: 宋体;">、值的表示</span></strong><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">是动态类型语言：类型依附于值而不是变量。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">有</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">8</span><span style="font-size: 9pt; font-family: 宋体;">种基本类型：</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">boolean</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">number</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">string</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">function</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">userdata</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">thread</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Nil</span><span style="font-size: 10pt; font-family: 宋体;">是一个标记类型，它只拥有一个值也叫</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Boolean</span><span style="font-size: 10pt; font-family: 宋体;">就是通常的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">true</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">false</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Number</span><span style="font-size: 10pt; font-family: 宋体;">是双精度浮点数，对应于</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">语言中的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型，但用</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">float</span><span style="font-size: 10pt; font-family: 宋体;">或者</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">long</span><span style="font-size: 10pt; font-family: 宋体;">作为替代来编译</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">也很容易（不少游戏</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">consoles</span><span style="font-size: 10pt; font-family: 宋体;">或者小机器都缺乏对</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">的硬件支持）</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">是有显式大小的字节数组，因此可以存储任意的二进制类型，包括嵌入零。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Table</span><span style="font-size: 10pt; font-family: 宋体;">类型就是关联的数组，可以用任何值做索引（除了</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">），也可以持有任何值。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Function</span><span style="font-size: 10pt; font-family: 宋体;">是依据与</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">虚拟机连接的协议编写的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">函数或者</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">函数。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Userdata</span><span style="font-size: 10pt; font-family: 宋体;">本质上是指向用户内存区块（</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">user memory block</span><span style="font-size: 10pt; font-family: 宋体;">）的指针，有两种风格：重量级</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: 宋体;">由</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">分配块并由</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">GC</span><span style="font-size: 10pt; font-family: 宋体;">回收；轻量级，由用户分配和释放（内存）块。最后，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">thread</span><span style="font-size: 10pt; font-family: 宋体;">表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">coroutines</span><span style="font-size: 10pt; font-family: 宋体;">。所有类型的值都是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class</span><span style="font-size: 10pt; font-family: 宋体;">值：我们可以将它们作为全局变量、局部变量和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的域来存储，作为参数传递给函数，作为函数的返回值等等。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">typedef struct {<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span>typedef union {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">int t; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>GCObject
*gc;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">Value v; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>void *p;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">} TObject; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>lua_Number n;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 215pt;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">int b;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 185pt;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">} Value;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMBX10;" lang="EN-US">Figure 1: </span><span style="font-size: 10pt; font-family: 宋体;">带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">将值表示为带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union(tagged unions)</span><span style="font-size: 10pt; font-family: 宋体;">，也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">pairs(t,v)</span><span style="font-size: 10pt; font-family: 宋体;">，其中</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">t</span><span style="font-size: 10pt; font-family: 宋体;">是一个决定了值</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">类型的整数型标签，而</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">是一个实现了</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">类型的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">语言的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">结构。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Nil</span><span style="font-size: 10pt; font-family: 宋体;">拥有一个单独的值（译注：也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Booleans</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">numbers</span><span style="font-size: 10pt; font-family: 宋体;">被实现为&#8220;拆箱式&#8221;的值：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中直接表示这些类型的值。这就意味着</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">（译注：指图中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Value</span><span style="font-size: 10pt; font-family: 宋体;">）必须有足够的空间容纳</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">（类型）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Strings,tables,
functions, threads, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> userdata</span><span style="font-size: 10pt; font-family: 宋体;">类型的值通过引用来实现：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">拥有指向实现这些类型的结构的指针。这些结构（译注：指实现</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Strings,tables, functions, threads, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> userdata</span><span style="font-size: 10pt; font-family: 宋体;">这些类型的具体结构）共享一个共同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">head</span><span style="font-size: 10pt; font-family: 宋体;">，用来保存用于垃圾收集的信息。结构的剩下的部分专属于各自的类型。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><span>&nbsp;</span>Figure1</span><span style="font-size: 10pt; font-family: 宋体;">展示了一个实际的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值的实现。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">TObject</span><span style="font-size: 10pt; font-family: 宋体;">是这个实现的主要结构体：它表示了上文描述的带标签的联合体（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">tagged unions</span><span style="font-size: 10pt; font-family: 宋体;">）</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> (t,v)</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Value</span><span style="font-size: 10pt; font-family: 宋体;">是实现了值的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">类型。类型</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">的值没有显式表示在这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">类型中是因为标签已经足够标识它们。域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">用来表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">numbers</span><span style="font-size: 10pt; font-family: 宋体;">类型（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua_Number</span><span style="font-size: 10pt; font-family: 宋体;">默认是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型）。同样，域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">b</span><span style="font-size: 10pt; font-family: 宋体;">是给</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">booleans</span><span style="font-size: 10pt; font-family: 宋体;">类型用的，域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">p</span><span style="font-size: 10pt; font-family: 宋体;">是给轻量级的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">userdata</span><span style="font-size: 10pt; font-family: 宋体;">类型。而域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">gc</span><span style="font-size: 10pt; font-family: 宋体;">是为会被垃圾回收的其他类型准备的（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(strings, tables, functions, </span><span style="font-size: 10pt; font-family: 宋体;">重量级</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">userdata, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">threads)</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">使用带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">实现</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值的一个后果就是拷贝值的代价稍微昂贵了一点：在一台支持</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">64</span><span style="font-size: 10pt; font-family: 宋体;">位</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">32</span><span style="font-size: 10pt; font-family: 宋体;">位机器上，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">TObject</span><span style="font-size: 10pt; font-family: 宋体;">的大小是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">12</span><span style="font-size: 10pt; font-family: 宋体;">字节（或者</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">16</span><span style="font-size: 10pt; font-family: 宋体;">字节，如果</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">按</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">8</span><span style="font-size: 10pt; font-family: 宋体;">字节对齐的话），因此拷贝一个值将需要拷贝</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3</span><span style="font-size: 10pt; font-family: 宋体;">（或者</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">）个机器字长。尽管如此，想在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">中实现一个更好的值的表示是困难的。一些动态类型语言（例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Smalltalk80</span><span style="font-size: 10pt; font-family: 宋体;">的原始实现）在每个指针中使用多余的位来存储值的类型标签。这个技巧在绝大多数机器上正常工作，这是因为一个指针的最后两个或者三个位由于对齐将总是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">0</span><span style="font-size: 10pt; font-family: 宋体;">，所以可以被用作他途。但是，这项技术既不是可移植的也无法在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">中实现，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C </span><span style="font-size: 10pt; font-family: 宋体;">语言标准甚至都不保证指针适合任何整数类型，所以没有在指针上操作位的标准方法。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">减小值大小的另一个观点就是持有显式标签，从而避免在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中放置一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型。例如，所有的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">number</span><span style="font-size: 10pt; font-family: 宋体;">类型可以表示为堆分配的对象，就像</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">那样。（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">python</span><span style="font-size: 10pt; font-family: 宋体;">使用了这项技术，除了预先分配了一些小的整数值）。尽管如此，这样的表示方法将使语言变的非常缓慢。作为选择，整数的值可以表示位&#8220;拆箱式&#8221;的值，直接存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中，而浮点值放在堆中。这个办法将极大地增加所有算术运算操作的实现复杂度。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">类似早期的解释型语言，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Snobol [11] </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> Icon [10]</span><span style="font-size: 10pt; font-family: 宋体;">，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">在一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表中&#8220;拘留&#8221;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">internalizes)</span><span style="font-size: 10pt; font-family: 宋体;">字符串：（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表）没有重复地持有每个字符串的单独拷贝。此外，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">是不可变的：一个字符串一旦被&#8220;拘留&#8221;，将不能再被改变。字符串的哈希值依据一个混合了位和算术运算的简单表达式来计算，囊括所有的位。当字符串被&#8220;拘留&#8221;时，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值保存（到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表），以支持更快的字符串比较和表索引。如果字符串太长的话，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">函数并不会用到字符串的所有字节，这有利于快速地散列长字符串。避免处理长字符串带来的性能损失是重要的，因为（这样的操作）在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">中是很普遍的。例如，用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">处理文件的时候经常将整个文件内容作为一个单独的长字符串读入内存。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p><img src ="http://www.blogjava.net/killme2008/aggbug/191314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-07 17:25 <a href="http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重定向和管道的实现</title><link>http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 29 Feb 2008 03:16:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/182868.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/182868.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/182868.html</trackback:ping><description><![CDATA[重定向标准输入的实现：<br />
1）close-then-open: close(0) ; fd=open("test",O_RDONLY); fd将是stdin。<br />
2)open-close-dup-close:<br />
fd=open(file),打开stdin将要重定向的文件；close(0);new_fd=dup(file);close(fd);new_fd就是被重定向的stdin<br />
3)open-dup2-close:<br />
fd=open(file);new_fd=dup2(fd,0);close(fd);<br />
<br />
重定向标准输出的实现：<br />
&nbsp;
父进程fork();子进程close(1);create("g",0644)，此时子进程的stdout被重定向到g;接下来子进程exec某个程序，文件描述符属于进程属性，exec调用不会改变他们，那么运行的程序的标准输出将被送到g，由此实现了标准输出重定向。<br />
<br />
本质上重定向的实现是依赖两个原则：<br />
1、标准输入、标准输出和标准错误分别是0、1和2<br />
2、最低可用描述符：打开文件时，为此文件安排的描述符总是进程内打开文件数组的最低可用位置的索引。<br />
<br />
管道：<br />
&nbsp; 匿名管道：适合于有亲缘关系的进程，通过pipe函数实现。<br />
&nbsp; 有名管道：通过mkfifo函数实现，实现进程间的双向通讯可以采用两个有名管道实现，也可以采用socketpair调用。<img src ="http://www.blogjava.net/killme2008/aggbug/182868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-29 11:16 <a href="http://www.blogjava.net/killme2008/archive/2008/02/29/182868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>写操作系统？看看这个（转载）</title><link>http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 22 Feb 2008 09:53:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/181476.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/181476.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/181476.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 今天在pongba的邮件列表里看到了这个<a href="http://blog.solrex.cn/articles/free-ebook-write-os-with-free-software-revision-1-released.html">《免费电子书&lt;使用开源软件——自己动手写操作系统&gt;》 </a><br />
&nbsp;&nbsp;&nbsp; 只能说太酷了，china-pub上一直有本书《自己动手写操作系统》，牛人看到这本书使用的是商业软件做示范，于是动念想是不是能使用开源软件来实现书中所有的demo，于是就有了这本宝贵的电子书。<br />
&nbsp;&nbsp;&nbsp; 项目主页：http://share.solrex.cn/WriteOS/<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/181476.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-22 17:53 <a href="http://www.blogjava.net/killme2008/archive/2008/02/22/181476.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>视频站点的搭建</title><link>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 19 Dec 2007 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/168788.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/168788.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/168788.html</trackback:ping><description><![CDATA[&nbsp; &nbsp; 挺久没动笔写blog了，换了新工作比较忙是一个原因。最近的工作是做一个素材管理的系统，其中有个要求做视频预览，将用户上传的视频转换并在网页上预览。在网页上看视频，现在大多数视频网站都是采用flv流媒体文件，用flash做的播放器播放，我们也采用了这种方式。流程大概主要：用户上传文件-&gt;后台转换文件成flv格式-&gt;flv播放器调用flv文件。<br />
&nbsp;&nbsp;&nbsp; 转换视频、音频文件到flv格式可以使用mencoder或者ffmpeg，我们采用了mencoder，在linux上的安装参考<a href="http://hi.baidu.com/flash%5Fzb/blog/item/bbf7668de6f85912b21bbae0.html">这里</a>,安装结束后记的设置环境变量：export LD_LIBRARY_PATH=/usr/local/lib:LD_LIBRARY_PATH<br />
&nbsp;&nbsp;&nbsp; java调用的话就是通过Process：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">&nbsp;Process&nbsp;process&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;runtime.exec(cmd);</span></div>
<br />
mencoder转换视频音频成flv命令：<br />
mencoder 源文件 -o 目标文件.flv -of lavf&nbsp;&nbsp;&nbsp; -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=400:mbd=2:mv0:trell:v4mv:cbp:last_pred=3:dia=4:cmp=6:vb_strategy=1 -vf scale=200:-3 -ofps 12 -srate 22050<br />
<br />
取视频元信息命令（视频比特率、长宽等信息）：<br />
mplayer -identify 文件名 -ao null -vo null -frames 0 <br />
<br />
切割视频命令：<br />
mencoder -ss 开始时间 -oac copy -ovc copy -endpos 终止时间 文件名 -o 目标文件名<br />
<br />
&nbsp;&nbsp;&nbsp; 操作flv文件（给视频打上信息、切割之类）可以采用<a href="http://rubyforge.org/projects/flvtool2/">flvtool2</a>。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 需要注意的是通过java调用的话，一定要处理标准输出和标准错误输出，不然进程会挂在那结束不了，可以开个线程取处理。在网页播放的话，可以考虑用<a href="http://hi.baidu.com/lzxinta/blog/item/4c02d55103216d2643a75b7b.html">这个播放器</a>，具体参数看它的说明。最后一个问题，IE6的flash控件需要激活，这个问题的解决可以采用<a href="http://blog.deconcept.com/swfobject/">swfobject.js</a>。<br />
&nbsp;&nbsp;&nbsp; 有兴趣的老大们可以考虑自己搭个&#8220;土豆网&#8221;，说不定哪天拿了风投.....浮云<br /><img src ="http://www.blogjava.net/killme2008/aggbug/168788.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-12-19 16:46 <a href="http://www.blogjava.net/killme2008/archive/2007/12/19/168788.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天长见识了</title><link>http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 29 Nov 2007 10:17:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/164069.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/164069.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/164069.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 先是读《Programming in Lua》第9章讲<span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine，然后去google </span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine，找到</span><em><a href="http://pobox.com/%7Eanakin/">Simon Tatham</a>写的</em><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">一篇</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US"><a href="http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html">coroutine in c</a>，讲怎么在C语言中实现</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine，文中</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">先ugly地基于栈实现了一个：<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;function(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">switch</span><span style="color: #000000;">&nbsp;(state)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">:&nbsp;</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;LABEL0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">:&nbsp;</span><span style="color: #0000ff;">goto</span><span style="color: #000000;">&nbsp;LABEL1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;LABEL0:&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;start&nbsp;of&nbsp;function&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;so&nbsp;we&nbsp;will&nbsp;come&nbsp;back&nbsp;to&nbsp;LABEL1&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LABEL1:;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;resume&nbsp;control&nbsp;straight&nbsp;after&nbsp;the&nbsp;return&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<br />
这个方法简单，但是相当丑陋，你必须手工维护这些标签。然后提到了Duff's Device技巧：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">switch</span><span style="color: #000000;">&nbsp;(count&nbsp;</span><span style="color: #000000;">%</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;{&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">7</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">6</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">5</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">4</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">3</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">2</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">&nbsp;((count&nbsp;</span><span style="color: #000000;">-=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;">)&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
这段代码能编译通过吗？能的，不信你试试，这是一段用于拷贝数组的代码，我们一般拷贝数组是这样做的：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">send(to,&nbsp;from,&nbsp;count)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register&nbsp;</span><span style="color: #0000ff;">short</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to,&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register&nbsp;count;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">to&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">from</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(</span><span style="color: #000000;">--</span><span style="color: #000000;">count</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
如果循环的中的操作足够快，那么其实大部分时间都是浪费在判断循环条件上面的，而通过Duff's Device通过switch语句将要进行的连续循环操作的次数进行了预判（根据擦case语句的位置）然后依次执行，而不必每次都去进 行测试条件，从而加速循环。这个技巧怎么应用于实现更优雅的<span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">coroutine呢？看代码<br />
<br />
</span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;function(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i,&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">switch</span><span style="color: #000000;">&nbsp;(state)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">:&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;start&nbsp;of&nbsp;function&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;so&nbsp;we&nbsp;will&nbsp;come&nbsp;back&nbsp;to&nbsp;"case&nbsp;1"&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">case</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">:;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;resume&nbsp;control&nbsp;straight&nbsp;after&nbsp;the&nbsp;return&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
更好的方式是使用宏：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;crBegin&nbsp;static&nbsp;int&nbsp;state=0;&nbsp;switch(state)&nbsp;{&nbsp;case&nbsp;0:</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;crReturn(i,x)&nbsp;do&nbsp;{&nbsp;state=i;&nbsp;return&nbsp;x;&nbsp;case&nbsp;i:;&nbsp;}&nbsp;while&nbsp;(0)</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">#define</span><span style="color: #000000;">&nbsp;crFinish&nbsp;}</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;function(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;crBegin;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">10</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;crReturn(</span><span style="color: #000000;">1</span><span style="color: #000000;">,&nbsp;i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;crFinish;<br />
}</span></div>
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/164069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-11-29 18:17 <a href="http://www.blogjava.net/killme2008/archive/2007/11/29/164069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hack,hacker</title><link>http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 15 Oct 2007 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/152846.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/152846.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/152846.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; hack有水平高低之分，最近看到一个blog，牛人的hack水平让你不得不服。情况是这样的，牛人在使用 <a href="http://public.railsplugins.net/repos/mongrel_light_cluster/trunk/">mongrel_light_cluster</a>的过程中，发现这个cluster违反了copy-on-write的语义，导致占用了太多的内存。根本原因在于Ruby的GC机制是<a href="http://blog.beaver.net/2005/03/ruby_gc_and_copyonwrite.html">marks all memory pages as dirty</a>。为了减少内存的占用，让集群跑更多mongrel，牛人走上了hack之路，给c ruby打补丁，他也真的<a href="http://izumi.plan99.net/blog/index.php/2007/10/13/making-ruby%e2%80%99s-garbage-collector-copy-on-write-friendly-part-4/">做到了</a>。c ruby的GC使用的是mark and sweep(标记并清除)的垃圾收集算法，他发现在mark过程中使用了<a href="http://www.blogjava.net/killme2008/archive/2007/09/18/146234.html">st_table</a>，这个数据结构占用了很大的内存，那么就改用<a href="http://code.google.com/p/google-sparsehash/">Google&#8217;s sparse_hash</a>。然后他又写了一个memory pool，以应对marking和sweep使用过程中对malloc和free调用带来的内存损失，因为在x86 GNU/linux gcc上，malloc函数如果申请的内存小于76KB，那么当free的时候这些内存不会被返还给操作系统。他的hack之路还没结束，有兴趣的关注他的blog: <br />
<br />
&nbsp;http://izumi.plan99.net/blog/index.php/<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/152846.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-10-15 09:09 <a href="http://www.blogjava.net/killme2008/archive/2007/10/15/152846.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby变量在c ruby中的存储</title><link>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 20 Sep 2007 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/146799.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/146799.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/146799.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 读完ruby hacking guide第6章，彻底总结下：<br />
1.在Ruby中，类也是一个对象，因此有实例变量。类的实例变量、类变量、常量都是存储在RClass struct的iv_tbl中，<br />
struct RClass {<br />
&nbsp;&nbsp;&nbsp; struct RBasic basic;<br />
&nbsp;&nbsp;&nbsp; struct st_table *iv_tbl;<br />
&nbsp;&nbsp;&nbsp; struct st_table *m_tbl;<br />
&nbsp;&nbsp;&nbsp; VALUE super;<br />
};<br />
iv_tbl的类型是st_table，我在<a href="http://www.blogjava.net/killme2008/archive/2007/09/18/146234.html">这里</a>用java实现了一下。<br />
<br />
2.用户自定义类的对象（ruby层次声明的类的对象)的实例变量存储在RObject struct的iv_tbl中，<br />
struct RObject {<br />
&nbsp; struct RBasic basic;<br />
&nbsp; struct st_table *iv_tbl;<br />
&nbsp;};<br />
调用方法，本质上是一个查表操作。buildin的几个类，比如String、Array、Hash等(在c层次上实现的类），它们的结构并没有iv_table，这是从节省内存空间的角度考虑，它们的实例变量存储在一张全局的st_table中。这张表比较特别，其中的每一个对应的值又是一个st_table，也就是一个&#8220;二元结构&#8221;，第一层结构是类名与实例变量表的映射，第二层才是实例变量名与实际值的映射。<br />
<br />
3.全局变量存储在一张全局的st_table中，这个表的键就是变量名ID，由于全局变量允许通过alias来设置别名，因此这张全局表中真正存储的是下面这个struct<br />
<br />
334  struct global_entry {<br />
335      struct global_variable *var;<br />
336      ID id;<br />
337  };<br />
<br />
324  struct global_variable {<br />
325      int   counter;      /* 引用计数 */<br />
326      void *data;         /* 变量值 */<br />
327      VALUE (*getter)();  /* 取值函数 */<br />
328      void  (*setter)();  /* 设置函数 */<br />
329      void  (*marker)();  /* 标记函数 */<br />
330      int block_trace;<br />
331      struct trace_var *trace;<br />
332  };<br />
(variable.c)<br />
<br />
当不同变量名（通过别名声明）指向的是同一个全局变量，其实它们指向的是同一个struct global_variable。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/146799.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-20 16:17 <a href="http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>判断栈的增长方向</title><link>http://www.blogjava.net/killme2008/archive/2007/09/17/145892.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 17 Sep 2007 08:16:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/17/145892.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/145892.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/17/145892.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/145892.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/145892.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; dreamhead老大曾经讨论过这个问题，寻找一种可移植的方式来判断栈的增长方向，见《<a href="http://dreamhead.blogbus.com/logs/4840895.html">栈的增长方向</a>》。今天在读Ruby hacking guide第5章，介绍alloca函数的部分，提到ruby实现的C语言版本的alloca.c，读了下代码，发现这里倒是实现了一个很漂亮的函数用于实现判断栈的增长方向，利用了局部static变量，与dreamhead老大的想法其实是一致的。<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;find_stack_direction(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">);<br />
</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;stack_dir;<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br />
{<br />
&nbsp;&nbsp;find_stack_direction();<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(stack_dir</span><span style="color: #000000;">==</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts(</span><span style="color: #000000;">"</span><span style="color: #000000;">stack&nbsp;grew&nbsp;upward</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts(</span><span style="color: #000000;">"</span><span style="color: #000000;">stack&nbsp;grew&nbsp;downward</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
}<br />
</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;find_stack_direction&nbsp;(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br />
{<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">addr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;NULL;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;address&nbsp;of&nbsp;first<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`dummy',&nbsp;once&nbsp;known&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;auto&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dummy;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;to&nbsp;get&nbsp;stack&nbsp;address&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(addr&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;NULL)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;initial&nbsp;entry&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;addr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">dummy;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;find_stack_direction&nbsp;();&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;recurse&nbsp;once&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;second&nbsp;entry&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">dummy&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;addr)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack_dir&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;stack&nbsp;grew&nbsp;upward&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack_dir&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">&nbsp;stack&nbsp;grew&nbsp;downward&nbsp;</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
}<br />
</span></div>
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/145892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-17 16:16 <a href="http://www.blogjava.net/killme2008/archive/2007/09/17/145892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言中实现可变参数函数</title><link>http://www.blogjava.net/killme2008/archive/2007/08/31/141775.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 31 Aug 2007 09:06:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/08/31/141775.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/141775.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/08/31/141775.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/141775.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/141775.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 通过stdarg.h头文件为函数提供了定义可变参数列表的能力。声明一个可变参数的函数类似：<br />
void f1(int n,...);<br />
<br />
其中n表示参数列表个数，而用省略号来表示未知参数列表。stdarg.h中提供了一个va_list类型，用于存放参数。一个大概的使用过程类似：<br />
void f1(int n,...)<br />
{<br />
&nbsp;&nbsp; va_list ap;<br />
&nbsp;&nbsp; va_start(ap,n);&nbsp;&nbsp; //初始化参数列表<br />
&nbsp;&nbsp; double first=va_arg(ap,double);&nbsp; //取第一个参数<br />
&nbsp;&nbsp; int second=va_arg(ap,int);&nbsp;&nbsp; //取第二个参数<br />
&nbsp;&nbsp; ...<br />
&nbsp;&nbsp; va_end(ap);&nbsp; //清理工作<br />
}<br />
看一个求和的例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdarg.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&nbsp;sum(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;,<img src="http://www.blogjava.net/Images/dot.gif" alt="" />);<br />
</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">void</span><span style="color: #000000;">)<br />
{<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&nbsp;s,t;<br />
&nbsp;&nbsp;s</span><span style="color: #000000;">=</span><span style="color: #000000;">sum(</span><span style="color: #000000;">3</span><span style="color: #000000;">,</span><span style="color: #000000;">1.1</span><span style="color: #000000;">,</span><span style="color: #000000;">2.2</span><span style="color: #000000;">,</span><span style="color: #000000;">13.3</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;t</span><span style="color: #000000;">=</span><span style="color: #000000;">sum(</span><span style="color: #000000;">6</span><span style="color: #000000;">,</span><span style="color: #000000;">1.1</span><span style="color: #000000;">,</span><span style="color: #000000;">2.1</span><span style="color: #000000;">,</span><span style="color: #000000;">13.1</span><span style="color: #000000;">,</span><span style="color: #000000;">4.1</span><span style="color: #000000;">,</span><span style="color: #000000;">5.1</span><span style="color: #000000;">,</span><span style="color: #000000;">6.1</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">return&nbsp;value&nbsp;for&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;&nbsp;\<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">sum(3,1.1,2.2,13.3):&nbsp;&nbsp;&nbsp;%g\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,s);<br />
&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">return&nbsp;value&nbsp;for&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;\<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">sum(6,1.1,2.1,13.1,4.1,5.1,6.1):&nbsp;&nbsp;&nbsp;&nbsp;%g\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,t);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
}<br />
</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&nbsp;sum(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;lim,<img src="http://www.blogjava.net/Images/dot.gif" alt="" />)<br />
{<br />
&nbsp;&nbsp;va_list&nbsp;ap;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">double</span><span style="color: #000000;">&nbsp;total</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;va_start(ap,lim);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(i</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">lim;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total</span><span style="color: #000000;">+=</span><span style="color: #000000;">va_arg(ap,</span><span style="color: #0000ff;">double</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;va_end(ap);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;total;<br />
}<br />
</span></div>
<br />
C语言对可变参数的使用还是有点麻烦，不如ruby和java简便。比如ruby中定义并使用可变参数参数：<br />
def sum(*e)<br />
&nbsp;&nbsp; e.inject{|sum,i| sum+=i}<br />
end<br />
<br />
sum(1,2,3,4,5)=&gt;15<br />
&nbsp;&nbsp; <br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/141775.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-08-31 17:06 <a href="http://www.blogjava.net/killme2008/archive/2007/08/31/141775.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>断开的管道？</title><link>http://www.blogjava.net/killme2008/archive/2007/08/29/141062.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 29 Aug 2007 11:17:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/08/29/141062.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/141062.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/08/29/141062.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/141062.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/141062.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 在《unix/linux编程实践》一书中的多线程web server例子，我用ab测试一下老是导致程序挂掉，报一个断开的管道的错误。搜索得知，这个错误就是一般常见的Connection &nbsp; reset &nbsp; by &nbsp; peer。当往关闭的管道或是socket里面写东西就会产生SIGPIPE信号，而系统默认对这个信号的处理是杀死该进程，因此解决办法就是在程序中设置忽略这个信号：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include&lt;signal.h&gt;<br>....<br><br>signal(SIGPIPE,&nbsp;SIG_IGN);</span></div>
<br><br><img src ="http://www.blogjava.net/killme2008/aggbug/141062.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-08-29 19:17 <a href="http://www.blogjava.net/killme2008/archive/2007/08/29/141062.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>比较C语言标准I/O与*nix系统I/O的异同</title><link>http://www.blogjava.net/killme2008/archive/2007/08/22/138651.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 22 Aug 2007 08:47:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/08/22/138651.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/138651.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/08/22/138651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/138651.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/138651.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; linux/unix系统的I/O也就是一般所说的低级I/O——操作系统提供的基本IO服务，与os绑定，特定于*nix平台。而标准I/O是ANSI C建立的一个标准I/O模型，是一个标准函数包和stdio.h头文件中的定义，具有一定的可移植性。两者一个显著的不同点在于，标准I/O默认采用了缓冲机制，比如调用fopen函数，不仅打开一个文件，而且建立了一个缓冲区（读写模式下将建立两个缓冲区），还创建了一个包含文件和缓冲区相关数据的数据结构。低级I/O一般没有采用缓冲，需要自己创建缓冲区，不过其实在*nix系统中，都是有使用称为<span style="font-weight: bold;">内核缓冲</span>的技术用于提高效率，读写调用是在内核缓冲区和进程缓冲区之间进行的数据复制。<br><br><span style="font-weight: bold;">1.fopen与open</span><br><span style="font-weight: bold;">标准I/O使用fopen函数打开一个文件</span>：<br>FILE* fp=fopen(const char* path,const char *mod)<br><br>其中path是文件名，mod用于指定文件打开的模式的字符串，比如"r","w","w+","a"等等，可以加上字母b用以指定以二进制模式打开（对于*nix系统，只有一种文件类型，因此没有区别）,如果成功打开，返回一个FILE文件指针，如果失败返回NULL,这里的文件指针并不是指向实际的文件，而是一个关于文件信息的数据包，其中包括文件使用的缓冲区信息。<br><br><span style="font-weight: bold;">*nix系统使用open函数用于打开一个文件</span>：<br>int fd=open(char *name,int how);<br>与fopen类似，name表示文件名字符串，而how指定打开的模式：O_RDONLY(只读),O_WRONLY(只写）,O_RDWR （可读可写),还有其他模式请man 2 open。成功返回一个正整数称为<span style="font-weight: bold;">文件描述符</span>，这与标准I/O显著不同，失败的话返回-1，与标准I/O返回NULL也是不同的。<br><br><span style="font-weight: bold;">2.fclose与close</span><br>与打开文件相对的，<span style="font-weight: bold;">标准I/O使用fclose关闭文件</span>，将文件指针传入即可，如果成功关闭，返回0，否则返回EOF<br>比如： <br><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;"></span>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">if</span><span style="color: #000000;">(fclose(fp)</span><span style="color: #000000;">!=</span><span style="color: #000000;">0</span><span style="color: #000000;">)&nbsp;&nbsp;<br>&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">Error&nbsp;in&nbsp;closing&nbsp;file</span><span style="color: #000000;">"</span><span style="color: #000000;">);</span></div>
<br>而*nix使用close用于关闭open打开的文件，与fclose类似，只不过当错误发生时返回的是-1，而不是EOF，成功关闭同样是返回0。C语言用error code来进行错误处理的传统做法。<br><br><span style="font-weight: bold;">3.读文件</span>，getc,fscanf,fgets和read<br>标准I/O中进行文件读取可以使用getc，一个字符一个字符的读取，也可以使用gets（读取标准io读入的）、fgets以字符串单位进行读取（读到遇到的第一个换行字符的后面），gets（接受一个参数，文件指针）不判断目标数组是否能够容纳读入的字符，可能导致存储溢出(<span style="font-weight: bold;">不建议使用</span>），而fgets使用三个参数：<br>&nbsp;char * fgets(char *s, int size, FILE *stream);
<br>第一个参数和gets一样，用于存储输入的地址，第二个参数为整数，表示输入字符串的最大长度，最后一个参数就是文件指针，指向要读取的文件。最后是fscanf，与scanf类似，只不过增加了一个参数用于指定操作的文件，比如fscanf(fp,"%s",words)<br><br>*nix系统中使用read函数用于读取open函数打开的文件，函数原型如下：<br>ssize_t numread=read(int fd,void *buf,size_t qty);<br><br>其中fd就是open返回的文件描述符，buf用于存储数据的目的缓冲区，而qty指定要读取的字节数。如果成功读取，就返回读取的字节数目（小于等于qty）。<br><br><span style="font-weight: bold;">4.判断文件结尾</span>，如果尝试读取达到文件结尾，标准IO的getc会返回特殊值EOF，而fgets碰到EOF会返回NULL,而对于*nix的read函数，情况有所不同。read读取qty指定的字节数，最终读取的数据可能没有你所要求的那么多（qty），而当读到结尾再要读的话，read函数将返回0.<br><br><span style="font-weight: bold;">5.写文件</span>：putc,fputs,fprintf和write<br><br>与读文件相对应的，标准C语言I/O使用putc写入字符，比如：<br>putc(ch,fp);<br>第一个参数是字符，第二个是文件指针。而fputs与此类似：<br>fputs(buf,fp);<br>仅仅是第一个参数换成了字符串地址。而fprintf与printf类似，增加了一个参数用于指定写入的文件，比如：<br>fprintf(stdout,"Hello %s.\n","dennis");<br>切记fscanf和fprintf将FILE指针作为第一个参数，而putc,fputs则是作为第二个参数。<br><br>在*nix系统中提供write函数用于写入文件，原型与read类似：<br>ssize_t result=write(int fd,void *buf ,size_t amt);<br><br>fd是文件描述符，buf是将要写入的内存数据，amt是要写的字节数。如果写入成功返回写入的字节数，通过result与amt的比较可以判断是否写入正常，如果写入失败返回-1。write函数仅仅是将数据写入了缓冲区，何时写入磁盘由内核决定，如果要强制写入硬盘，那么在open的时候选择O_SYNC选项，或者调用fsync函数<br><br><span style="font-weight: bold;">6.随机存取</span>：fseek()、ftell()和lseek()<br>标准I/O使用fseek和ftell用于文件的随机存取，先看看fseek函数原型<br>int fseek(FILE *stream, long offset, int whence);<br>第一个参数是文件指针，第二个参数是一个long类型的偏移量（offset），表示从起始点开始移动的距离。第三个参数就是用于指定起始点的模式，stdio.h指定了下列模式常量：<br>SEEK_SET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件开始处<br>SEEK_CUR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当前位置<br>SEEK_END&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件结尾处<br>看几个调用例子：<br>fseek(fp,0L,SEEK_SET);&nbsp; //找到文件的开始处<br>fseek(fp,0L,SEEK_END);&nbsp; //定位到文件结尾处<br>fseek(fp,2L,SEEK_CUR);&nbsp; //文件当前位置向前移动2个字节数<br><br>而ftell函数用于返回文件的当前位置，返回类型是一个long类型，比如下面的调用：<br>fseek(fp,0L,SEEK_END);//定位到结尾<br>long last=ftell(fp);&nbsp; //返回当前位置<br>那么此时的last就是文件指针fp指向的文件的字节数。<br><br>与标准I/O类似，*nix系统提供了lseek来完成fseek的功能，原型如下：<br>off_t lseek(int fildes, off_t offset, int whence);
<br><br>fildes是文件描述符，而offset也是偏移量，whence同样是指定起始点模式，唯一的不同是lseek有返回值，如果成功就返回指针变化前的位置，否则返回-1。因此可以通过下列方法模拟ftell函数来返回当前偏移量：<br>off_t&nbsp;&nbsp;&nbsp; currpos;<br>currpos = lseek(fd, 0, SEEK_CUR);
<br>whence的取值与fseek相同：SEEK_SET,SEEK_CUR,SEEK_END，但也可以用整数0,1,2相应代替。<br><br>最后，以一个例子结尾，通过c语言编写linux系统的cp指令，先看看使用标准I/O版本的：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdlib.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;oops(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">);<br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;ac,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">av[])<br>{<br>&nbsp;&nbsp;FILE&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">in,</span><span style="color: #000000;">*</span><span style="color: #000000;">out;<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;ch;<br><br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(ac</span><span style="color: #000000;">!=</span><span style="color: #000000;">3</span><span style="color: #000000;">){<br>&nbsp;&nbsp;&nbsp;fprintf(stderr,</span><span style="color: #000000;">"</span><span style="color: #000000;">Useage:%s&nbsp;source-file&nbsp;target-file.\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">0</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">((in</span><span style="color: #000000;">=</span><span style="color: #000000;">fopen(av[</span><span style="color: #000000;">1</span><span style="color: #000000;">],</span><span style="color: #000000;">"</span><span style="color: #000000;">r</span><span style="color: #000000;">"</span><span style="color: #000000;">))</span><span style="color: #000000;">==</span><span style="color: #000000;">NULL)<br>&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">can&nbsp;not&nbsp;open&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">1</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">((out</span><span style="color: #000000;">=</span><span style="color: #000000;">fopen(av[</span><span style="color: #000000;">2</span><span style="color: #000000;">],</span><span style="color: #000000;">"</span><span style="color: #000000;">w</span><span style="color: #000000;">"</span><span style="color: #000000;">))</span><span style="color: #000000;">==</span><span style="color: #000000;">NULL)<br>&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">can&nbsp;not&nbsp;open&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">2</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">((ch</span><span style="color: #000000;">=</span><span style="color: #000000;">getc(in))</span><span style="color: #000000;">!=</span><span style="color: #000000;">EOF)<br>&nbsp;&nbsp;&nbsp;&nbsp;putc(ch,out);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(fclose(in)</span><span style="color: #000000;">!=</span><span style="color: #000000;">0</span><span style="color: #000000;">||</span><span style="color: #000000;">fclose(out)</span><span style="color: #000000;">!=</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">can&nbsp;not&nbsp;close&nbsp;files.\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;oops(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">s1,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;s2)<br>{<br>&nbsp;&nbsp;fprintf(stderr,</span><span style="color: #000000;">"</span><span style="color: #000000;">Error:%s&nbsp;%s\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,s1,s2);<br>&nbsp;&nbsp;exit(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>}<br></span></div>
<br>再看一个使用unix io的版本：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">unistd.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">fcntl.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br><br>#define&nbsp;BUFFERSIZE&nbsp;</span><span style="color: #000000;">4096</span><span style="color: #000000;"><br>#define&nbsp;COPYMODE&nbsp;</span><span style="color: #000000;">0644</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;oops(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">);<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;ac,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">av[])<br>{<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;in_fd,out_fd,n_chars;<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;buf[BUFFERSIZE];<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(ac</span><span style="color: #000000;">!=</span><span style="color: #000000;">3</span><span style="color: #000000;">){<br>&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,</span><span style="color: #000000;">"</span><span style="color: #000000;">useage:%s&nbsp;source-file&nbsp;target-file.\n</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">0</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;&nbsp;&nbsp;exit(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">((in_fd</span><span style="color: #000000;">=</span><span style="color: #000000;">open(av[</span><span style="color: #000000;">1</span><span style="color: #000000;">],O_RDONLY))</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">Can't&nbsp;open&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">1</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">((out_fd</span><span style="color: #000000;">=</span><span style="color: #000000;">creat(av[</span><span style="color: #000000;">2</span><span style="color: #000000;">],COPYMODE))</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">Can't&nbsp;open&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">2</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">((n_chars</span><span style="color: #000000;">=</span><span style="color: #000000;">read(in_fd,buf,BUFFERSIZE))</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(write(out_fd,buf,n_chars)</span><span style="color: #000000;">!=</span><span style="color: #000000;">n_chars)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">Write&nbsp;error&nbsp;to&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">2</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(n_chars</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">Read&nbsp;error&nbsp;from&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">,av[</span><span style="color: #000000;">1</span><span style="color: #000000;">]);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(close(in_fd)</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">||</span><span style="color: #000000;">close(out_fd)</span><span style="color: #000000;">==-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br>&nbsp;&nbsp;&nbsp;&nbsp;oops(</span><span style="color: #000000;">"</span><span style="color: #000000;">Error&nbsp;closing&nbsp;files</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;">""</span><span style="color: #000000;">);<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br>}<br></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;oops(</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">s1,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">s2)<br>{<br>&nbsp;&nbsp;fprintf(stderr,</span><span style="color: #000000;">"</span><span style="color: #000000;">Error:%s</span><span style="color: #000000;">"</span><span style="color: #000000;">,s1);<br>&nbsp;&nbsp;perror(s2);<br>&nbsp;&nbsp;exit(</span><span style="color: #000000;">1</span><span style="color: #000000;">);<br>}<br></span></div>
<br>显然，在使用unix i/o的时候，你要更多地关注缓冲问题以提高效率，而stdio则不需要考虑。<br><br><br><br>
<br><br><br><img src ="http://www.blogjava.net/killme2008/aggbug/138651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-08-22 16:47 <a href="http://www.blogjava.net/killme2008/archive/2007/08/22/138651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言的5种存储类以及关键字volatile、restrict</title><link>http://www.blogjava.net/killme2008/archive/2007/08/04/134399.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 04 Aug 2007 07:34:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/08/04/134399.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/134399.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/08/04/134399.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/134399.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/134399.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 《C Primer Plus》读到12章，我的C语言复习进展的挺不错。这一章介绍存储类、连接和内存管理，可以说是重中之重。<br>C的5种存储类：<br><span style="font-weight: bold;">自动</span>——在一个代码块内（或在一个函数头部作为参量）声明的变量，无论有没有存储类修饰符auton，都属于自动存储类。该类具有自动存储时期、代码块的作用域和空链接(no linkage),如未初始化，它的值是不确定的（java要求局部变量必须初始化）<br><br><span style="font-weight: bold;">寄存器</span>——在一个代码块内（或在一个函数头部作为参量）使用修饰符register声明的变量属于寄存器存储类。该类与自动存储类相似，具有自动存储时期、代码块作用域和空连接，声明为register仅仅是一个请求，而非命令，因此变量仍然可能是普通的自动变量，但是仍然无法获取地址。。如果没有被初始化，它的值也是未定的。<br><br><span style="font-weight: bold;">静态、空链接</span>——在一个代码块内使用存储类修饰符static声明的局部变量属于静态空连接存储类。该类具有静态存储时期、代码块作用域和空链接，仅在编译时初始化一次。如未明确初始化，它的字节将被设定为0.<br><br><span style="font-weight: bold;">静态、外部链接</span>——在所有函数外部定义、未使用static修饰的变量属于静态、外部链接存储类。改类具有静态存储时期、文件作用域和外部链接，仅在编译时初始化一次。如未明确初始化，它的字节也被设定为0.<br><br style="font-weight: bold;"><span style="font-weight: bold;">静态、内部链接</span>——与静态、外部链接存储类不同的是，它使用static声明，也定义在所有函数外部，但是具有内部链接（仅能被与它在同一个文件的函数使用），仅在编译时初始化一次。如未明确初始化，它的字节也被设定为0.<br><br>两个关键字：volatile和restrict，两者都是为了方便编译器的优化。<br><br>volatile告诉编译器该被变量除了可被程序修改意外还可能被其他代理修改，因此，当要求使用volatile 声明的变量的值的时候，系统总是重新从它所在的内存读取数据，而不是使用寄存器中的缓存。比如<br>val1=x;<br>val2=x;<br>如果没有声明volatile，系统在给val2赋值的时候可能直接从寄存器读取x（假定聪明的编译器优化了），而不是从内存的初始位置，那么在两次赋值之间，x完全有可能被被某些编译器未知的因素更改（比如：操作系统、硬件或者其它线程等）。如果声明为volatile，编译器将不使用缓存，而是每次都从内存重新读取x。<br><br>而restrict是c99引入的，它只可以用于限定指针，并表明指针是访问一个数据对象的唯一且初始的方式，考虑下面的例子：<br>int ar[10];<br>int * restrict restar=(int *)malloc(10*sizeof(int));<br>int *par=ar;<br><br>这里说明restar是访问由malloc()分配的内存的唯一且初始的方式。par就不是了。<br>那么：<br>for(n=0;n&lt;10;n++)<br>{<br>&nbsp;&nbsp; par[n]+=5;<br>&nbsp;&nbsp; restar[n]+=5;<br>&nbsp;&nbsp; ar[n]*=2;<br>&nbsp;&nbsp; par[n]+=3;<br>&nbsp;&nbsp; restar[n]+=3;<br>}<br>因为restar是访问分配的内存的唯一且初始的方式，那么编译器可以将上述对restar的操作进行优化：<br>&nbsp;&nbsp; restar[n]+=8;<br><br>而par并不是访问数组ar的唯一方式，因此并不能进行下面的优化：<br>&nbsp;&nbsp; par[n]+=8;<br>因为在par[n]+=3前，ar[n]*=2进行了改变。使用了关键字restric，编译器就可以放心地进行优化了。这个关键字据说来源于古老的<font id="zoom" class="f14">FORTRAN。有兴趣的看看<a  href="http://www.chinaunix.net/jh/23/950178.html">这个</a>。</font><br><br><img src ="http://www.blogjava.net/killme2008/aggbug/134399.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-08-04 15:34 <a href="http://www.blogjava.net/killme2008/archive/2007/08/04/134399.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何设置一个基本的OpenLDAP Server(转载）</title><link>http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 14 Jul 2007 08:08:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/130281.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/130281.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/130281.html</trackback:ping><description><![CDATA[<p>如何设置一个基本的OpenLDAP Server <br>本文出自:http://www.linuxforum.net 作者:吴阿亭 Jephe wu (2001-09-04 15:00:01) </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一. 目的&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本文旨在介绍如何安装OpenLDAP并且设置一个公司内部的集中化的邮件地址薄服务器供客 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 户端查询。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基本上，OpenLDAPg还应用在其它许多方面，象集中化的用户帐号验证服务器,但邮件地址 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 薄查询是最常用的。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 二. 安装&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从<a href="http://www.openldap.org/">www.openldap.org</a>下载最新的openldap软件包，按照编译和安装的步骤，依次运行： </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #tar cvfz openldap-stable-20010524.tgz&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #cd openldap-2.0.11&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #./configure&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make depend&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make test&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #make install&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我的操作环境是redhat 6.1，如果没有遇到任何错误，最后默认安装LDAP后台程序slapd <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 到目录/usr/local/libexec;配置文件在目录/usr/local/etc/openldap/ 并且放各种 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OpenLDAP工具 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ldapadd,ldapdelete,ldapmodify,ldapmodrdn,ldappasswd,ldapsearch 在目录 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /usr/local/bin,运行时数据库在/usr/local/var/openldap-ldbm 。&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 三. 设置&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1) 更改配置文件/usr/local/etc/openldap/slapd.conf&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在include /usr/local/etc/openldap/schema/core.schema这行后面加上下面的行， <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 包括所有的方案。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/corba.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/cosine.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/inetorgperson.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/java.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/krb5-kdc.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/misc.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/nadf.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/nis.schema&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include /usr/local/etc/openldap/schema/openldap.schema&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2) 在文件slapd.conf的"ldbm database definitions"部分更改相应的 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; suffix,rootdn行如下&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; database ldbm&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; suffix "o=yourdomain,c=us"&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rootdn "cn=root,o=yourdomain,c=us"&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rootpw secret&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; directory /usr/local/var/openldap-ldbm&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有各种格式你可以用，这里我用的是o=yourdomain,c=us 说明你的公司域名和所在的国 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 家或地区&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rootdn的格式安装后默认为cn=Manager,这里改为root完全是自己的喜好,这样符合 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Unix/Linux中root具有最高权限的传统。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3) 现在可以启动slapd了，运行/usr/local/libexec/slapd 。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以考虑把/usr/local/bin and /usr/local/libexec加到搜索路径中，即加到 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /etc/profile&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 中的PATH行:&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PATH="$PATH:/usr/X11R6/bin:/usr/local/bin:/usr/local/libexec"&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这样下次登录后只需键入 slapd 。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4) 测试ldap server是否正常工作。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行下面的命令检查是否有相应的输出。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ldapsearch -x -b 'o=yourdomain,c=us' '(objectclass=*)'&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5) 编辑.ldif文本文件，用ldapadd添加记录进入LDAP数据库。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 文件内容如下：&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dn: o=yourdomain,c=us&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectclass: dcobject&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectclass: organization&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; o: yourdomain&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dc: yourdomain&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dn: cn=Jephe Wu,o=yourdomain,c=us&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objectclass: inetorgperson&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cn: Jephe Wu&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sn: Wu&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mail: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#106;&#101;&#112;&#104;&#101;&#95;&#119;&#117;&#64;&#121;&#111;&#117;&#114;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;">jephe_wu@yourdomain.com</a>&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......more users......&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 依次类推，添加每个人的记录进入该文件中，注意对象类型 inetorgperson 至少必须要 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有cn和sn&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ,这里我们用cn,sn,mail三项定义,这对我们的邮件地址薄功能来说已经足够。你还可以 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定义象&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mobile, homephone,pager......等等。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后用下面的命令添加上面的.ldif文件进入LDAP数据库&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ldapadd -x -D "cn=root,o=yourdomain,c=us" -w secret -f <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "yourldiffilename"&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注：上面的文件的第一部分"dn: o=yourdomain,c=us"是必须的，否则不能添加数据。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用你的公司的域名替换上面的"yourdomain"。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6) 设置Outlook Express, 允许用LDAP服务器查询邮件地址。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "工具/帐号/添加--目录服务"，填入你的服务器的IP地址或者主机全称域名，在下一个屏 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 幕中选yes以允许用目录服务来查询地址，最后在"目录服务"栏中选中刚才设置的项目击 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;属性/高级",在"搜索库"中填入&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "o=yourdomain,c=us" 。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Netscape请根据上面的信息设置相应的选项。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 四. 常见使用问题&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1) 能启动slapd 没有问题，但不能添加数据库，运行ldapadd添加时出错 "ldap_bind: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cannot contact LDAP Server" 。&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 答: 最可能的原因是在/etc/hosts中没有127.0.0.1 localhost项目。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2) 注意查询顺序: 如果在Outlook Express的地址薄中有内容，则检查地址时地址薄优 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先，如果在本地地址薄中找不到相应记录，然后再查询LDAP服务器。&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3) 用下面的命令确信客户端与LDAP服务器有通讯,在服务器运行下面的命令，然后在OE中 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 测试检查地址，你将会得到查询LDAP数据库的连接过程的输出。&nbsp; </p>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # tcpdump port 389&nbsp;
<br><img src ="http://www.blogjava.net/killme2008/aggbug/130281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-14 16:08 <a href="http://www.blogjava.net/killme2008/archive/2007/07/14/130281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>redhat9安装subversion手记</title><link>http://www.blogjava.net/killme2008/archive/2007/07/06/128569.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 06 Jul 2007 05:47:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/06/128569.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/128569.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/06/128569.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/128569.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/128569.html</trackback:ping><description><![CDATA[一、subversion最新版本已经到1.4.4，我安装的还是老版本，新版本也可以，BerkeleyDB和Apache的版本要与subversion要求的一致,安装所需文件及下载地址：<br>1) Subversion 1.2.3
<br><a href="http://subversion.tigris.org/downloads/subversion-1.2.3.tar.gz">http://subversion.tigris.org/downloads/subversion-1.2.3.tar.gz</a>
<br><br>2)Berkeley DB 4.4.20
<br><a href="http://downloads.sleepycat.com/db-4.4.20.tar.gz">http://downloads.sleepycat.com/db-4.4.20.tar.gz</a><br><br>3)Apache 2.0.54
<br><a href="http://apache.justdn.org/httpd/httpd-2.0.54.tar.gz">http://apache.justdn.org/httpd/httpd-2.0.54.tar.gz</a>
<br><br>二、以root用户登陆系统。<br><br>安装Apache<br>#tar -zxvf httpd-2.0.54.tar.gz<br>#cd httpd-2.0.54<br>#./configure --enable-dav --enable-so --enable-maintainer-mode<br>#make<br>#make install<br><br>安装Berkeley DB<br>#tar -zxvf db-4.4.20.NC.tar.gz<br>#cd db-4.4.20.NC/build_unix/<br>#../dist/configure --prefix=/usr/local/bdb<br>#make<br>#make install<br><br>安装Subversion<br>#tar -zxvf subversion-1.2.3.tar.gz<br>#cd subversion-1.2.3<br>#./configure --with-berkeley-db=/usr/local/bdb --with-apxs=/usr/local/apache2/bin/apxs<br>#make<br>#make install<br>
/* 你可以用以下命令检验subversion是否安装成功 */<br>#svnadmin --version
<br><br>三、新建一用户组svn，并建立一用户svnroot，用于管理svn的运行和维护<br>groupadd svn<br>useradd -G svn -m "the svn mananger" svnroot<br>passwd svnroot&nbsp; #设置svn密码<br><br>四、使用svnroot登录，执行下列操作<br>
# mkdir /home/svnroot/repository
<br><br>//创建仓库test<br>svnadmin create /home/svnroot/repository/test
<br><br>//导入项目到仓库中<br>svn import /home/yourproject file:///home/svnroot/repository/test &#8211;m "initial import"
<br>//改变权限，仅限svnroot拥有读、写、执行权利<br> chmod 700 /home/svnroot/repository
<br><br>五、root用户登录，设置Apache<br>//编辑httpd.conf<br>
# vi /usr/local/apache2/conf/httpd.conf
<br>&nbsp;&nbsp; 找到下面两行，如果没有，则添加：<br>&nbsp;&nbsp; LoadModule dav_svn_module modules/mod_dav_svn.so<br>
&nbsp; &nbsp;LoadModule authz_svn_module modules/mod_authz_svn.so<br>&nbsp;&nbsp; 接着上面再添加下面这段配置：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Location&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">svn</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;DAV&nbsp;svn<br>&nbsp;&nbsp;&nbsp;SVNParentPath&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">home</span><span style="color: #000000;">/</span><span style="color: #000000;">svnroot</span><span style="color: #000000;">/</span><span style="color: #000000;">repository</span><span style="color: #000000;">/</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;AuthzSVNAccessFile&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">home</span><span style="color: #000000;">/</span><span style="color: #000000;">svnroot</span><span style="color: #000000;">/</span><span style="color: #000000;">repository</span><span style="color: #000000;">/</span><span style="color: #000000;">authz.conf<br>&nbsp;&nbsp;&nbsp;AuthType&nbsp;Basic<br>&nbsp;&nbsp;&nbsp;AuthName&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">Subversion.svn</span><span style="color: #000000;">"</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;AuthUserFile&nbsp;</span><span style="color: #000000;">/</span><span style="color: #000000;">home</span><span style="color: #000000;">/</span><span style="color: #000000;">svnroot</span><span style="color: #000000;">/</span><span style="color: #000000;">repository</span><span style="color: #000000;">/</span><span style="color: #000000;">authfile<br>&nbsp;&nbsp;&nbsp;Require&nbsp;valid</span><span style="color: #000000;">-</span><span style="color: #000000;">user<br>&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">Location</span><span style="color: #000000;">&gt;</span></div>
<br>这段信息设置了/svn/目录需要认证才能访问，用户信息放在authfile，授权信息在authz.conf文件里。<br><br>六、权限管理，使用svnroot登录<br>1）增加用户，通过下列命令第一次增加时建立authfile文件，比如添加了一个用户dennis<br>htpasswd -c /home/svnroot/repository/authfile dennis<br>会提示你输入密码，以后再添加就不用-c选项了<br><br>2）权限分配,建立并编辑authz.conf<br>
# vi /home/svnroot/repository/authz.conf
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">[groups]&nbsp;&nbsp;#这个表示群组设置<br>admin</span><span style="color: #000000;">=</span><span style="color: #000000;">svnroot&nbsp;&nbsp;#svnroot是admin组<br>[test:</span><span style="color: #000000;">/</span><span style="color: #000000;">]&nbsp;&nbsp;#这表示，仓库test的根目录下的访问权限<br>dennis</span><span style="color: #000000;">=</span><span style="color: #000000;">rw&nbsp;#test仓库dennis用户具有读和写权限<br>[test2:</span><span style="color: #000000;">/</span><span style="color: #000000;">]&nbsp;#假设有test2仓库,它的访问权限<br>dennis</span><span style="color: #000000;">=</span><span style="color: #000000;">r&nbsp;&nbsp;#test2仓库dennis有读权限<br>[</span><span style="color: #000000;">/</span><span style="color: #000000;">] </span><span style="color: #008000;">#</span><span style="color: #008000;">这个表示在所有仓库的根目录下</span><span style="color: #008000;"><br></span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;r&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#这个表示对所有的用户都具有读权限<br>@admin</span><span style="color: #000000;">=</span><span style="color: #000000;">rw&nbsp;#admin组有读和写权限，比如svnroot<br><br></span></div>
<br>设置完成后，<br>重启apache<br>/usr/local/apache2/bin/apachectl restart<br>启动svn服务<br>#svnserve -d
<br><br>通过浏览器访问http://localhost/svn/test/，输入用户名密码，一切OK！<br><br>我只在我的windows机器上安装了subversion管理我的文档，这次在redhat9上的安装还算顺利，参考了下列文章：<br><a  href="http://lwb12915.bokee.com/viewdiary.15574585.html">《<strong>Linux 上安装 Subversion</strong>》</a><br><a  href="http://bbs.chinaunix.net/viewthread.php?tid=789349">《在Redhat9 Linux下安装，配置Subversion 1.3.1》</a><br>
&nbsp;<br><img src ="http://www.blogjava.net/killme2008/aggbug/128569.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-06 13:47 <a href="http://www.blogjava.net/killme2008/archive/2007/07/06/128569.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>迷上了shell编程，推荐好书一本</title><link>http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 05 Jul 2007 07:06:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/128347.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/128347.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/128347.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; shell编程，类似dos下的批处理文件，也有很大不同，shell更接近一门编程语言。最近迷上了这玩意，入门很容易，再深入就有点难了，写了几个简单的script处理日常命令，用着蛮爽，大大提高了我继续深入学习linux的积极性，待复习了C语言基础，准备读读《<a href="http://www.china-pub.com/computers/common/info.asp?id=23911" class="blue13" target="_blank">UNIX/LINUX编程实践教程</a>》。前天在emule下了《EveryDay Scripting With Ruby》,这本书在amazon评价很高，昨天一口气读了6章，非常不错。这本书适合ruby初学者，有一定ruby使用经验的也能有不少收获，书中介绍了4个常用的ruby编写的工具脚本，循序渐进、一步一步引你走入ruby的世界，有趣并实用；更可贵的是，这本书从第2个Project开始就以TDD的方式开发，让你充分体验TDD和Ruby结合带来的快感，强烈推荐准备开始学ruby的看看这本书。读这本书主要是想更深入地将ruby使用在我的日常工作中，熟识部分飞快翻过，总共也才250多页，花不了一两天功夫。这本书的源码从网站上下不了，封了来自中国大陆的IP，我将源码传上，有兴趣的看看。<br><br><a href="http://www.blogjava.net/Files/killme2008/bmsft-code.zip">《EveryDay Scripting With Ruby》书中源码</a><br><br>  <img src ="http://www.blogjava.net/killme2008/aggbug/128347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-05 15:06 <a href="http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vi常用命令</title><link>http://www.blogjava.net/killme2008/archive/2007/07/03/127735.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 03 Jul 2007 01:17:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/03/127735.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/127735.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/03/127735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/127735.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/127735.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; vi作为linux下的通用文本编辑工具，是经常使用到的。vi功能强大，命令也相当多，常用的摘记下：<br>1.设置显示行号&nbsp; :set nu<br>&nbsp; 取消显示行号&nbsp; :set nonu<br>2.光标移动到n行 nG<br>&nbsp; 光标移动到最后一行 G<br>3.光标移动到本行第n个字符 n空格<br>&nbsp; 光标移动到本行最后一个字符 $<br>4.向光标之后搜索字符串 /word<br>&nbsp; 向光标之前搜索字符串 ?word<br>5.从第n1行到第n2行搜索word1字符串，并替换为word2&nbsp;&nbsp; :n1,n2s/word1/word2/g<br>&nbsp; 逐个替换&nbsp;&nbsp; :n1,n2s/word1/word2/gc<br>&nbsp; 从第一行到最后一行进行替换应该是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :1,$s/word1/word2/g<br>6.向前翻页 ctr+f<br>&nbsp; 向后翻页 ctr+b<br>7.恢复修改操作 u<br>8.复制本行 yy<br>&nbsp; 本行往下n行进行复制 nyy<br>9.粘贴在光标以下的行 p<br>&nbsp; 粘贴在光标以上的行 P<br>10.向后删除一个字符 x<br>&nbsp;&nbsp; 向前删除一个字符 X<br>&nbsp;&nbsp; 向后删除n个字符 nx<br>11.保存&nbsp;&nbsp; :w<br>&nbsp;&nbsp; 退出&nbsp;&nbsp; :q<br>&nbsp;&nbsp; 强制退出不保存 :q!<br>&nbsp;&nbsp; 强制保存&nbsp;&nbsp; :w!<br>&nbsp;&nbsp; 保存并退出 :wq<br>&nbsp;&nbsp; 另存为&nbsp;&nbsp;&nbsp;&nbsp; :w otherfilename<br>&nbsp;&nbsp; <br><br><br><img src ="http://www.blogjava.net/killme2008/aggbug/127735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-03 09:17 <a href="http://www.blogjava.net/killme2008/archive/2007/07/03/127735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Erlang分布式在linux和windows上的注意事项</title><link>http://www.blogjava.net/killme2008/archive/2007/06/29/127099.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 29 Jun 2007 08:33:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/06/29/127099.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/127099.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/06/29/127099.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/127099.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/127099.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 没事做，就在两台机器间测试下Erlang分布式的例子，一个台是windowsXP，一台装的redHat9，没有详细的文档，自己摸索着搞成功了，记录下。<br><br>1.首先,分布式Erlang的实现提供了自有的安全机制来预防未经授权的Erlang系统访问。Erlang系统与别的机器进行交互时必须有同样的magic cookie,保存在一个称为.erlang.cookie的文件中，为了在两台不同机器间测试，需要编辑一份.erlang.cookie,内容随便，比如：<br>just_test<br><br>然后将这份文件拷贝到windows环境变量HOMEPATH所在的目录
，比如我的是C:\Documents and Settings\Admin，而linux拷贝到环境变量$HOME指向的目录，比如我这里是/root。特别注意一点，linux的.erlang.cookie文件需要设置权限为-r--------，也就是400，仅所有者可读：<br>chmod 400 .erlang.cookie<br><br>2.因为Erlang中的node名称是name@host，host是计算机名，因此在两台机器上都需要将计算机名和ip加进hosts文件，这个文件在linux下是在/etc/hosts，你可以用vi编辑如下：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">127.0</span><span style="color: #000000;">.</span><span style="color: #000000;">0.1</span><span style="color: #000000;">&nbsp;&nbsp;localhost&nbsp;localhost<br>x.x.x.x&nbsp;&nbsp;&nbsp;&nbsp;zane&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zane</span><span style="color: #008000;">&nbsp;&nbsp; #</span><span style="color: #008000;">windows机器的ip和计算机名</span></div>
，hosts在windows系统的C:\WINDOWS\system32\drivers\etc目录下，编辑：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">127.0</span><span style="color: #000000;">.</span><span style="color: #000000;">0.1</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;localhost<br>x.x.x.x&nbsp;&nbsp;&nbsp;dennis&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">linux机器的名称和ip</span></div>
<br>3.第三步，要启动节点，通过命令erl -sname 或者erl -name，在此之前需要启动epmd进程，它负责映射符号名到机器地址<br>在两个机器都执行：<br>epmd -daemon<br><br>4.至此配置完成，可以测试下Erlang分布式编程在不同的机器和系统之间了（比如《<a  href="http://www.blogjava.net/killme2008/archive/2007/06/15/124547.html">Erlang入门(三)--分布式编程</a>》中的ping pong例子），very cool!<br><br><img src ="http://www.blogjava.net/killme2008/aggbug/127099.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-06-29 16:33 <a href="http://www.blogjava.net/killme2008/archive/2007/06/29/127099.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>redhat9安装jdk5、ruby和Erlang备忘</title><link>http://www.blogjava.net/killme2008/archive/2007/06/28/126886.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 28 Jun 2007 10:08:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/06/28/126886.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/126886.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/06/28/126886.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/126886.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/126886.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 今天费了一个下午安装了redhat9，并且安装了需要使用的jdk5、netbean、ruby和Erlang。做个备忘。<br><br>一。安装jdk5<br>1.到sun的网站上下载jdk5与netbean5.5的捆绑版本，注意要linux平台的<br><br>2.比如下载到/root/目录下，执行<br>chmod 755 jdk-1_5_0_12-nb-5_5_1-linux-ml.bin<br>然后执行：<br>./jdk-1_5_0_12-nb-5_5_1-linux-ml.bin
<br>就会自动启动安装向导，一路选择确定下去就OK了。<br><br>3.设置环境变量，这时其实没有设置就可以启动netbean了，不过为了在终端执行，还是要设置下环境变量，使用vi编辑/etc/profile配置文件，在最后面加上：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">JAVA_HOME</span><span style="color: #000000;">=/</span><span style="color: #000000;">opt</span><span style="color: #000000;">/</span><span style="color: #000000;">jdk1.</span><span style="color: #000000;">5</span><span style="color: #000000;">.0_12<br>PATH</span><span style="color: #000000;">=/</span><span style="color: #000000;">opt</span><span style="color: #000000;">/</span><span style="color: #000000;">jdk1.</span><span style="color: #000000;">5</span><span style="color: #000000;">.0_12</span><span style="color: #000000;">/</span><span style="color: #000000;">bin:$PATH<br>CLASSPATH</span><span style="color: #000000;">=/</span><span style="color: #000000;">opt</span><span style="color: #000000;">/</span><span style="color: #000000;">jdk1.</span><span style="color: #000000;">5</span><span style="color: #000000;">.0_12</span><span style="color: #000000;">/</span><span style="color: #000000;">lib</span><span style="color: #000000;">/</span><span style="color: #000000;">dt.jar:</span><span style="color: #000000;">/</span><span style="color: #000000;">opt</span><span style="color: #000000;">/</span><span style="color: #000000;">jdk1.</span><span style="color: #000000;">5</span><span style="color: #000000;">.0_12</span><span style="color: #000000;">/</span><span style="color: #000000;">lib</span><span style="color: #000000;">/</span><span style="color: #000000;">tools.jar<br>export&nbsp;JAVA_HOME&nbsp;PATH&nbsp;CLASSPATH</span></div>
保存退出，reboot下就OK<br><br>二。安装ruby<br>1.到ruby-lang.org下载ruby-1.8.6.tar.gz
<br>2.解压缩并进入解压后的目录：<br>tar xzvf ruby-1.8.6.tar.gz
<br><font>cd ruby-1.8.6</font><br><br>3.默认是安装/usr/local目录下，可以通过下面的命令设置安装到/usr/local/ruby目录下：<br>/.configure -prefix=/usr/local/ruby<br><br>4.执行命令：make &amp;&amp; make install<br><br>5.再次编辑vi /etc/profile，修改我们在上面提到的PATH，把ruby的bin加进去：<br>PATH=/usr/local/ruby/bin:/opt/jdk1.5.0_12/bin:$PATH
<br><br>6.测试下是否正确安装，<br>ruby -version<br>ruby -e "puts 'hello'"<br><br>三、Erlang的安装<br><br>1.到Erlang.org下载最新版本的linux平台下的Erlang（源代码版本，需要自己编译），比如otp_src_R11B-5.tar.gz<br><br>2.解压缩，并进入解压后的目录：<br>tar zxvf otp_src_R11B-5.tar.gz
<br>cd otp_src_R11B-5
<br><br>3.build Erlang需要下列工具，确认你的linux版本有安装：<br>&nbsp;GNU make<br><br>&nbsp;GNU C compiler<br><br>&nbsp;Perl 5<br><br>&nbsp;OpenSSL<br><br>&nbsp;Sun Java jdk-1.2.2<br><br>&nbsp;X Windows<br><br>&nbsp;sed&nbsp; solaris平台需要<br><br>&nbsp;Flex 可选<br>
<br>4.安装过程，顺序执行下列命令，包括OTP在内都将被安装<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">1</span><span style="color: #000000;">)export&nbsp;LANG</span><span style="color: #000000;">=</span><span style="color: #000000;">C&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">如果是C&nbsp;Shell，执行setenv&nbsp;LANG&nbsp;C,linux一般是Bourne shell<br><br>
</span><span style="color: #008000;"><br></span><span style="color: #000000;"><br></span><span style="color: #000000;">2</span><span style="color: #000000;">).</span><span style="color: #000000;">/</span><span style="color: #000000;">configure<br><br></span><span style="color: #000000;">3</span><span style="color: #000000;">)make<br><br></span><span style="color: #000000;">4</span><span style="color: #000000;">)make&nbsp;install</span></div>
<br>5.确认安装正确，新开一个终端，执行erl进入Erlang shell<br><br>最后启动下ssh，允许防火墙通过ssh执行下面的命令，在windows上搞个putty<br>iptables -A INPUT -p tcp --sport 22 -j ACCEPT<br>
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
<br><br><br><br><br> <img src ="http://www.blogjava.net/killme2008/aggbug/126886.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-06-28 18:08 <a href="http://www.blogjava.net/killme2008/archive/2007/06/28/126886.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>