<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_kernel@hcy</title><subtitle type="text">不抛弃，不放弃，不哭泣。</subtitle><id>http://feed.cnblogs.com/blog/u/59556/rss</id><updated>2011-07-13T15:15:47Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/59556/rss"/><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2011/07/13/2105773.html</id><title type="text">DeaDBeeF MPRIS插件 v2.1</title><summary type="text">2.0版本实现了MPRIS v2的基本功能。插件单独编译，不再是补丁的形式。需要安装DeaDBeeF的头文件。编译安装的DeaDBeeF已经默认安装了头文件。如果使用的是编译好的静态文件，需要拷贝DeaDBeeF源码中的deadbeef.h文件到/usr/local/include/deadbeef/中。make之后不需要make install，拷贝目录.libs中的mpris.so.0.0.0文件到DeaDBeeF文件夹的plugin目录，并重命名位mpris.so即可。注意，拷贝的是动态库，不要拷贝另外几个链接文件。修正了一些bug。下载地址最新版的osd-lyrics可以自动检测播放器</summary><published>2011-07-13T15:02:00Z</published><updated>2011-07-13T15:02:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2011/07/13/2105773.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2011/07/13/2105773.html"/><content type="html">&lt;p&gt;2.0版本实现了MPRIS v2的基本功能。&lt;/p&gt;&lt;p&gt;插件单独编译，不再是补丁的形式。需要安装DeaDBeeF的头文件。编译安装的DeaDBeeF已经默认安装了头文件。如果使用的是编译好的静态文件，需要拷贝DeaDBeeF源码中的deadbeef.h文件到/usr/local/include/deadbeef/中。make之后不需要make install，拷贝目录.libs中的mpris.so.0.0.0文件到DeaDBeeF文件夹的plugin目录，并重命名位mpris.so即可。注意，拷贝的是动态库，不要拷贝另外几个链接文件。&lt;/p&gt;&lt;p&gt;修正了一些bug。&lt;/p&gt;&lt;p&gt;&lt;a href="http://code.google.com/p/deadbeef-mpris-plugin/downloads/list" target="_blank"&gt;下载地址&lt;/a&gt;&lt;/p&gt;&lt;p&gt;最新版的osd-lyrics可以自动检测播放器，&lt;span style="color: #800000;"&gt;不再&lt;/span&gt;需要先前的补丁。&lt;/p&gt;&lt;p&gt;v2.1:&lt;/p&gt;&lt;p&gt;1. Add configuration setting.&lt;/p&gt;&lt;p&gt;2. Fix bugs.&lt;/p&gt;&lt;p&gt;配置截图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/81339/2011071323142174.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;v2.0:&lt;br /&gt; 1. Implement interface org.mpris.MediaPlayer2&lt;br /&gt; 2. Implement interface org.mpris.MediaPlayer2.Player&lt;br /&gt; 3. Fix some bugs.&lt;/p&gt;&lt;p&gt;v1.5&lt;br /&gt; 1. Repaire the bug that Quit causes SEGFAULT&lt;br /&gt; 2. Repaire that AddTrack can not play the track that is added.&lt;br /&gt; 3. Implement PositionGet and PositionSet&lt;br /&gt; 4. Repaire other bugs.&lt;/p&gt;&lt;p&gt;v1.0&lt;br /&gt; 1. Implement most main interface of MPRIS v1.&lt;br /&gt; 2. DelTrack need the support of DeaDBeeF. We do not implement it.&lt;br /&gt; 3. Raise need the support of the gui. We do not implement it.&lt;br /&gt; 4. AddTrack can not play the track at once. The DeaDBeeF's plt_add_file function may have a bug.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/2105773.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2011/07/13/2105773.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2011/06/21/2085601.html</id><title type="text">连接DeaDBeeF和osd-lyrics</title><summary type="text">DeaDBeeF是linux下优秀的播放器，osd-lyrics可以在linux下完美的显示歌词。osd-lyrics通过DBus与播放器通信，实现同步显示歌词。DeaDBeeF没有提供DBus接口，因此无法与osd-lyrics进行通信，也就无法通过osd-lyrics同步显示歌词。要想将两者连接起来，可以通过下面的方法：首先，让DeaDBeeF支持DBus接口。可以通过安装MPRIS插件实现。MPRIS是Media Player Remote Interfacing Specification，是Linux下媒体播放器交互的一个协议，具体可参考这里和这里。osd-lyrics使用MPRIS</summary><published>2011-06-20T16:04:00Z</published><updated>2011-06-20T16:04:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2011/06/21/2085601.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2011/06/21/2085601.html"/><content type="html">&lt;p&gt;&lt;a target="_blank" href="http://deadbeef.sourceforge.net/"&gt;DeaDBeeF&lt;/a&gt;是linux下优秀的播放器，&lt;a target="_blank" href="http://code.google.com/p/osd-lyrics/"&gt;osd-lyrics&lt;/a&gt;可以在linux下完美的显示歌词。&lt;/p&gt;&lt;p&gt;osd-lyrics通过DBus与播放器通信，实现同步显示歌词。DeaDBeeF没有提供DBus接口，因此无法与osd-lyrics进行通信，也就无法通过osd-lyrics同步显示歌词。&lt;/p&gt;&lt;p&gt;要想将两者连接起来，可以通过下面的方法：&lt;/p&gt;&lt;p&gt;首先，让DeaDBeeF支持DBus接口。可以通过安装&lt;a target="_blank" href="http://code.google.com/p/deadbeef-mpris-plugin/downloads/detail?name=mpris.so&amp;amp;can=2&amp;amp;q=#makechanges"&gt;MPRIS插件&lt;/a&gt;实现。MPRIS是&lt;meta content="text/html; charset=utf-8" http-equiv="content-type" /&gt;Media Player Remote Interfacing Specification，是Linux下媒体播放器交互的一个协议，具体可参考&lt;a target="_blank" href="http://xmms2.org/wiki/MPRIS"&gt;这里&lt;/a&gt;和&lt;a target="_blank" href="http://www.mpris.org/2.1/spec/"&gt;这里&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;osd-lyrics使用MPRIS协议同播放器进行通信。安装插件之后，还要对osd-lyrics打补丁，让其支持DeaDBeeF。&lt;/p&gt;&lt;p&gt;首先下载&lt;a target="_blank" href="http://code.google.com/p/deadbeef-mpris-plugin/downloads/detail?name=deadbeef.patch&amp;amp;can=2&amp;amp;q=#makechanges"&gt;补丁&lt;/a&gt;。然后下载osd-lyrics的&lt;a target="_blank" href="http://code.google.com/p/osd-lyrics/downloads/detail?name=osdlyrics-0.4.0.tar.gz&amp;amp;can=2&amp;amp;q="&gt;源码&lt;/a&gt;。使用git打上补丁。编译安装。&lt;/p&gt;&lt;p&gt;这样就可以了。&lt;/p&gt;&lt;p&gt;先运行DeaDBeeF，再运行osd-lyrics。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/81339/2011062100001844.png" /&gt;&lt;/p&gt;&lt;p&gt;也可以在osd-lyrics中设置自动启动DeaDBeeF。如图&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/81339/2011062100034680.png" /&gt;&lt;/p&gt;&lt;p&gt;然后只需要启动osd-lyrics，osd-lyrics会自动启动DeaDBeeF。&lt;/p&gt;&lt;p&gt;目前两个补丁均已提交到官方。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/2085601.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2011/06/21/2085601.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2011/05/18/2050421.html</id><title type="text">redis源码分析（2）dict哈希词典</title><summary type="text">redis的哈希字典和其他字典的功能一样，用于根据key值快速的查找对应的value（这不废话么。。。）。redis的哈希字典使用的是哈希的方法（依旧是废话）。redis的字典有一种独特的rehash的方法，这是本文介绍的重点。首先，dict包含四个结构体。关系如图所示： 结构体dict表示一个字典。每个字典中含有两个哈希表，ht[0]和ht[1]。哈希表用结构体dictht表示。哈希表采用链表法来处理冲突。结构体dictht的成员变量size表示table的长度，通常是2的幂次。sizemask等于size减1，用于计算哈希值对应的桶。used表示table的所有桶中的dictEntry实</summary><published>2011-05-18T12:30:00Z</published><updated>2011-05-18T12:30:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/18/2050421.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/18/2050421.html"/><content type="html">&lt;meta content="text/html; charset=utf-8" http-equiv="content-type" /&gt;&lt;div&gt;&lt;span&gt;redis的哈希字典和其他字典的功能一样，用于根据key值快速的查找对应的value（这不废话么。。。）。redis的哈希字典使用的是哈希的方法（依旧是废话）。redis的字典有一种独特的rehash的方法，这是本文介绍的重点。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;首先，dict包含四个结构体。关系如图所&lt;/span&gt;&lt;span&gt;示：&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/81339/2011052111471677.png" /&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;结构体dict表示一个字典。每个字典中含有两个哈希表，ht[0]和ht[1]。哈希表用结构体dictht表示。哈希表采用链表法来处理冲突。结构体dictht的成员变量size表示table的长度，通常是2的幂次。sizemask等于size减1，用于计算哈希值对应的桶。used表示table的所有桶中的dictEntry实例的个数，也就是table对应的所有链表的总长度。键值对用结构体dictEnty封装，键值对会组成一个链表。结构体dictType包含有一些函数指针，这些函数指针保存的函数用于对字典中的数据进行处理，比如dup键或值，比较键，折构键值等。最重要的是hashFunction函数，很明显，这时对键值求hash值的函数。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;dict提供对字符串和整数的哈希函数。字符串哈希函数使用的是Bernstein方法，整数是Thomas Wang的方法。两个方法都简单，没什么可讲的。至于这两种方法的优劣，读者可自行google。Bernstein方法笔者在不同的程序见过很多次，想必应该是很好的方法。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;下面介绍一下dict的rehash。通常情况下，所有的数据都是存在放dict的ht[0]中，ht[1]只在rehash的时候使用。dict进行rehash的时候，将ht[0]中的所有数据rehash到ht[1]中。然后将ht[1]赋值给ht[0]，并清空ht[1]。dict的rehash并不是一次性完成的，而是分成多步。在调用dict的一些操作函数时，如add，find等，都会判断是否需要执行一步rehash并视情况而执行。每一步的大小分为两种，一种是在一步中将ht[0]的table中的一个元素，也就是一个哈希桶，如table[2]，所对应的链表中的所有元素进行rehash，另一种是在一步中执行一段固定的时间，当时间到达后，暂停rehash。这两种方法对应的函数分别是_dictRehashStep和dictRehashMilliseconds。这两个函数调用dictRehash进行实际的rehash。dictRehash的代码如下：&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Performs N steps of incremental rehashing. Returns 1 if there are still&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #008000;"&gt;* keys to move from the old to the new hash table, otherwise 0 is returned.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #008000;"&gt;* Note that a rehashing step consists in moving a bucket (that may have more&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #008000;"&gt;* thank one key as we use chaining) from the old to the new hash table. &lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #008000;"&gt;进行N步增量重哈希。&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #008000;"&gt;如果没有完成旧哈希表中所有值的重哈希，返回1，否则返回0。&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #008000;"&gt;每一步重哈希移动一整个哈希桶。&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; dictRehash(dict &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;d, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; n) {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;dictIsRehashing(d)) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;(n&lt;/span&gt;&lt;span style="color: #000000;"&gt;--&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;       dictEntry &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;de, &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;nextde;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Check if we already rehashed the whole table... &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].used &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; &lt;span style="color: #000000;"&gt;           zfree(d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].table);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt; &lt;span style="color: #000000;"&gt;           d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt; &lt;span style="color: #000000;"&gt;           _dictReset(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;]);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt; &lt;span style="color: #000000;"&gt;           d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;rehashidx &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt; &lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Note that rehashidx can't overflow as we are sure there are more&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * elements because ht[0].used != 0 &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;(d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].table[d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;rehashidx] &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; NULL) d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;rehashidx&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt; &lt;span style="color: #000000;"&gt;       de &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].table[d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;rehashidx];&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Move all the keys in this bucket from the old to the new hash HT &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;(de) {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt; &lt;span style="color: #000000;"&gt;           unsigned &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; h;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt; &lt;span style="color: #000000;"&gt;           nextde &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; de&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;next;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;30&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Get the index in the new hash table &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;31&lt;/span&gt; &lt;span style="color: #000000;"&gt;           h &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; dictHashKey(d, de&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;key) &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;].sizemask;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;32&lt;/span&gt; &lt;span style="color: #000000;"&gt;           de&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;next &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;].table[h];&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;33&lt;/span&gt; &lt;span style="color: #000000;"&gt;           d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;].table[h] &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; de;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;34&lt;/span&gt; &lt;span style="color: #000000;"&gt;           d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].used&lt;/span&gt;&lt;span style="color: #000000;"&gt;--&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;35&lt;/span&gt; &lt;span style="color: #000000;"&gt;           d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;].used&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;36&lt;/span&gt; &lt;span style="color: #000000;"&gt;           de &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; nextde;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;37&lt;/span&gt; &lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;38&lt;/span&gt; &lt;span style="color: #000000;"&gt;       d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].table[d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;rehashidx] &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; NULL;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;39&lt;/span&gt; &lt;span style="color: #000000;"&gt;       d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;rehashidx&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;40&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;41&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;42&lt;/span&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;结构体dict中的rehashidx变量表示当前需要rehash的桶的下标，也就是table的下标。如果rehashidx为-1，表示当前没有进行rehash。宏dictIsRehashing通过rehashidx判断是否在进行rehash。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;dictRehash函数执行n步rehash。每步中，首先判断是否已经完成了rehash，判断的标准就是ht[0]的used为0。ht[0]的used为0说明table中所有的链表都是空的，那么所有的元素都已经移动到ht[1]中。此时，将ht[1]赋值给ht[0]，清空ht[1]。将rehashidx赋值为-1表明rehash结束。如果rehash没有结束，那么，查找ht[0]中下一个非空的桶。将这个桶中的所有数据rehash到ht[1]中。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;那么，什么时候开始rehash？首先说明一下rehash是干吗的。从前面的代码中可以看出，所谓的rehash，不管你分不分步，无非就是把数据从ht[0]中取出，重新计算hash值，然后放到ht[1]对应的桶中，然后把ht[1]变成ht[0]。读者们可以看看dictAdd代码，rehash的步骤和把数据放入ht[0]的过程没什么区别。这就比较蛋疼了，搞毛啊，穷折腾么？显然不是！在rehash的时候，ht[0]和ht[1]的table的长度是不一样的！ht[1]的table长度是ht[0]的table长度的2倍。数据对应与ht[1]的桶的下标和在ht[0]的桶的下标是不一样的。前面介绍的那两种哈希方法计算出来的哈希值通常会很大，要远大于table的长度。因此，这个哈希值与table长度进行与运算的时候，得到的值就不一样。说白了，在ht[0]中，桶下表是哈希值的低m位，在ht[1]中就是低m+1位，两个值自然极有可能不一样了。所以，rehash之后，ht[1]中链表的长度大大减少。随着数据的增加，ht[0]中的链表会越来越长，这会造成查找效率降低。为了降低链表的长度，要加大桶的长度。在dictAdd函数中，调用_dictKeyIndex函数。_dictKeyIndex函数查找新的key所对应的桶的下标。_dictKeyIndex函数调用_dictExpandIfNeeded函数判断是否需要扩充ht[0]的table。_dictExpandIfNeeded函数调用dictExpand函数进行实际的扩充。dictExpand函数的代码如下：&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Expand or create the hashtable &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; dictExpand(dict &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;d, unsigned &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt; size)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #000000;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #000000;"&gt;   dictht n; &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; the new hashtable &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;   unsigned &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt; realsize &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _dictNextPower(size);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; the size is invalid if it is smaller than the number of&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #008000;"&gt;    * elements already inside the hashtable &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (dictIsRehashing(d) &lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt; d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].used &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; size)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; DICT_ERR;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Allocate the new hashtable and initialize all pointers to NULL &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #000000;"&gt;   n.size &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; realsize;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;span style="color: #000000;"&gt;   n.sizemask &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; realsize&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #000000;"&gt;   n.table &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; zcalloc(realsize&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(dictEntry&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; &lt;span style="color: #000000;"&gt;   n.used &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Is this the first initialization? If so it's not really a rehashing&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt; &lt;span style="color: #008000;"&gt;    * we just set the first hash table so that it can accept keys. &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;20&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;].table &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; NULL) {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;21&lt;/span&gt; &lt;span style="color: #000000;"&gt;       d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; n;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;22&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; DICT_OK;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;23&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;24&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;25&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Prepare a second hash table for incremental rehashing &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;26&lt;/span&gt; &lt;span style="color: #000000;"&gt;   d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ht[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; n;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;27&lt;/span&gt; &lt;span style="color: #000000;"&gt;   d&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;rehashidx &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;28&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; DICT_OK;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;29&lt;/span&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;span&gt;dictExpand首先调用_dictNextPower函数来计算比size大的下一个2的次幂。然后，分配一个新的哈希表。如果此时ht[0]的table是NULL，那么说明这是第一次调用dictExpand函数，也就是第一次向dict插入数据，直接将新的哈希表赋值给ht[0]。如果不是，那么新的哈希表赋值给ht[1]。注意，此时rehashidx被赋值为0，这就表明下面要开始rehash了。在dictAdd，dictFind和dictGenericDelete中分别在开始的时候调用了_dictRehashStep 。这三个函数也是被频繁调用的函数。&lt;/span&gt;&lt;/p&gt;&lt;meta http-equiv="content-type" content="text/html; charset=utf-8" /&gt;&lt;div&gt;&lt;p id="internal-source-marker_0.35558950155973434"&gt;&lt;span&gt;由于rehash不是一次完成的，因此，在对dict进行操作的时候，数据会分布在ht[0]和ht[1]中。对于dictFind，dictDelete等函数，遍历两个表即可。但是，对于dictAdd函数，需要一些特殊的操作。如果此时在进行rehash，那么数据应该被插到ht[1]中，而不是ht[0]中。如果插到ht[0]中，倘若此时还没有对数据所在的桶rehash，那么随后的rehash中也会把数据移动到ht[1]中。如果此时已经对其所在的桶rehash过了，那么在dictExpand的第一个while语句中会出现数组越界的情况，很有可能造成程序崩溃。dictAdd调用_dictKeyIndex来计算key对应的桶的下。如果处在rehash中，得到的是在ht[1]中的下标，否则是在ht[0]中的下标。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;redis的dict提供了一个迭代器。由于rehash的存在，如果不加保护，某写数据可能会被返回两次。比如，一个数据e在ht[0]中，此时还没有对e所在的桶进行rehash，迭代器访问完e之后，恰好对e所在的桶进行了rehash。那么，当迭代器遍历ht[1]中的时候，e会被再次返回。为了防止这种现象，redis限制一旦有迭代器对dict进行访问，那么rehash就会暂停，直到不再有迭代器访问字典。结构体dict中的iterators用于记录当前正在访问字典的迭代器。可以有多个迭代器同时访问字典。迭代器返回的数据可以被删除。迭代器通过记录数据的指针和其在链表中的后继数据的指针实现对删除的支持。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;redis限制有迭代器访问的时候禁止rehash，但是，在rehash的过程中迭代器可以随时对字典进行遍历。一旦有迭代器遍历字典，rehash就会暂停直到遍历结束。迭代器也会根据当前是否在进行rehahs来判断是否需要访问ht[1]。&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/2050421.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/18/2050421.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2011/05/15/2046963.html</id><title type="text">redis源码分析（1）内存管理</title><summary type="text">神马是redis？redis是一个开源的，牛B的键值数据库。由于键可以被保存为字符串，列表，哈希表，集合和有序集合，redis有时候也被称作数据结构服务器。这句蹩脚的翻译来自redis官网的介绍。想进一步了解的可以去它官网瞅瞅。目前redis已归入vmware门下。下面，切入正题。redis是用c编写的。用c编写的程序都要面临一个很重要也很头疼的问题----内存管理。很多时候，不当的内存管理会成为万恶之源。。。redis的内存管理只有两个文件zmalloc.c和zmalloc.h。zmalloc.h的内容如下： 1 void *zmalloc(size_t size); 2 void *z</summary><published>2011-05-15T08:55:00Z</published><updated>2011-05-15T08:55:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/15/2046963.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/15/2046963.html"/><content type="html">&lt;meta http-equiv="content-type" content="text/html; charset=utf-8" /&gt;&lt;div&gt;&lt;p id="internal-source-marker_0.05522271292284131"&gt;&lt;span&gt;神马是redis？redis是一个开源的，牛B的键值数据库。由于键可以被保存为字符串，列表，哈希表，集合和有序集合，redis有时候也被称作数据结构服务器。这句蹩脚的翻译来自&lt;/span&gt;&lt;a href="http://redis.io/"&gt;&lt;span&gt;redis官网&lt;/span&gt;&lt;/a&gt;&lt;span&gt;的介绍。想进一步了解的可以去它官网瞅瞅。目前redis已归入vmware门下。&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;下面，切入正题。redis是用c编写的。用c编写的程序都要面临一个很重要也很头疼的问题----内存管理。很多时候，不当的内存管理会成为万恶之源。。。redis的内存管理只有两个文件zmalloc.c和zmalloc.h。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;zmalloc.h的内容如下：&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;zmalloc(size_t size);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;zcalloc(size_t size);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;zrealloc(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;ptr, size_t size);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; zfree(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;ptr);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;zstrdup(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;s);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;size_t zmalloc_used_memory(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; zmalloc_enable_thread_safeness(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;float&lt;/span&gt;&lt;span style="color: #000000;"&gt; zmalloc_get_fragmentation_ratio(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;size_t zmalloc_get_rss(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;size_t zmalloc_allocations_for_size(size_t size);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; ZMALLOC_MAX_ALLOC_STAT 256&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;就这么几行。这是redis的内存管理接口。zmalloc,zcalloc,zrealloc和zfree分别对应c库中的malloc,calloc,realloc和free。zstrdup用于生成一个字符串的拷贝。后面的几个函数用于获取内存使用信息，后面会详细介绍。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;在看zmalloc.c的源码之前，先看看redis是怎样管理内存的。redis为了方便内存的管理，在分配一块内存之后，会将这块内存的大小存入内存块的头部。如下图。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;real_ptr &amp;nbsp;&amp;nbsp;&amp;nbsp;ret_ptr&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; | &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;V &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;V&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-------------------------------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;| &amp;nbsp;&amp;nbsp;&amp;nbsp;size &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;| &amp;nbsp;memory block &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;/span&gt;&lt;br /&gt;&lt;span&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;--------------------------------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;real_ptr是redis调用malloc后返回的指针。redis将内存块的大小size存入头部，size所占据的内存大小是已知的，为size_t类型的长度，然后返回ret_ptr。当需要释放内存的时候，ret_ptr被传给内存管理程序。通过ret_ptr，程序可以很容易的算出real_ptr的值，然后将real_ptr传给free释放内存。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;redis会记录所有的内存分配情况。redis定义一个数组，这个数组的长度为ZMALLOC_MAX_ALLOC_STAT。数组的每一个元素代表当前程序所分配的内存块的个数，且内存块的大小为该元素的下标。在程序中，这个数组为zmalloc_allocations。zmalloc_allocations[16]代表已经分配的长度为16bytes的内存块的个数。zmalloc.c中有一个静态变量used_memory用来记录当前分配的内存总大小。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;下面开始分析代码。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;首先是定义宏PREFIX_SIZE：&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;#ifdef HAVE_MALLOC_SIZE&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; PREFIX_SIZE (0)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#if&lt;/span&gt;&lt;span style="color: #000000;"&gt; defined(__sun)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; PREFIX_SIZE (sizeof(long long))&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; PREFIX_SIZE (sizeof(size_t))&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;8&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endif&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;9&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endif&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;如果定义了HAVE_MALLOC_SIZE，那么PREFIX_SIZE就为0。这里，HAVE_MALLOC_SIZE用来确定系统是否有函数malloc_size。这个HAVE_MALLOC_SIZE宏在config.h中定义，如下：&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Use tcmalloc's malloc_size() when available.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #008000;"&gt;* When tcmalloc is used, native OSX malloc_size() may never be used because&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #008000;"&gt;* this expects a different allocation scheme. Therefore, *exclusively* use&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #008000;"&gt;* either tcmalloc or OSX's malloc_size()! &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#if&lt;/span&gt;&lt;span style="color: #000000;"&gt; defined(USE_TCMALLOC)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;#include &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;google&lt;/span&gt;&lt;span style="color: #000000;"&gt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;tcmalloc.h&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#if&lt;/span&gt;&lt;span style="color: #000000;"&gt; TC_VERSION_MAJOR &amp;gt;= 1 &amp;amp;&amp;amp; TC_VERSION_MINOR &amp;gt;= 6&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; HAVE_MALLOC_SIZE 1&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; redis_malloc_size(p) tc_malloc_size(p)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endif&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#elif&lt;/span&gt;&lt;span style="color: #000000;"&gt; defined(__APPLE__)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;#include &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;malloc&lt;/span&gt;&lt;span style="color: #000000;"&gt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt;malloc.h&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; HAVE_MALLOC_SIZE 1&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; redis_malloc_size(p) malloc_size(p)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endif&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;如果使用google的tcmalloc库，那么，redis_malloc_size就对应与tcmalloc库的tc_malloc_size函数。如果是在apple的mac上编译，那么redis_malloc_size就对应与malloc_size。redis_malloc_size的功能是获得参数p所指向的内存块的大小。tcmalloc库在google的&lt;/span&gt;&lt;a href="http://code.google.com/p/google-perftools/"&gt;&lt;span&gt;google-perftools&lt;/span&gt;&lt;/a&gt;&lt;span&gt;库中，据说这个库在内存管理的效率上很惊艳。不过这个库是c++写的，而redis是c写的，两者揉一起还是有点不给力阿。。。&lt;/span&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;如果没有malloc_size函数，那么在Solaris系统上，用long long类型的长度来定义PREFIX_SIZE，其他系统为size_t的长度。&lt;/span&gt;&lt;/p&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;接着，定义下面这些宏。这些宏的作用是如果使用tcmalloc库，那么将库中的分配函数对应到标准库上。后面的函数可直接使用标准库函数的名称。在更换库的时候不需要更改。&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt; &lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Explicitly override malloc/free etc when using tcmalloc. &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#if&lt;/span&gt;&lt;span style="color: #000000;"&gt; defined(USE_TCMALLOC)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; malloc(size) tc_malloc(size)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; calloc(count,size) tc_calloc(count,size)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; realloc(ptr,size) tc_realloc(ptr,size)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; free(ptr) tc_free(ptr)&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endif&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;下面的两个宏用于更新zmalloc_allocations数组。update_zmalloc_stat_alloc用于在分配内存的时候更新已分配大小，update_zmalloc_stat_free用于在释放内存的时候删除对应的记录。&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; update_zmalloc_stat_alloc(__n,__size) do { \&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #000000;"&gt;   size_t _n &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (__n); \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #000000;"&gt;   size_t _stat_slot &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (__size &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; ZMALLOC_MAX_ALLOC_STAT) &lt;/span&gt;&lt;span style="color: #000000;"&gt;?&lt;/span&gt;&lt;span style="color: #000000;"&gt; __size : ZMALLOC_MAX_ALLOC_STAT; \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (_n&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)) _n &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;(_n&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)); \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (zmalloc_thread_safe) { \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;       pthread_mutex_lock(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;used_memory_mutex);  \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;       used_memory &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _n; \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #000000;"&gt;       zmalloc_allocations[_stat_slot]&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;; \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;       pthread_mutex_unlock(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;used_memory_mutex); \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;   } &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt; { \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;       used_memory &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _n; \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;       zmalloc_allocations[_stat_slot]&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;; \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #000000;"&gt;   } \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;span style="color: #000000;"&gt;} &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;update_zmalloc_stat_alloc的第一个参数__n是从系统那实际获得的内存大小，第二个参数是程序请求的内存大小。update_zmalloc_stat_alloc首先判断程序请求的内存大小在zmalloc_allocations数组中对应的下标。如果内存大小大于zmalloc_allocations数组的长度-1，那么其对应的下标是最后一个。然后，将实际分配的内存大小对齐为long类型长度的整数倍（malloc通常会考虑对齐问题，实际分配的内存大小也会因对齐而有所出入，后文会介绍）。最后，在used_memory记录实际分配的大小，在zmalloc_allocations对应位置加一。这里如果设置为线程安全，那么在记录之前要对两个静态变量加锁。&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;#define&lt;/span&gt;&lt;span style="color: #000000;"&gt; update_zmalloc_stat_free(__n) do { \&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #000000;"&gt;   size_t _n &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (__n); \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (_n&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)) _n &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;(_n&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;long&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)); \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (zmalloc_thread_safe) { \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;       pthread_mutex_lock(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;used_memory_mutex);  \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;       used_memory &lt;/span&gt;&lt;span style="color: #000000;"&gt;-=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _n; \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;       pthread_mutex_unlock(&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;used_memory_mutex); \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #000000;"&gt;   } &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt; { \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;       used_memory &lt;/span&gt;&lt;span style="color: #000000;"&gt;-=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _n; \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;   } \&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;} &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt;(&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;update_zmalloc_stat_free和update_zmalloc_stat_alloc差不多，但仅仅减少了used_memory的值。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;对于zmalloc,zalloc,zrealloc和zfree这几个函数，仅仅是对标准库的函数的简单的封装。所做的工作除了调用标准库（也可能是tcmalloc库）的函数分配内存外，就是对每次分配和释放内存做合适的记录。如果系统中有malloc_size函数，那么直接调用前面的那两个宏，没什么可讲的。如果没有malloc_size函数，那么需要在所分配的内存头部的PREFIX_SIZE大小的区域内，记录内存块的大小。代码很简单，就一句：&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;((size_t&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;)ptr) &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; size;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;现将ptr转换成size_t类型的指针，然后将size的值赋给其指向的内存。笔者感觉没有必要在前面定义PREFIX_SIZE的时候区分系统，因为这里直接硬编码了内存大小的类型为size_t。前面的宏判断有点多此一举了。这里的size是返回的内存区域的大小，不包括保存大小的头部。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;读取内存块大小需要两步：&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt; &lt;span style="color: #000000;"&gt;realptr &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;)ptr&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt;PREFIX_SIZE;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;oldsize &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;((size_t&lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;)realptr);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;程序传进来的是ret_ptr，通过减去PREFIX_SIZE得到real_ptr。从real_ptr所指向的内存中读取大小即可。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;其余的几个函数也很直接，没什么好说的。最后讲一讲zmalloc_get_rss()函数。这个函数用来获取进程的RSS。神马是RSS？google reader那个？显然不是。。。全称为Resident Set Size，指实际使用物理内存（包含共享库占用的内存）。在linux系统中，可以通过读取/proc/pid/stat文件获取，pid为当前进程的进程号。读取到的不是byte数，而是内存页数。通过系统调用sysconf(_SC_PAGESIZE)可以获得当前系统的内存页大小。Unix系统貌似可以直接通过task_info直接获取，比linux系统简单的多。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;获得进程的RSS后，可以计算目前数据的内存碎片大小，直接用rss除以used_memory。rss包含进程的所有内存使用，包括代码，共享库，堆栈等。但是由于通常情况下redis在内存中数据的量要远远大于这些数据所占用的内存，因此这个简单的计算还是比较准确的。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;这里有一个问题，程序都是用多少内存就分配多少内存，哪来的内存碎片？其实，当调用malloc的时候，malloc并不是严格按照参数的值来分配内存。比如，程序只请求一个byte的内存，malloc不会就只分配一个byte，通常，基于内存对齐等方面的考虑，malloc会分配4个byte。这样，如果程序中大量请求1byte内存，那么实际使用的是所请求的4倍。malloc进行小内存分配是很浪费的。所以，碎片就在这里产生了。&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;总的来说，redis的内存管理简单粗暴，没有神马复杂的引用计数等技术。但是，很多时候，简单的往往是高效且合理的。redis内存的中数据通常会是几个G，这个方法快速，统计结果也很精确。&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/2046963.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/15/2046963.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2011/05/05/2037137.html</id><title type="text">Lighttpd1.4.20源码分析之状态机（4） 错误处理和连接关闭</title><summary type="text">Lighttpd所要处理的错误分为两种。一种是http协议规定的错误，如404错误。另一种就是服务器运行过程中的错误，如write错误。 对于http协议规定的错误，lighttpd返回相应的错误提示文件。其实对于lighttpd而言，这不算错误。在返回错误提示文件后，相当于顺利的完成了一次请求，只是结果和客户端想要的不一样而已。 对于服务器运行中的错误，状态机会直接进入CON_STATE_ERROR状态。大部分的情况下，这种错误都是由客户端提前断开连接所造成的。比如你不停的刷新页面，在你刷新的时候，前一次的连接没有完成，但被浏览器强行断开，这时，服务器就会出现连接错误。对于服务器而言，刷新.</summary><published>2011-05-04T16:03:00Z</published><updated>2011-05-04T16:03:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/05/2037137.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/05/2037137.html"/><content type="html">&lt;p&gt;Lighttpd所要处理的错误分为两种。一种是http协议规定的错误，如404错误。另一种就是服务器运行过程中的错误，如write错误。&lt;/p&gt;&lt;p&gt;对于http协议规定的错误，lighttpd返回相应的错误提示文件。其实对于lighttpd而言，这不算错误。在返回错误提示文件后，相当于顺利的完成了一次请求，只是结果和客户端想要的不一样而已。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于服务器运行中的错误，状态机会直接进入CON_STATE_ERROR状态。大部分的情况下，这种错误都是由客户端提前断开连接所造成的。比如你不停的刷新页面，在你刷新的时候，前一次的连接没有完成，但被浏览器强行断开，这时，服务器就会出现连接错误。对于服务器而言，刷新前后的两个连接是不相干的。因此，服务器在接收后一个连接的时候仍然会继续处理前一次的连接。而这时前一次的连接已经断开，这就产生了连接错误。&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;进入CON_STATE_ERROR状态后，如果前面的处理已经得到了结果。也就是http_status不为空。那么调用plugins_call_handle_request_done告诉插件请求处理结束。&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;            * even if the connection was drop we still have to write it to the&lt;br /&gt;            * access log&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status)&lt;br /&gt;           {&lt;br /&gt;               plugins_call_handle_request_done(srv, con);&lt;br /&gt;           }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接着，如果使用了ssl，关闭ssl连接。关闭ssl连接的代码很长，但大部分都是错误处理。再朝后，如果连接模式不是DIRECT，调用plugins_call_handle_connection_close告诉插件连接已经关闭。到此，如果连接没有设置keep_alive，那么关闭连接并做一些清理工作之后就直接结束状态机的运行了。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果设置了keep_alive，此时可能是服务器首先关闭连接的。调用shutdown关闭连接的读和写。如果关闭没有出错，状态机进入CON_STATE_CLOSE状态。&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * close the connection&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #008000;"&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; ((con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;keep_alive &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; shutdown(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;fd, SHUT_WR)))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;close_timeout_ts &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; srv&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;cur_ts;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;               connection_set_state(srv, con, CON_STATE_CLOSE);、&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (srv&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;srvconf.log_state_handling)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;               {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;                   log_error_write(srv, __FILE__, __LINE__, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;sd&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;                                   &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;shutdown for fd&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;fd);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;               }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #000000;"&gt;           }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面的代码中有这么一句：con-&amp;gt;close_timeout_ts = srv-&amp;gt;cur_ts;将close_timeout_ts的值设置为当前时间。这时干吗用的？不着急，继续完后走。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 进入CON_STATE_ERROR状态之后，如果是keep_alive，且缓冲区中有数据还没读，那么把这些数据读出来然后直接丢弃。如果没有数据可读，直接设置close_time_ts为0。接着执行下面的代码：&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;1&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (srv&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;cur_ts &lt;/span&gt;&lt;span style="color: #000000;"&gt;-&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;close_timeout_ts &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;2&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;3&lt;/span&gt; &lt;span style="color: #000000;"&gt;               connection_close(srv, con);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;4&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (srv&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;srvconf.log_state_handling)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;5&lt;/span&gt; &lt;span style="color: #000000;"&gt;               {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;6&lt;/span&gt; &lt;span style="color: #000000;"&gt;                   log_error_write(srv, __FILE__, __LINE__, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;sd&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;connection closed for fd&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;fd);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;7&lt;/span&gt; &lt;span style="color: #000000;"&gt;               }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;8&lt;/span&gt; &lt;span style="color: #000000;"&gt;           }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 除了输出日志，这段代码就是调用了connection_close。connection_close做最后的清理工作，包括调用close，将对应的connection放回缓冲池中等。前面刚刚说过，在CON_STATE_ERROR中设置了close_time_ts为cur_ts。在出了CON_STATE_ERROR后，进入CON_STATE_CLOSE，这段时间cur_ts是没有改变的。如果前面的代码中测试缓冲区中没有数据可读，此时const_time_ts是等于cur_ts。也就是说状态机还在CON_CLOSE_STATE这个状态，然后就退出了状态机的大while循环。服务器进入了connection_state_mechine最后面的那个switch语句。在这个switch中，连接对应的fd被加入到fdevent系统中并监听读入事件。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个时候连接都已经关闭了还有什么能读的啊？别急！细心的读者应该注意到了，到这个时候，服务器仅仅是对连接调用了shutdown函数，没有调用close函数。首先说一下shutdown和close的区别。close作用在socket fd上和作用在其他fd上的效果差不多，都是减少引用计数，当计数为0的时候释放资源，关闭连接。shutdown函数则是针对socket fd的专门函数。shutdown可以关闭socket连接的一个方向，也就是可以只关闭写或者只关闭读（socket连接是全双工的）。另外一个区别就是，如果连接是多个进程共享的，那么在一个进程中调用close不影响其他进程使用连接，因为仅仅是引用计数减少1。而如果一个进程调用了shutdown ，那么，不管三七二十一，系统直接咔嚓掉这个连接，其他进程看到的也是关闭的连接。还有一个区别，调用了close的socket fd，read，write函数不能再从这个fd上读取或发送数据。而调用了shutdown的socket fd，如果缓冲区中还有数据可读，由于此时对于进程而言，socket fd没有关闭，read依然可以从这个fd读数据。由于shutdown仅仅是关闭了连接，不会进行资源的释放，要想释放连接占用的资源，还必须调用close函数。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 对于keep_alive的连接，关闭是服务器主动发起的。根据TCP协议，主动发起关闭的一方，其连接将进入TIME_WAIT状态，此时连接所占用的资源没有释放。更悲剧的是要在这个状态待很长时间。。。（默认4分钟）对于高并发的服务器，如果服务器主动关闭大量连接，那么服务器的资源很快就会被用光（端口，内存等），新的连接将无法建立。关于这个TIME_WAIT状态，读者可自行google之，网上有很多介绍的文章以及处理办法。虽然这个TIME_WAIT状态看似会给我们带来很多麻烦，但是，如果没有这个状态我们会更麻烦。。。《UNIX Network Programming Volum1》这本神作中有详细的介绍，有兴趣的读者可以看看。既然麻烦不可避免，那么就尽量将麻烦的影响见到最低。连接占用的资源主要就是端口和内存。端口是没办法的，占用就占用了。但是，内存还是可以节省一点的。前面说了，shutdown之后，我们依然可以把缓冲区的数据读出来。那么，我们把这些数据读出来以后，缓冲区所占用的内存就可以释放了。从而降低了内存的使用。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在CON_STATE_CLOSE中，下面的代码把缓冲区的数据读了出来：&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt; 1&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (ioctl(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;fd, FIONREAD, &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;b))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 2&lt;/span&gt; &lt;span style="color: #000000;"&gt;          {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 3&lt;/span&gt; &lt;span style="color: #000000;"&gt;              log_error_write(srv, __FILE__, __LINE__, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ss&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;ioctl() failed&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, strerror(errno));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 4&lt;/span&gt; &lt;span style="color: #000000;"&gt;          }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 5&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (b &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 6&lt;/span&gt; &lt;span style="color: #000000;"&gt;          {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 7&lt;/span&gt; &lt;span style="color: #000000;"&gt;              &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt; buf[&lt;/span&gt;&lt;span style="color: #800080;"&gt;1024&lt;/span&gt;&lt;span style="color: #000000;"&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 8&lt;/span&gt; &lt;span style="color: #000000;"&gt;              log_error_write(srv, __FILE__, __LINE__, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;sdd&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;CLOSE-read()&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;fd, b);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 9&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt; &lt;span style="color: #000000;"&gt;             read(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;fd, buf, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;sizeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(buf));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt; &lt;span style="color: #000000;"&gt;          }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt; &lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt; &lt;span style="color: #008000;"&gt;                * nothing to read&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt; &lt;span style="color: #008000;"&gt;                &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt; &lt;span style="color: #000000;"&gt;             con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;close_timeout_ts &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;19&lt;/span&gt; &lt;span style="color: #000000;"&gt;          }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果没有数据可读，那么设置close_timeout_ts会使连接在后面的代码中被关闭。如果有数据可读，读取数据之后，连接依然处在CON_STATE_CLOSE状态中，连接对应的fd被加入到fdevent系统中监听读事件。如果缓冲区中还有数据，那么在connection_handle_fdevent 函数中，也有上面这段代码，再次运行之。如果数据没有读完，服务器将会重复的在connection_handle_fdevent函数中运行上述代码直到数据读完。随着close_timeout_ts被设置为0，在下次joblist的调度中，状态机将会关闭连接，清理所有资源。&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 至此，连接正式关闭。之所以这么麻烦，就是由于连接是服务器主动关闭的，会有TIME_WAIT状态的问题。这样处理仅仅在内存上有了一些节省。但是具体效果怎样，这要看系统内核是如何处理连接缓冲区的。如果各位读者了解这方面的内容，还请不吝赐教！&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 另外，shutdown之后内核中的缓冲区到底会怎样笔者并不是很确定。上面的内容只是根据代码的推断。还是那句话，如果给为读者有什么高见，还行不吝赐教啊。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/2037137.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/05/2037137.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2011/05/01/2033928.html</id><title type="text">Linux下有趣的命令</title><summary type="text">yes：输出一串y，有时可以用来对付很多y/n选择的应用 。输出很多。。。banner：打印字符标题，就是用字符拼出大字来 ,最好把窗口最大化，否则可能显示不全。ddate：把日历转成什么其他历，Today is Sweetmorn, the 63rd day of Discord in the YOLD 3173fortune：输出一句话，内容有很多种，据说有唐诗宋词（有唐诗宋词的是fortune-zh，安装完之后，fortune会随机的输出唐诗宋词或英文名言。）cal 9 1752：打印日历，不过那一个月的有问题，原因如下：ppop 写道 "sniper在其BLOG中写道：今天偶</summary><published>2011-05-01T08:09:00Z</published><updated>2011-05-01T08:09:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/01/2033928.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/01/2033928.html"/><content type="html">&lt;div class="entry-content"&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;yes&lt;/strong&gt;：输出一串y，有时可以用来对付很多y/n选择的应用 。输出很多。。。&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;banner&lt;/strong&gt;：打印字符标题，就是用字符拼出大字来 ,最好把窗口最大化，否则可能显示不全。&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ddate&lt;/strong&gt;：把日历转成什么其他历，Today is Sweetmorn, the 63rd day of Discord in the YOLD 3173&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;fortun&lt;/strong&gt;&lt;strong&gt;e&lt;/strong&gt;：输出一句话，内容有很多种，据说有唐诗宋词（有唐诗宋词的是fortune-zh，安装完之后，fortune会随机的输出唐诗宋词或英文名言。）&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;cal 9 1752&lt;/strong&gt;：打印日历，不过那一个月的有问题，原因如下：&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;ppop 写道 "sniper在其BLOG中写道：今天偶然在一个博客上看到关于Linux中日期隐含一段历史的介绍，很好奇，按照别人介绍的方法试验了下。 CODE: cal 9 1752 就可以看到： September 1752 S M Tu W Th F S 1 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 发现1752年9月2日的后面竟然是14日，原因如下： 1582年2月，罗马教廷要求从1582 年10月中减去10天，因此1852 年10月4日后面紧跟着就是15日。 在意大利、西班牙等国家都这样处理了。其他天主教国家也很快跟着这么做了，但是新教国家不愿意修改，而且希腊等东正教国家直到20世纪初才修改，所以这个改革在英国及其殖民地（包括美国）在1752年9月才被执行。这样1752 年9月2日后面跟着的就是1752 年9月14日。 但在Windows下，由于电脑的日期无法调回那个时候（1980再往前就是2099），于是调用VC的月历控件写个万年历，1752 年9月却很正常，看来这是个一段要靠Linux才能了解的历史。"&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;tac&lt;/strong&gt;：concatenate and print files in reverse，把文件的行反过来打印（cat 反过来写的。。试试就知道）&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ptx&lt;/strong&gt; - produce a permuted index of file contents，生成索引？不知道&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;xev&lt;/strong&gt;：打印即时的X事件&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;xeyes&lt;/strong&gt;：出眼睛那个，进X第一都要玩玩吧&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;cowsay/cowthink&lt;/strong&gt;：打印一个小牛（或其他动物）说话或想像，内容可自定&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;factor&lt;/strong&gt;：分解因数&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;shred&lt;/strong&gt;：覆盖文件让它不能再读 (传说中的文件粉碎机。。)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这两个搞笑：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;apt-get moo&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(__)&lt;br /&gt;(oo)&lt;br /&gt;/------\/&lt;br /&gt;/ |&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;br /&gt;*&amp;nbsp; /\---/\&lt;br /&gt;~~&amp;nbsp;&amp;nbsp; ~~&lt;br /&gt;...."Have you mooed today?"...&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;apt-build moo&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(__)&amp;nbsp;&amp;nbsp;&amp;nbsp; ~&lt;br /&gt;(oo)&amp;nbsp;&amp;nbsp; /&lt;br /&gt;_____\/___/&lt;br /&gt;/&amp;nbsp; /\ / /&lt;br /&gt;~&amp;nbsp; /&amp;nbsp; * /&lt;br /&gt;/ ___/&lt;br /&gt;*----/\&lt;br /&gt;/&amp;nbsp; \&lt;br /&gt;/&amp;nbsp;&amp;nbsp; /&lt;br /&gt;~&amp;nbsp;&amp;nbsp;&amp;nbsp; ~&lt;br /&gt;..."Have you danced today? Discow!"...&lt;br /&gt;试试下面的一串：&lt;br /&gt;aptitude moo&lt;br /&gt;aptitude -v moo&lt;br /&gt;aptitude -vv moo&lt;br /&gt;aptitude -vvv moo&lt;br /&gt;aptitude -vvvv moo&lt;br /&gt;aptitude -vvvvv moo&lt;br /&gt;aptitude -vvvvvv moo&lt;br /&gt;aptitude -vvvvvvv moo&lt;br /&gt;aptitude -vvvvvvvvvvvvvvvvvvvv moo&lt;/p&gt;&lt;p&gt;还有make love，翻成中文倒不好玩了&lt;/p&gt;&lt;p&gt;还有人说who am i，不够有意思 。可以试试who is sb。&lt;br /&gt;其实who am后面跟任何东西都是一样的。。。&lt;/p&gt;&lt;p&gt;有人说 rm -fr /，还有dd if=/dev/zero of=/dev/mem，这就太坏了，没事别试，尤其是root敢死队不要试 这个危险&lt;/p&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/2033928.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2011/05/01/2033928.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2011/04/30/2033654.html</id><title type="text">Lighttpd1.4.20源码分析之状态机（3）返回response</title><summary type="text">好久没顾这个了，最近比较清闲，重新拾掇一下，有始有终。 回到正题，前一篇介绍完了请求的处理，先面lighttpd将会把处理的结果返回给客户端。状态机进入CON_STATE_RESPONST_START。在这个状态中，服务器主要的工作在函数connection_handle_write_prepare。这个函数不算复杂，主要是根据客户端请求的method来设置response的headers，其实就是设置“Content-Length”的值。下面是函数代码，做了一些删减： 1 static int connection_handle_write_prepare(server * srv, co.</summary><published>2011-04-30T15:43:00Z</published><updated>2011-04-30T15:43:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2011/04/30/2033654.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2011/04/30/2033654.html"/><content type="html">&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;" id="internal-source-marker_0.17984627729287184"&gt;好久没顾这个了，最近比较清闲，重新拾掇一下，有始有终。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;回到正题，前一篇介绍完了请求的处理，先面lighttpd将会把处理的结果返回给客户端。状态机进入CON_STATE_RESPONST_START。在这个状态中，服务器主要的工作在函数&lt;/span&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;connection_handle_write_prepare。这个函数不算复杂，主要是根据客户端请求的method来设置response的headers，其实就是设置&amp;ldquo;Content-Length&amp;rdquo;的值。&lt;/span&gt;下面是函数代码，做了一些删减：&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;&amp;nbsp;&lt;/span&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #008080;"&gt;  1&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; connection_handle_write_prepare(server &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt; srv, connection &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt; con)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  2&lt;/span&gt; &lt;span style="color: #000000;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  3&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;mode &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; DIRECT)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  4&lt;/span&gt; &lt;span style="color: #000000;"&gt;   {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  5&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  6&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * static files&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  7&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  8&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;request.http_method)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;  9&lt;/span&gt; &lt;span style="color: #000000;"&gt;       {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 10&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_GET:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 11&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_POST:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 12&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_HEAD:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 13&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_PUT:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 14&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_MKCOL:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 15&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_DELETE:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 16&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_COPY:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 17&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_MOVE:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 18&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_PROPFIND:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 19&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_PROPPATCH:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 20&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_LOCK:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 21&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_UNLOCK:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 22&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 23&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_OPTIONS:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 24&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 25&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * 400 is coming from the request-parser BEFORE uri.path is set&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 26&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * 403 is from the response handler when noone else catched it&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 27&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 28&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; ((&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;200&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 29&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;uri.path&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;used &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;uri.path&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;ptr[&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #800000;"&gt;*&lt;/span&gt;&lt;span style="color: #800000;"&gt;'&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 30&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 31&lt;/span&gt; &lt;span style="color: #000000;"&gt;               response_header_insert(srv, con, CONST_STR_LEN(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Allow&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;),&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 32&lt;/span&gt; &lt;span style="color: #000000;"&gt;                  CONST_STR_LEN(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;OPTIONS, GET, HEAD, POST&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 33&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 34&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;response.transfer_encoding &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;~&lt;/span&gt;&lt;span style="color: #000000;"&gt;HTTP_TRANSFER_ENCODING_CHUNKED;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 35&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;parsed_response &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;~&lt;/span&gt;&lt;span style="color: #000000;"&gt;HTTP_CONTENT_LENGTH;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 36&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 37&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;200&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 38&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;file_finished &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 39&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 40&lt;/span&gt; &lt;span style="color: #000000;"&gt;               chunkqueue_reset(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;write_queue);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 41&lt;/span&gt; &lt;span style="color: #000000;"&gt;           }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 42&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 43&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;default&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 44&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 45&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 46&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;400&lt;/span&gt;&lt;span style="color: #000000;"&gt;:            &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; bad request &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 47&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;414&lt;/span&gt;&lt;span style="color: #000000;"&gt;:            &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; overload request header &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 48&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;505&lt;/span&gt;&lt;span style="color: #000000;"&gt;:            &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; unknown protocol &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 49&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;207&lt;/span&gt;&lt;span style="color: #000000;"&gt;:            &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; this was webdav &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 50&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 51&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;default&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 52&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;501&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 53&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 54&lt;/span&gt; &lt;span style="color: #000000;"&gt;           }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 55&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 56&lt;/span&gt; &lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 57&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 58&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 59&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 60&lt;/span&gt; &lt;span style="color: #000000;"&gt;   {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 61&lt;/span&gt; &lt;span style="color: #000000;"&gt;       con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;403&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 62&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 63&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 64&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;switch&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 65&lt;/span&gt; &lt;span style="color: #000000;"&gt;   {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 66&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;204&lt;/span&gt;&lt;span style="color: #000000;"&gt;:                    &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; class: header only &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 67&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;205&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 68&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;case&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;304&lt;/span&gt;&lt;span style="color: #000000;"&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 69&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 70&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * disable chunked encoding again as we have no body&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 71&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 72&lt;/span&gt; &lt;span style="color: #000000;"&gt;       con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;response.transfer_encoding &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;~&lt;/span&gt;&lt;span style="color: #000000;"&gt;HTTP_TRANSFER_ENCODING_CHUNKED;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 73&lt;/span&gt; &lt;span style="color: #000000;"&gt;       con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;parsed_response &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;~&lt;/span&gt;&lt;span style="color: #000000;"&gt;HTTP_CONTENT_LENGTH;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 74&lt;/span&gt; &lt;span style="color: #000000;"&gt;       chunkqueue_reset(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;write_queue);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 75&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 76&lt;/span&gt; &lt;span style="color: #000000;"&gt;       con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;file_finished &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 77&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 78&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;default&lt;/span&gt;&lt;span style="color: #000000;"&gt;:                    &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; class: header + body &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 79&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;mode &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; DIRECT)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 80&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 81&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 82&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 83&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * only custom body for 4xx and 5xx&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 84&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 85&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;400&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;600&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 86&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 87&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 88&lt;/span&gt; &lt;span style="color: #000000;"&gt;       con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;file_finished &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 89&lt;/span&gt; &lt;span style="color: #000000;"&gt;       buffer_reset(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;physical.path);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 90&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 91&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 92&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * try to send static errorfile&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 93&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 94&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;buffer_is_empty(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;conf.errorfile_prefix))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 95&lt;/span&gt; &lt;span style="color: #000000;"&gt;       {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 96&lt;/span&gt; &lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;设置对应的错误提示文件&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 97&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 98&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt; 99&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;file_finished)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;100&lt;/span&gt; &lt;span style="color: #000000;"&gt;       {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;101&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;没有对应的错误提示文件，设置默认错误提示。&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;102&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;103&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;break&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;104&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;105&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;106&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;file_finished)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;107&lt;/span&gt; &lt;span style="color: #000000;"&gt;   {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;108&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;109&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * we have all the content and chunked encoding is not used, set a&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;110&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * content-length&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;111&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;112&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; ((&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;parsed_response &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_CONTENT_LENGTH)) &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;113&lt;/span&gt; &lt;span style="color: #000000;"&gt;           (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;response.transfer_encoding &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_TRANSFER_ENCODING_CHUNKED) &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;114&lt;/span&gt; &lt;span style="color: #000000;"&gt;       {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;115&lt;/span&gt; &lt;span style="color: #000000;"&gt;           off_t qlen &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; chunkqueue_length(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;write_queue);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;116&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;*&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;117&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * The Content-Length header only can be sent if we have content:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;118&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * - HEAD doesn't have a content-body (but have a content-length)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;119&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * - 1xx, 204 and 304 don't have a content-body (RFC 2616 Section 4.3)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;120&lt;/span&gt; &lt;span style="color: #008000;"&gt;            *&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;121&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * Otherwise generate a Content-Length header as chunked encoding is not&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;122&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * available&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;123&lt;/span&gt; &lt;span style="color: #008000;"&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;124&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; ((con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;100&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;200&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;125&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;204&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;http_status &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;304&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;126&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;127&lt;/span&gt; &lt;span style="color: #000000;"&gt;               data_string &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;ds;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;128&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;129&lt;/span&gt; &lt;span style="color: #008000;"&gt;                * no Content-Body, no Content-Length&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;130&lt;/span&gt; &lt;span style="color: #008000;"&gt;                &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;131&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (NULL &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (ds &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (data_string &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt;) array_get_element(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;response.headers, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Content-Length&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;132&lt;/span&gt; &lt;span style="color: #000000;"&gt;               {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;133&lt;/span&gt; &lt;span style="color: #000000;"&gt;                   buffer_reset(ds&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;value);    &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt; Headers with empty values&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;134&lt;/span&gt; &lt;span style="color: #008000;"&gt;                                                * are ignored for output &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;135&lt;/span&gt; &lt;span style="color: #000000;"&gt;               }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;136&lt;/span&gt; &lt;span style="color: #000000;"&gt;           }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;137&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (qlen &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt; con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;request.http_method &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_HEAD)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;138&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;139&lt;/span&gt; &lt;span style="color: #000000;"&gt;               &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;140&lt;/span&gt; &lt;span style="color: #008000;"&gt;                * qlen = 0 is important for Redirects (301, ...) as they MAY&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;141&lt;/span&gt; &lt;span style="color: #008000;"&gt;                * have a content. Browsers are waiting for a Content otherwise&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;142&lt;/span&gt; &lt;span style="color: #008000;"&gt;                &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;143&lt;/span&gt; &lt;span style="color: #000000;"&gt;               buffer_copy_off_t(srv&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;tmp_buf, qlen);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;144&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;145&lt;/span&gt; &lt;span style="color: #000000;"&gt;               response_header_overwrite(srv, con, CONST_STR_LEN(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Content-Length&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;), CONST_BUF_LEN(srv&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;tmp_buf));&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;146&lt;/span&gt; &lt;span style="color: #000000;"&gt;           }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;147&lt;/span&gt; &lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;148&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;149&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;150&lt;/span&gt; &lt;span style="color: #000000;"&gt;   {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;151&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;*&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;152&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * the file isn't finished yet, but we have all headers&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;153&lt;/span&gt; &lt;span style="color: #008000;"&gt;        *&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;154&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * to get keep-alive we either need:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;155&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;156&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * - Transfer-Encoding: chunked (HTTP/1.1)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;157&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;158&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;159&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (((con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;parsed_response &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_CONTENT_LENGTH) &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;160&lt;/span&gt; &lt;span style="color: #000000;"&gt;           ((con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;response.transfer_encoding &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_TRANSFER_ENCODING_CHUNKED) &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;))&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;161&lt;/span&gt; &lt;span style="color: #000000;"&gt;       {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;162&lt;/span&gt; &lt;span style="color: #000000;"&gt;           con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;keep_alive &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;163&lt;/span&gt; &lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;164&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;165&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;*&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;166&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * if the backend sent a Connection: close, follow the wish&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;167&lt;/span&gt; &lt;span style="color: #008000;"&gt;        *&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;168&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * NOTE: if the backend sent Connection: Keep-Alive, but no Content-Length, we&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;169&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * will close the connection. That's fine. We can always decide the close&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;170&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * the connection&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;171&lt;/span&gt; &lt;span style="color: #008000;"&gt;        *&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;172&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * FIXME: to be nice we should remove the Connection: ...&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;173&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;174&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;parsed_response &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_CONNECTION)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;175&lt;/span&gt; &lt;span style="color: #000000;"&gt;       {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;176&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;177&lt;/span&gt; &lt;span style="color: #008000;"&gt;            * a subrequest disable keep-alive although the client wanted it&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;178&lt;/span&gt; &lt;span style="color: #008000;"&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;179&lt;/span&gt; &lt;span style="color: #000000;"&gt;           &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;keep_alive &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;response.keep_alive)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;180&lt;/span&gt; &lt;span style="color: #000000;"&gt;           {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;181&lt;/span&gt; &lt;span style="color: #000000;"&gt;               con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;keep_alive &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;182&lt;/span&gt; &lt;span style="color: #000000;"&gt;           }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;183&lt;/span&gt; &lt;span style="color: #000000;"&gt;       }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;184&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;185&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;186&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;request.http_method &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; HTTP_METHOD_HEAD)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;187&lt;/span&gt; &lt;span style="color: #000000;"&gt;   {&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;188&lt;/span&gt; &lt;span style="color: #000000;"&gt;       &lt;/span&gt;&lt;span style="color: #008000;"&gt;/*&lt;/span&gt;&lt;span style="color: #008000;"&gt;*&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;189&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * a HEAD request has the same as a GET&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;190&lt;/span&gt; &lt;span style="color: #008000;"&gt;        * without the content&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;191&lt;/span&gt; &lt;span style="color: #008000;"&gt;        &lt;/span&gt;&lt;span style="color: #008000;"&gt;*/&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;192&lt;/span&gt; &lt;span style="color: #000000;"&gt;       con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;file_finished &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;193&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;194&lt;/span&gt; &lt;span style="color: #000000;"&gt;       chunkqueue_reset(con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;write_queue);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;195&lt;/span&gt; &lt;span style="color: #000000;"&gt;       con&lt;/span&gt;&lt;span style="color: #000000;"&gt;-&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;response.transfer_encoding &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;amp;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;~&lt;/span&gt;&lt;span style="color: #000000;"&gt;HTTP_TRANSFER_ENCODING_CHUNKED;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;196&lt;/span&gt; &lt;span style="color: #000000;"&gt;   }&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;197&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;198&lt;/span&gt; &lt;span style="color: #000000;"&gt;   http_response_write_header(srv, con);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;199&lt;/span&gt; &lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;200&lt;/span&gt; &lt;span style="color: #000000;"&gt;   &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;201&lt;/span&gt; &lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;首先，该函数判断连接的模式（mode）是否是DIRECT，如果是，说明连接没有经过插件处理，是由服务器自身处理的。这里判断连接的请求method，如果是OPTION，则设置Allow的值。同时清空write_queue，因为没有数据需要返回。&lt;/span&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt; 接着，在下面这个switch语句中，比较http_status的值，如果为204,205,304,说明服务器不需要给客户端返回文件，仅仅返回response中headers及其之前的部分。这里和前面处理OPTION方法都设置con-&amp;gt;file_finished为1。file_finished用来标记客户端请求的静态文件是否已经发送完了（这个file_finished的含义比较模糊，目前还没搞清楚是表示文件发送完毕，还是要发送的文件设置完毕可以发送。。。也有可能是个bug。。。如果各位读者有什么高见，还望不吝赐教！）。这两处都不需要给客户端发送文件，因此将其设置为1，发送程序将直接跳过文件的发送。switch的default分支处理4xx错误，返回相应的错误提示文件。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;出了switch语句之后，接着是一个if判断file_finished的值。如果值为1，说明不需要给客户端返回文件数据。对于1xx，204和304状态，将Content-Length设置为空值。如果method是HEAD，那么服务器可能需要返回一些数据，这时候要设置对应的Content-Length。如果file_finished的值为0，那么要设置一下keep_alive的值。在connection_handle_write_prepare函数的最后，调用http_response_write_header将headers写入write_queue，等待返回给客户端。如果一切顺利，那么状态机进入CON_STATE_WRITE。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;由于数据可能不会一次写完，尤其是发送大文件的时候。因此，在CON_STATE_WRITE状态中首先判断write_queue时候为空，也就是有没有数据还没有发送。同时判断连接是否可写。如果有数据且可写，那么调用connection_handle_write发送数据。如果没有数据可写或者连接不可写，那么会退出switch(con-&amp;gt;state)这个语句。同时，由于状态机状态没有发生改变，switch后面的if语句使得服务器退出了大while循环，进入循环后面的小switch(con-&amp;gt;state)语句。这个switch语句在前面已经介绍过。在这里，进入CON_STATE_WRITE分支，如果有数据可写且连接可写且没有达到流量限制，那么在fdevent中注册这个连接，否则，删除这个连接。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;下面我们进入connection_handle_write函数，看看有数据可写且连接可写的情况。connection_handle_write函数会首先在switch语句中调用network_write_chunkqueue函数。顾名思义，这个函数就是将write_queue中的数据写回给客户端的。函数network_write_chunkqueue首先判断当前连接的流量是否超过了限制，如果是，则不发送任何数据，直接将连接加到作业列表（joblist）中，让其他连接发送数据。如果没有超限，那么首先设置TCP_CORK选项。这个选项可以将多个write调用的数据一起发送，提高发送效率。有关TCP_CORK的内容读者可自行google之。接下来就是调用srv-&amp;gt;network_backend_wirte()函数进行真正的写数据了。这个函数的真正定义有多个，在network_*.c文件中。服务器在network.c的network_init函数中会根据当前的运行环境设置不同的值。为了提高服务器的效率，不同的OS会提供一些不同的方法，提高发送文件的速度。通过传统的先read在write的方法，需要4次数据拷贝（从磁盘到内核缓冲区，从内核缓冲区到用户缓冲区，从用户缓冲区到网络接口的内核缓冲区，最后，从网络接口的内核缓冲区到网络设备缓冲区。），OS会提供一些特定的方法来减少拷贝的次数，具体读者可以google&amp;ldquo;直接IO&amp;rdquo;，有不少介绍这个的文章。为了充分利用这些方法来提高服务器的性能，lighttpd在不同的OS上都会去使用这些特定的接口，因此就需要多个network_backend_wirte函数的实现。这些实现基本上大同小异，因此这里只介绍network_write.c中的实现。函数的主体是个大循环，遍历所有的chunk。如果chunk的类型是MEM_CHUNK，那么这个chunk中的数据是在内存中的，直接调用write或者windows下的send函数发送数据。如果是FILE_CHUNK类型，说明这个chunk表示的是一个文件，那么如果运行环境有mmap函数，就使用mmap映射文件并发送，否则就read在write。如果这个chunk发送完了，那么继续发送下一个chunk。如果没有发送完（chunk_finished=0），那么退出循环，接着也就退出了这个函数。服务器这时返回到network_write_chunkqueue中，下面做一些统计工作，再一次检查该连接的流量是否超限。最后服务器返回到connection_handle_write中。如果network_write_chunkqueue返回-1，表示服务器出错。状态机进入CON_STATE_ERROR。如果返回-2，则客户端关闭连接，状态机也进入CON_STATE_ERROR。返回0表示发送完毕，进入下一个状态。返回1说明数据没有发送完，标记is_wirtable为0。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;从connection_handler_write函数返回后，如果数据没有发送完毕，那么状态机还在&lt;br class="kix-line-break" /&gt;CON_STATE_WRITE状态，接着连接被加到fdevent系统中，等待下一次数据发送。重复上述过程知道发送完毕或出错。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;如果数据发送完毕，状态机进入CON_STATE_RESPONSE_END状态。在这个状态中，服务器首先调用plugins_call_handle_request_done通知所有插件连接处理完毕。然后判断是否保持连接，如果保持，将状态机设置为CON_STATE_REQUEST_START。如果不保持，那么先调用plugins_call_handle_connection_close通知所有插件连接关闭。然后关闭连接。最后，重置con，清除前一次请求的数据。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;至此，请求处理结束。总的来说，返回response的过程还算直接，没有多少难懂的地方。比较不好懂的地方都是关于http协议中一些情况的细节处理，读者可以参照rfc理解。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; font-family: Arial; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下面一片文章将会分析一些错误处理过程。&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/2033654.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2011/04/30/2033654.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2010/09/05/1818481.html</id><title type="text">debian下设置git的http代理</title><summary type="text">首先安装corkscrew。接着，写一个proxy wrapper。corkscrew的参数分别为：代理服务器的地址，代理服务器端口，所要代理的网址，认证文件。认证文件中包含用户名和密码，形式为“user:password”。将这个wrapper保存到文件proxy-wrapper中。修改git的默认配置文件，通常是/home/xxx/.gitconfig。在[core]段...</summary><published>2010-09-05T08:15:00Z</published><updated>2010-09-05T08:15:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2010/09/05/1818481.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2010/09/05/1818481.html"/><content type="html">&lt;p&gt;首先安装corkscrew。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;sudo apt-get install corkscrew&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;接着，写一个proxy wrapper。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;#!/bin/bash&lt;br/&gt;#git proxy wrapper&lt;br/&gt;# Put your own values&lt;br/&gt;PROXY_IP=10.0.8.0&lt;br/&gt;PROXY_PORT=8080&lt;br/&gt;corkscrew ${PROXY_IP} ${PROXY_PORT}  $*  /path/to/proxy-auth&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;corkscrew的参数分别为：代理服务器的地址，代理服务器端口，所要代理的网址，认证文件。&lt;/p&gt;&lt;p&gt;认证文件中包含用户名和密码，形式为&amp;ldquo;user:password&amp;rdquo;。&lt;/p&gt;&lt;p&gt;将这个wrapper保存到文件proxy-wrapper中。&lt;/p&gt;&lt;p&gt;修改git的默认配置文件，通常是/home/xxx/.gitconfig。&lt;/p&gt;&lt;p&gt;在[core]段添加需要代理的服务器。如：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;[core]&lt;br/&gt;gitproxy="/home/XXX/bin/proxy-wrapper" for XXXXX1.org&lt;br/&gt;gitproxy="/home/XXX/bin/proxy-wrapper" for XXXXX2.com&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;这样就可以了。。。&lt;/p&gt;&lt;p&gt;git还支持ssh和http协议。通过对本机的http代理或者ssh代理进行设置，可以通过这两个协议访问。&lt;/p&gt;&lt;p&gt;我的git配置文件：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;[user]&lt;br/&gt;name = xxx&lt;br/&gt;email = xxx@gmail.com&lt;br/&gt;[core]&lt;br/&gt;editor = vim&lt;br/&gt;gitproxy="/home/xxx/bin/proxy-wrapper" for gnome.org&lt;br/&gt;gitproxy="/home/xxx/bin/proxy-wrapper" for github.com&lt;br/&gt;[color]&lt;br/&gt;status = auto&lt;br/&gt;branch = auto&lt;br/&gt;diff = auto&lt;br/&gt;ui = true&lt;br/&gt;pager = true&lt;br/&gt;[color "branch"]&lt;br/&gt;current = yellow reverse&lt;br/&gt;local = yellow&lt;br/&gt;remote = green&lt;br/&gt;[color "diff"]&lt;br/&gt;meta = yellow bold&lt;br/&gt;frag = magenta bold&lt;br/&gt;old = red bold&lt;br/&gt;new = green bold&lt;br/&gt;[color "status"]&lt;br/&gt;added = yellow&lt;br/&gt;changed = green&lt;br/&gt;untracked = cyan&lt;br/&gt;[alias]&lt;br/&gt;co = checkout&lt;br/&gt;br = branch&lt;br/&gt;cm = commit&lt;br/&gt;st = status&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/1818481.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2010/09/05/1818481.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2010/08/29/1811760.html</id><title type="text">好久没更新了。。。</title><summary type="text">先忙毕设，接着是考驾照。毕设顺利完成。路考挂了。。。真悲剧。想拿个驾照真不容易，不送礼是不行的！</summary><published>2010-08-29T01:50:00Z</published><updated>2010-08-29T01:50:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2010/08/29/1811760.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2010/08/29/1811760.html"/><content type="html">&lt;p&gt;先忙毕设，接着是考驾照。&lt;/p&gt;&lt;p&gt;毕设顺利完成。&lt;/p&gt;&lt;p&gt;路考挂了。。。&lt;/p&gt;&lt;p&gt;真悲剧。想拿个驾照真不容易，不送礼是不行的！&lt;/p&gt;&lt;img src="http://www.cnblogs.com/kernel_hcy/aggbug/1811760.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/kernel_hcy/archive/2010/08/29/1811760.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/kernel_hcy/archive/2010/05/04/1727462.html</id><title type="text">zz from newsmth e进制是信息表示的最优解</title><summary type="text">先考虑最优的定义假定总共有n位，每位m个状态，m*n=v在v一定时，使得m^n最大也就是k(n)=(v/n)^n最大考虑一般情况下ln(k(n))=(ln(v)-ln(n))*n=ln(v)*n - ln(n)*n对n求导 ln(v) - (n*1/n + ln(n)) = ln(v) - 1 - ln(n)解得ln(n)=ln(v)-1是k(n)唯一的极值点易知是k(n)最大值点所以n=v/e ...</summary><published>2010-05-04T11:56:00Z</published><updated>2010-05-04T11:56:00Z</updated><author><name>kernel@hcy</name><uri>http://www.cnblogs.com/kernel_hcy/</uri></author><link rel="alternate" href="http://www.cnblogs.com/kernel_hcy/archive/2010/05/04/1727462.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/kernel_hcy/archive/2010/05/04/1727462.html"/><content type="text">先考虑最优的定义假定总共有n位，每位m个状态，m*n=v在v一定时，使得m^n最大也就是k(n)=(v/n)^n最大考虑一般情况下ln(k(n))=(ln(v)-ln(n))*n=ln(v)*n - ln(n)*n对n求导 ln(v) - (n*1/n + ln(n)) = ln(v) - 1 - ln(n)解得ln(n)=ln(v)-1是k(n)唯一的极值点易知是k(n)最大值点所以n=v/e ...</content></entry></feed>
