<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>colaghost</title>
	<atom:link href="http://www.colaghost.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.colaghost.com</link>
	<description>自己的世界。。。</description>
	<lastBuildDate>Thu, 17 May 2012 03:17:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>借钱风波</title>
		<link>http://www.colaghost.com/life/249</link>
		<comments>http://www.colaghost.com/life/249#comments</comments>
		<pubDate>Thu, 17 May 2012 03:14:26 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[历程]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=249</guid>
		<description><![CDATA[上个月中旬的时候突然接到一个算有点亲戚关系的人的电话，这里先称他为A吧，比较久没联系，当时也没想到会有什么事。闲聊两句后他开门见山了，问我有没有七八K借一下。我刚开始还以为是不是遇到什么急事了，没想到他跟我说是赌钱输了。我当时就犹豫了一下，没有立刻答应，只说现在身上也没啥钱，他也算比较直接，让我跟我同事借一下，我说我试下吧，就挂了电话。
当时问了几个同事，说应不应该借，同事都直接说这种情况不要借，借了等于鼓励他再去赌，想要回来也基本上不太可能了。
我也想过不借，但当时电话里感觉他还是挺急的，毕竟有点亲戚关系在，而且不知道会不会因为这点钱出点什么事，最后还是借了，但给自己留了点余地，只借了三K，而且说我也是跟同学借的，他当时信誓旦旦地保证说下周一一定还，只是先借钱周转一下，我隐约看到了他在我面前拍着胸口说着这句话，但是人可能都是会再去搏一下，输的人希望翻本，赢的人希望赢得更多，人性的弱点。
A在那周五突然发了条短信给我，让我提供下银行账户，说周六就打钱给我，还说了一通感谢麻烦的话。本来以为这事就这么结了，但是实际上我可能想得简单了点。
我当时给的是一个同事的账户，就在周日的时候问A转了没，好顺便跟同事说一下。没想到他跟我说又输了十来万，要回家准备跑路了，还说得先回家跟家里人要下钱才能周转给我，让我再等一下。我这时候隐约有点不详的预感了。
过了些天，他跟我说五月八号就一定还我，但是到了八号晚上他没有任何一个电话甚至短信也没有，又骗了我一次。
我这时候没再发短信，直接打了个电话过去，他接通后，只说了他现在在广州，晚点跟我说，好像不太方便说话。我也就没说什么直接挂了，过了一会，他发了条短信过来，大致意思就是说他姐刚刚在这，他跟他姐借了钱，周末会过来我那，顺便把钱还给我。
周末刚好一个好久没见的同学过来，恰好也是B女友的生日。这里顺便提上B，B跟A是邻居，从小玩到大，但是长大后关系就淡了。那天A并没有过来，但是同学过来了，也就没有怎么想起这件事，晚上的时候几个朋友一起凑着聊着天。
但是有时候总会有点小插曲，手机响了，一看来电是汕头那边的固话，一听才知道是A。一拿起来我就问A是不是回家了，他说刚回，然后就说了一堆最近怎么怎么样，他哥也输了多少多少钱，却闭口不提怎么没过来我这边的事，好像根本就没有发生过一样。最后还说他目前没钱周转，也不好意思跟家里人开口，问我能不能再借点钱他，保证很快就还，也不用多，只需要一两K就行了。我当时语气没有变吧，只是心里冷笑了几下，我找了个借口拒绝了他。当时B在我身边说话，A听到了，就跟我说让B听一下，我按了下静音，跟B说是A，让B听，B当时就明白我的意思了（我有跟B说A跟我借钱的事），跟A说了挺久。
后来我问了B一下，他说A也找他借钱，他表示没钱后A还让他先跟他妈要一点借他，还要B找借口跟他妈说是B要的，让A帮忙拿到广州而已。
我当时佩服得五体投地，这种也能敢想得出来，B比较好人，说可能是实在走投无路了吧。
A跟我说他在家时我就很生气了，一次又一次地欺骗我，当时差点就在我面前拍胸口保证了，结果没一句是实现了，然后还找着一个又一个的借口哄着我，完全没有一点愧疚感。
我借他钱时我就说过，不要再赌了，还年轻，还有拼搏的时间，赌虽然来得快，可是有可能让他不能自拔。他说好，要守了，不能再这样下去，事情过后要好好找点小生意做。可惜全都是P话，拿到钱后继续赌，还跟我说又输了十几万，我能说什么。
这三K我已经在心里当送给他了，可是我受不了他一次又一次地哄骗我，当我是傻瓜，还不了直接一句话，我会理解，可是不要信誓旦旦给我什么承诺，却一次又一次地反口，还要难为他一次又一次想借口来敷衍我。
]]></description>
			<content:encoded><![CDATA[<p>上个月中旬的时候突然接到一个算有点亲戚关系的人的电话，这里先称他为A吧，比较久没联系，当时也没想到会有什么事。闲聊两句后他开门见山了，问我有没有七八K借一下。我刚开始还以为是不是遇到什么急事了，没想到他跟我说是赌钱输了。我当时就犹豫了一下，没有立刻答应，只说现在身上也没啥钱，他也算比较直接，让我跟我同事借一下，我说我试下吧，就挂了电话。<br />
当时问了几个同事，说应不应该借，同事都直接说这种情况不要借，借了等于鼓励他再去赌，想要回来也基本上不太可能了。<br />
我也想过不借，但当时电话里感觉他还是挺急的，毕竟有点亲戚关系在，而且不知道会不会因为这点钱出点什么事，最后还是借了，但给自己留了点余地，只借了三K，而且说我也是跟同学借的，他当时信誓旦旦地保证说下周一一定还，只是先借钱周转一下，我隐约看到了他在我面前拍着胸口说着这句话，但是人可能都是会再去搏一下，输的人希望翻本，赢的人希望赢得更多，人性的弱点。<br />
A在那周五突然发了条短信给我，让我提供下银行账户，说周六就打钱给我，还说了一通感谢麻烦的话。本来以为这事就这么结了，但是实际上我可能想得简单了点。<br />
我当时给的是一个同事的账户，就在周日的时候问A转了没，好顺便跟同事说一下。没想到他跟我说又输了十来万，要回家准备跑路了，还说得先回家跟家里人要下钱才能周转给我，让我再等一下。我这时候隐约有点不详的预感了。<br />
过了些天，他跟我说五月八号就一定还我，但是到了八号晚上他没有任何一个电话甚至短信也没有，又骗了我一次。<br />
我这时候没再发短信，直接打了个电话过去，他接通后，只说了他现在在广州，晚点跟我说，好像不太方便说话。我也就没说什么直接挂了，过了一会，他发了条短信过来，大致意思就是说他姐刚刚在这，他跟他姐借了钱，周末会过来我那，顺便把钱还给我。<br />
周末刚好一个好久没见的同学过来，恰好也是B女友的生日。这里顺便提上B，B跟A是邻居，从小玩到大，但是长大后关系就淡了。那天A并没有过来，但是同学过来了，也就没有怎么想起这件事，晚上的时候几个朋友一起凑着聊着天。<br />
但是有时候总会有点小插曲，手机响了，一看来电是汕头那边的固话，一听才知道是A。一拿起来我就问A是不是回家了，他说刚回，然后就说了一堆最近怎么怎么样，他哥也输了多少多少钱，却闭口不提怎么没过来我这边的事，好像根本就没有发生过一样。最后还说他目前没钱周转，也不好意思跟家里人开口，问我能不能再借点钱他，保证很快就还，也不用多，只需要一两K就行了。我当时语气没有变吧，只是心里冷笑了几下，我找了个借口拒绝了他。当时B在我身边说话，A听到了，就跟我说让B听一下，我按了下静音，跟B说是A，让B听，B当时就明白我的意思了（我有跟B说A跟我借钱的事），跟A说了挺久。<br />
后来我问了B一下，他说A也找他借钱，他表示没钱后A还让他先跟他妈要一点借他，还要B找借口跟他妈说是B要的，让A帮忙拿到广州而已。<br />
我当时佩服得五体投地，这种也能敢想得出来，B比较好人，说可能是实在走投无路了吧。<br />
A跟我说他在家时我就很生气了，一次又一次地欺骗我，当时差点就在我面前拍胸口保证了，结果没一句是实现了，然后还找着一个又一个的借口哄着我，完全没有一点愧疚感。<br />
我借他钱时我就说过，不要再赌了，还年轻，还有拼搏的时间，赌虽然来得快，可是有可能让他不能自拔。他说好，要守了，不能再这样下去，事情过后要好好找点小生意做。可惜全都是P话，拿到钱后继续赌，还跟我说又输了十几万，我能说什么。<br />
这三K我已经在心里当送给他了，可是我受不了他一次又一次地哄骗我，当我是傻瓜，还不了直接一句话，我会理解，可是不要信誓旦旦给我什么承诺，却一次又一次地反口，还要难为他一次又一次想借口来敷衍我。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/life/249/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nginx内存管理及数据结构浅析&#8211;共享内存的实现</title>
		<link>http://www.colaghost.com/web-server/246</link>
		<comments>http://www.colaghost.com/web-server/246#comments</comments>
		<pubDate>Thu, 17 May 2012 02:39:20 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[web server]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=246</guid>
		<description><![CDATA[nginx是多进程模型，在许多场景我们可能需要跨进程共享数据，考虑到这个可能性，nginx本身也提供了共享内存这方面的接口。ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);
这个是nginx中关于分配共享内存最底层的接口了，它实际上就是直接调用mmap进行共享内存的分配的。
对于需要多次分配和释放共享内存的场景来说，直接用这个接口实际是无法忍受效率上的问题，或者有人想到可以直接分配一块大内存自己来进行分配释放的管理，但其实你不用自己做，nginx已经做好这部分的工作了，相关的接口是ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)，通过这个接口我们可以分配一大块内存，再借助ngx_slab_pool_t这个结构体来管理共享内存。那nginx又是如何来组织共享内存的呢？
在ngx_cycle_s结构里有一个成员，即ngx_cycle_s->shared_memory，它的类型是ngx_list_t，用来登记所有分配的共享内存，它装的节点类型是ngx_shm_zone_t，一个节点对应一块分配的共享内存，以下是它的源码：

1
2
3
4
5
6
7
8
9
10
struct ngx_shm_zone_s &#123;
//指向自定义数据结构，一般用来初始化时使用，可能指向本地地址
void *data;
//真正的共享内存
ngx_shm_t shm;
//初始化函数
ngx_shm_zone_init_pt init;
//标记
void *tag;
&#125;;

我们再看看ngx_shared_memory_add这个函数的实现，它首先检查要分配的内存是否存在，存在则直接返回，否则创建一个新的再返回。
1. 两个相同名字的共享内存大小要一样。
2. 两个相同名字的共享内存tag要一样。
3. 如果当前共享内存已经存在，则不需要再次添加。会返回同一个共享内存
4. 如果此共享内存不存在，则添加一个新的ngx_shm_zone_t
添加完后会返回ngx_shm_zone_t，我们需要设置init函数和data数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
ngx_shm_zone_t *
ngx_shared_memory_add&#40;ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag&#41;
&#123;
    ngx_uint_t        i;
    ngx_shm_zone_t   *shm_zone;
    ngx_list_part_t  *part;
&#160;
  [...]]]></description>
			<content:encoded><![CDATA[<p>nginx是多进程模型，在许多场景我们可能需要跨进程共享数据，考虑到这个可能性，nginx本身也提供了共享内存这方面的接口。ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);<br />
这个是nginx中关于分配共享内存最底层的接口了，它实际上就是直接调用mmap进行共享内存的分配的。<br />
对于需要多次分配和释放共享内存的场景来说，直接用这个接口实际是无法忍受效率上的问题，或者有人想到可以直接分配一块大内存自己来进行分配释放的管理，但其实你不用自己做，nginx已经做好这部分的工作了，相关的接口是ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name, size_t size, void *tag)，通过这个接口我们可以分配一大块内存，再借助ngx_slab_pool_t这个结构体来管理共享内存。那nginx又是如何来组织共享内存的呢？<br />
在ngx_cycle_s结构里有一个成员，即ngx_cycle_s->shared_memory，它的类型是ngx_list_t，用来登记所有分配的共享内存，它装的节点类型是ngx_shm_zone_t，一个节点对应一块分配的共享内存，以下是它的源码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> ngx_shm_zone_s <span style="color: #009900;">&#123;</span>
<span style="color: #666666; font-style: italic;">//指向自定义数据结构，一般用来初始化时使用，可能指向本地地址</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>data<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//真正的共享内存</span>
ngx_shm_t shm<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//初始化函数</span>
ngx_shm_zone_init_pt init<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//标记</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>tag<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>我们再看看ngx_shared_memory_add这个函数的实现，它首先检查要分配的内存是否存在，存在则直接返回，否则创建一个新的再返回。<br />
1. 两个相同名字的共享内存大小要一样。<br />
2. 两个相同名字的共享内存tag要一样。<br />
3. 如果当前共享内存已经存在，则不需要再次添加。会返回同一个共享内存<br />
4. 如果此共享内存不存在，则添加一个新的ngx_shm_zone_t<br />
添加完后会返回ngx_shm_zone_t，我们需要设置init函数和data数据</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">ngx_shm_zone_t <span style="color: #339933;">*</span>
ngx_shared_memory_add<span style="color: #009900;">&#40;</span>ngx_conf_t <span style="color: #339933;">*</span>cf<span style="color: #339933;">,</span> ngx_str_t <span style="color: #339933;">*</span>name<span style="color: #339933;">,</span> size_t size<span style="color: #339933;">,</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>tag<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    ngx_uint_t        i<span style="color: #339933;">;</span>
    ngx_shm_zone_t   <span style="color: #339933;">*</span>shm_zone<span style="color: #339933;">;</span>
    ngx_list_part_t  <span style="color: #339933;">*</span>part<span style="color: #339933;">;</span>
&nbsp;
    part <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>cf<span style="color: #339933;">-&gt;</span>cycle<span style="color: #339933;">-&gt;</span>shared_memory.<span style="color: #202020;">part</span><span style="color: #339933;">;</span>
    shm_zone <span style="color: #339933;">=</span> part<span style="color: #339933;">-&gt;</span>elts<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//先查找所有已经存在的共享内存，看看要创建的共享内存是否存在于这里面，如果存在的话就直接返回，否则</span>
<span style="color: #666666; font-style: italic;">//创建一个新的共享内存结构体再返回</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* void */</span> <span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">&gt;=</span> part<span style="color: #339933;">-&gt;</span>nelts<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>part<span style="color: #339933;">-&gt;</span>next <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            part <span style="color: #339933;">=</span> part<span style="color: #339933;">-&gt;</span>next<span style="color: #339933;">;</span>
            shm_zone <span style="color: #339933;">=</span> part<span style="color: #339933;">-&gt;</span>elts<span style="color: #339933;">;</span>
            i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>name<span style="color: #339933;">-&gt;</span>len <span style="color: #339933;">!=</span> shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span>.<span style="color: #202020;">len</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ngx_strncmp<span style="color: #009900;">&#40;</span>name<span style="color: #339933;">-&gt;</span>data<span style="color: #339933;">,</span> shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span>.<span style="color: #202020;">data</span><span style="color: #339933;">,</span> name<span style="color: #339933;">-&gt;</span>len<span style="color: #009900;">&#41;</span>
            <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>size <span style="color: #339933;">&amp;&amp;</span> size <span style="color: #339933;">!=</span> shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">size</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            ngx_conf_log_error<span style="color: #009900;">&#40;</span>NGX_LOG_EMERG<span style="color: #339933;">,</span> cf<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span>
                            <span style="color: #ff0000;">&quot;the size %uz of shared memory zone <span style="color: #000099; font-weight: bold;">\&quot;</span>%V<span style="color: #000099; font-weight: bold;">\&quot;</span> &quot;</span>
                            <span style="color: #ff0000;">&quot;conflicts with already declared size %uz&quot;</span><span style="color: #339933;">,</span>
                            size<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span><span style="color: #339933;">,</span> shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">size</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> NULL<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>tag <span style="color: #339933;">!=</span> shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">tag</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            ngx_conf_log_error<span style="color: #009900;">&#40;</span>NGX_LOG_EMERG<span style="color: #339933;">,</span> cf<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span>
                            <span style="color: #ff0000;">&quot;the shared memory zone <span style="color: #000099; font-weight: bold;">\&quot;</span>%V<span style="color: #000099; font-weight: bold;">\&quot;</span> is &quot;</span>
                            <span style="color: #ff0000;">&quot;already declared for a different use&quot;</span><span style="color: #339933;">,</span>
                            <span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">return</span> NULL<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//此共享内存已经存在，直接返回</span>
        <span style="color: #b1b100;">return</span> <span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//插入一个新的共享内存结构体结点</span>
    shm_zone <span style="color: #339933;">=</span> ngx_list_push<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>cf<span style="color: #339933;">-&gt;</span>cycle<span style="color: #339933;">-&gt;</span>shared_memory<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>shm_zone <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> NULL<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    shm_zone<span style="color: #339933;">-&gt;</span>data <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
    shm_zone<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">log</span> <span style="color: #339933;">=</span> cf<span style="color: #339933;">-&gt;</span>cycle<span style="color: #339933;">-&gt;</span>log<span style="color: #339933;">;</span>
    shm_zone<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">size</span> <span style="color: #339933;">=</span> size<span style="color: #339933;">;</span>
    shm_zone<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">name</span> <span style="color: #339933;">=</span> <span style="color: #339933;">*</span>name<span style="color: #339933;">;</span>
    shm_zone<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">exists</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    shm_zone<span style="color: #339933;">-&gt;</span>init <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
    shm_zone<span style="color: #339933;">-&gt;</span>tag <span style="color: #339933;">=</span> tag<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> shm_zone<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>看到这里，会不会有一个疑问，ngx_shared_memory_add也就是找到或者插入一个ngx_shm_zone_t节点而已啊，但是并没有真正分配共享内存的操作啊？我刚开始也是百思不得其解，直到看到ngx_init_cycle这个函数后，才豁然开朗。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">ngx_cycle_t <span style="color: #339933;">*</span>
ngx_init_cycle<span style="color: #009900;">&#40;</span>ngx_cycle_t <span style="color: #339933;">*</span>old_cycle<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
。。。
&nbsp;
    <span style="color: #808080; font-style: italic;">/* create shared memory */</span>
&nbsp;
    part <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>cycle<span style="color: #339933;">-&gt;</span>shared_memory.<span style="color: #202020;">part</span><span style="color: #339933;">;</span>
    shm_zone <span style="color: #339933;">=</span> part<span style="color: #339933;">-&gt;</span>elts<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* void */</span> <span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">&gt;=</span> part<span style="color: #339933;">-&gt;</span>nelts<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>part<span style="color: #339933;">-&gt;</span>next <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            part <span style="color: #339933;">=</span> part<span style="color: #339933;">-&gt;</span>next<span style="color: #339933;">;</span>
            shm_zone <span style="color: #339933;">=</span> part<span style="color: #339933;">-&gt;</span>elts<span style="color: #339933;">;</span>
            i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">size</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            ngx_log_error<span style="color: #009900;">&#40;</span>NGX_LOG_EMERG<span style="color: #339933;">,</span> log<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span>
                          <span style="color: #ff0000;">&quot;zero size shared memory zone <span style="color: #000099; font-weight: bold;">\&quot;</span>%V<span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #339933;">,</span>
                          <span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">goto</span> failed<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//注意这里，没有设置init函数的共享内存是被视为不使用的</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">init</span> <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #808080; font-style: italic;">/* unused shared zone */</span>
            <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">log</span> <span style="color: #339933;">=</span> cycle<span style="color: #339933;">-&gt;</span>log<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//这里主要是考虑reload操作</span>
        opart <span style="color: #339933;">=</span> <span style="color: #339933;">&amp;</span>old_cycle<span style="color: #339933;">-&gt;</span>shared_memory.<span style="color: #202020;">part</span><span style="color: #339933;">;</span>
        oshm_zone <span style="color: #339933;">=</span> opart<span style="color: #339933;">-&gt;</span>elts<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>n <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> <span style="color: #808080; font-style: italic;">/* void */</span> <span style="color: #339933;">;</span> n<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>n <span style="color: #339933;">&gt;=</span> opart<span style="color: #339933;">-&gt;</span>nelts<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>opart<span style="color: #339933;">-&gt;</span>next <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                opart <span style="color: #339933;">=</span> opart<span style="color: #339933;">-&gt;</span>next<span style="color: #339933;">;</span>
                oshm_zone <span style="color: #339933;">=</span> opart<span style="color: #339933;">-&gt;</span>elts<span style="color: #339933;">;</span>
                n <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span>.<span style="color: #202020;">len</span> <span style="color: #339933;">!=</span> oshm_zone<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span>.<span style="color: #202020;">len</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ngx_strncmp<span style="color: #009900;">&#40;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span>.<span style="color: #202020;">data</span><span style="color: #339933;">,</span>
                            oshm_zone<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span>.<span style="color: #202020;">data</span><span style="color: #339933;">,</span>
                            shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">name</span>.<span style="color: #202020;">len</span><span style="color: #009900;">&#41;</span>
                <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//如果新的共享内存和旧的共享内存大小一样，就无需再次分配了，直接指过去即可</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">size</span> <span style="color: #339933;">==</span> oshm_zone<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">size</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">addr</span> <span style="color: #339933;">=</span> oshm_zone<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span>.<span style="color: #202020;">addr</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//这里还需要重新初始化一下，因为可能会有对本地内存的操作</span>
                <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">init</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> oshm_zone<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">data</span><span style="color: #009900;">&#41;</span>
                    <span style="color: #339933;">!=</span> NGX_OK<span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #b1b100;">goto</span> failed<span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #b1b100;">goto</span> shm_zone_found<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//如果老的共享内存和新的要分配的共享内存大小不一致，那就只能释放掉了</span>
            ngx_shm_free<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>oshm_zone<span style="color: #009900;">&#91;</span>n<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//真正分配共享内存的调用 </span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ngx_shm_alloc<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">shm</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> NGX_OK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">goto</span> failed<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//初始化共享内存，为用slab来管理内存池做准备</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ngx_init_zone_pool<span style="color: #009900;">&#40;</span>cycle<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> NGX_OK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">goto</span> failed<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//调用设置的init函数</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #202020;">init</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>shm_zone<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> NGX_OK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">goto</span> failed<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
    shm_zone_found<span style="color: #339933;">:</span>
&nbsp;
        <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
。。。
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>通过代码我们可以看到，对于每一个共享内存，都会先调用ngx_shm_alloc进行共享内存的分配，然后使用ngx_init_zone_pool对共享内存进行初始化，最后就调用我们设置的init函数了。<br />
ngx_init_zone_pool主要的目的就是让我们可以通过slab来分配、释放内存（具体的用法这里暂不提及，以后有空可以专门写一篇文章来说）。下面我们来看看ngx_init_zone_pool的实现吧：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> ngx_int_t
ngx_init_zone_pool<span style="color: #009900;">&#40;</span>ngx_cycle_t <span style="color: #339933;">*</span>cycle<span style="color: #339933;">,</span> ngx_shm_zone_t <span style="color: #339933;">*</span>zn<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    u_char           <span style="color: #339933;">*</span>file<span style="color: #339933;">;</span>
    ngx_slab_pool_t  <span style="color: #339933;">*</span>sp<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//通过slab来管理内存</span>
    sp <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>ngx_slab_pool_t <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">addr</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">exists</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>sp <span style="color: #339933;">==</span> sp<span style="color: #339933;">-&gt;</span>addr<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">return</span> NGX_OK<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        ngx_log_error<span style="color: #009900;">&#40;</span>NGX_LOG_EMERG<span style="color: #339933;">,</span> cycle<span style="color: #339933;">-&gt;</span>log<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span>
                      <span style="color: #ff0000;">&quot;shared zone <span style="color: #000099; font-weight: bold;">\&quot;</span>%V<span style="color: #000099; font-weight: bold;">\&quot;</span> has no equal addresses: %p vs %p&quot;</span><span style="color: #339933;">,</span>
                      <span style="color: #339933;">&amp;</span>zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">name</span><span style="color: #339933;">,</span> sp<span style="color: #339933;">-&gt;</span>addr<span style="color: #339933;">,</span> sp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">return</span> NGX_ERROR<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//初始化slab分配器</span>
    sp<span style="color: #339933;">-&gt;</span>end <span style="color: #339933;">=</span> zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">addr</span> <span style="color: #339933;">+</span> zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">size</span><span style="color: #339933;">;</span>
    sp<span style="color: #339933;">-&gt;</span>min_shift <span style="color: #339933;">=</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">;</span>
    sp<span style="color: #339933;">-&gt;</span>addr <span style="color: #339933;">=</span> zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">addr</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">#if (NGX_HAVE_ATOMIC_OPS)</span>
&nbsp;
    file <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">#else</span>
&nbsp;
    file <span style="color: #339933;">=</span> ngx_pnalloc<span style="color: #009900;">&#40;</span>cycle<span style="color: #339933;">-&gt;</span>pool<span style="color: #339933;">,</span> cycle<span style="color: #339933;">-&gt;</span>lock_file.<span style="color: #202020;">len</span> <span style="color: #339933;">+</span> zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">name</span>.<span style="color: #202020;">len</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>file <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> NGX_ERROR<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span> ngx_sprintf<span style="color: #009900;">&#40;</span>file<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;%V%V%Z&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>cycle<span style="color: #339933;">-&gt;</span>lock_file<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>zn<span style="color: #339933;">-&gt;</span>shm.<span style="color: #202020;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">#endif</span>
<span style="color: #666666; font-style: italic;">//创建共享内存的锁</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ngx_shmtx_create<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>sp<span style="color: #339933;">-&gt;</span>mutex<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span>sp<span style="color: #339933;">-&gt;</span>lock<span style="color: #339933;">,</span> file<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> NGX_OK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> NGX_ERROR<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    ngx_slab_init<span style="color: #009900;">&#40;</span>sp<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> NGX_OK<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>在调用这个接口进行初始化后，以后我们在这块共享内存上进行分配和释放都是通过slab来完成的了，例如有ngx_slab_alloc和<br />
ngx_slab_free。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/web-server/246/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nginx内存管理及数据结构浅析&#8211;内存池</title>
		<link>http://www.colaghost.com/web-server/232</link>
		<comments>http://www.colaghost.com/web-server/232#comments</comments>
		<pubDate>Tue, 10 Apr 2012 06:04:14 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[web server]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=232</guid>
		<description><![CDATA[基本上所有的高性能服务器都会涉及到内存池这一块，nginx也不例外。nginx的内存池实现相对比较简洁精巧，看起来比较容易理解。
以下是nginx内存池的示意图，这是根据自己的理解画的，有什么理解错误的地方欢迎大家拍砖。

nginx的内存池主要涉及它的创建、小内存分配、大内存分配和资源清理。
一、内存池的创建
这里主要涉及到两个数据结构，分别是ngx_pool_s和ngx_pool_data_t。ngx_pool_s维护了内存池的的头部信息，而ngx_pool_data_t维护了内存池的数据部分的信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//该结构用来维护内存池的数据部分，供用户分配内存使用
typedef struct &#123;
u_char               *last;//当前内存分配结束的位置
u_char               *end;//内存池结束位置
ngx_pool_t           *next;//指向下一个内存池
ngx_uint_t            failed;//统计内存池不能满足分配请求的次数
&#125; ngx_pool_data_t;
//该结构维护整个内存池链表的头部信息
struct ngx_pool_s &#123;
ngx_pool_data_t       d;//数据块
size_t                max;//数据块的大小，即可分配的内存的最大值
ngx_pool_t           *current;//当前内存池
ngx_chain_t       [...]]]></description>
			<content:encoded><![CDATA[<p>基本上所有的高性能服务器都会涉及到内存池这一块，nginx也不例外。nginx的内存池实现相对比较简洁精巧，看起来比较容易理解。</p>
<p>以下是nginx内存池的示意图，这是根据自己的理解画的，有什么理解错误的地方欢迎大家拍砖。</p>
<p><a href="http://www.colaghost.com/wp-content/uploads/2012/04/ngx_pool1.jpeg"><img class="aligncenter size-full wp-image-234" title="ngx_pool" src="http://www.colaghost.com/wp-content/uploads/2012/04/ngx_pool1.jpeg" alt="" width="691" height="551" /></a></p>
<p>nginx的内存池主要涉及它的创建、小内存分配、大内存分配和资源清理。</p>
<p><strong>一、内存池的创建</strong></p>
<p>这里主要涉及到两个数据结构，分别是ngx_pool_s和ngx_pool_data_t。ngx_pool_s维护了内存池的的头部信息，而ngx_pool_data_t维护了内存池的数据部分的信息。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//该结构用来维护内存池的数据部分，供用户分配内存使用</span>
<span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> <span style="color: #009900;">&#123;</span>
u_char               <span style="color: #339933;">*</span>last<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//当前内存分配结束的位置</span>
u_char               <span style="color: #339933;">*</span>end<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//内存池结束位置</span>
ngx_pool_t           <span style="color: #339933;">*</span>next<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//指向下一个内存池</span>
ngx_uint_t            failed<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//统计内存池不能满足分配请求的次数</span>
<span style="color: #009900;">&#125;</span> ngx_pool_data_t<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//该结构维护整个内存池链表的头部信息</span>
<span style="color: #993333;">struct</span> ngx_pool_s <span style="color: #009900;">&#123;</span>
ngx_pool_data_t       d<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//数据块</span>
size_t                max<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//数据块的大小，即可分配的内存的最大值</span>
ngx_pool_t           <span style="color: #339933;">*</span>current<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//当前内存池</span>
ngx_chain_t          <span style="color: #339933;">*</span>chain<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//这一部分暂不涉及</span>
ngx_pool_large_t     <span style="color: #339933;">*</span>large<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//分配大内存使用，即请求分配的内存大小超过max</span>
ngx_pool_cleanup_t   <span style="color: #339933;">*</span>cleanup<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//用来指向内存池释放时同时释放的资源</span>
ngx_log_t            <span style="color: #339933;">*</span>log<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<div></div>
<div>有了上面两个结构体，实际上已经可以分配一个内存池了，创建一个内存池的入口函数是ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log)，切记size需要大于sizeof(ngx_pool_s)，大于部分为此内存池供分配的内存。返回的ngx_pool_t指针指向整个内存池链表的头结点，头结点会维护整个内存池链接的头部信息，下次如果往内存池链表里面添加ngx_pool_s结点时只会维护顶部的ngx_pool_data_t部分的信息，即只维护此内存池结点的数据部分的信息。</div>
<div></div>
<div>关于整个内存池链接的结构可以参考下上图，pool指向内存池的头部结点，红色部分为可分配用户使用的内存块。由上图可以看出来，pool-&gt;d.last指向从内存池分配新内存的起始地址，pool-&gt;d.end指向这块内存池的结束位置，所有分配内存的地址都不能超过pool-&gt;d.end。</div>
<div></div>
<div>当进行内存分配操作时，首先判断要分配的size大小是否超过max，是的话就直接跟系统分配一块大内存，跟malloc一样，挂在pool-&gt;large下；否则就直接在pool-&gt;current指向的内存池里分配，并相应地移动pool-&gt;current-&gt;d.last的位置。</div>
<div></div>
<div><strong>二、分配小内存（size&lt;max）</strong></div>
<div></div>
<div>小内存分配涉及到的接口函数主要有：</div>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>ngx_palloc<span style="color: #009900;">&#40;</span>ngx_pool_t <span style="color: #339933;">*</span>pool<span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>ngx_pnalloc<span style="color: #009900;">&#40;</span>ngx_pool_t <span style="color: #339933;">*</span>pool<span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>ngx_pcalloc<span style="color: #009900;">&#40;</span>ngx_pool_t <span style="color: #339933;">*</span>pool<span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span> <span style="color: #339933;">*</span>ngx_pmemalign<span style="color: #009900;">&#40;</span>ngx_pool_t <span style="color: #339933;">*</span>pool<span style="color: #339933;">,</span> size_t size<span style="color: #339933;">,</span> size_t alignment<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<div>头三个函数都是进行内存分配的，参数为要从中分配内存的内存池链表的头结点和要分配的内存大小。ngx_palloc和ngx_pnalloc都是从内存池中分配内存，区别就是ngx_palloc取得的内存是对齐的，而ngx_pnalloc则没有；ngx_pcalloc是调用ngx_palloc分配内存的，并将分配的内存都置0.ngx_pmemalign主要用来对指针进行对齐，但是nginx似乎没有使用这个，而是用到了另外定义的一个宏，下面会谈到。</div>
</div>
<div></div>
<div>这里由于篇幅问题只进行ngx_palloc函数的分析，其它两个大同小异。</div>
<div>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">void</span> <span style="color: #339933;">*</span>
ngx_palloc<span style="color: #009900;">&#40;</span>ngx_pool_t <span style="color: #339933;">*</span>pool<span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    u_char      <span style="color: #339933;">*</span>m<span style="color: #339933;">;</span>
    ngx_pool_t  <span style="color: #339933;">*</span>p<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>size <span style="color: #339933;">&lt;=</span> pool<span style="color: #339933;">-&gt;</span>max<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        p <span style="color: #339933;">=</span> pool<span style="color: #339933;">-&gt;</span>current<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">do</span> <span style="color: #009900;">&#123;</span>
            m <span style="color: #339933;">=</span> ngx_align_ptr<span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">last</span><span style="color: #339933;">,</span> NGX_ALIGNMENT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>size_t<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">end</span> <span style="color: #339933;">-</span> m<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;=</span> size<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">last</span> <span style="color: #339933;">=</span> m <span style="color: #339933;">+</span> size<span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #b1b100;">return</span> m<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            p <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">next</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> ngx_palloc_block<span style="color: #009900;">&#40;</span>pool<span style="color: #339933;">,</span> size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ngx_palloc_large<span style="color: #009900;">&#40;</span>pool<span style="color: #339933;">,</span> size<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

</div>
<div></div>
<div>这里分配的是小内存，进行的是size&lt;=pool-&gt;max部分的逻辑。我们可以看到nginx会从pool-&gt;current指向的内存池结点开始遍历，首先用ngx_align_ptr这个宏对last指针进行内存对齐，再判断当前内存池结点的数据部分剩余的内存是否够分配，如果够的话则移动last指针size大小的值，然后返回分配的内存的起始地址；否则移动到下一个内存池结点再进行同样的判断。</div>
<div></div>
<div>这里有一种可能性，即内存池链表里可能所有节点的数据部分的剩余内存都不够分配了，这时候就需要在内存池链表里插入一个新的内存池（ngx_pool_t）结点，这是由ngx_palloc_block函数完成的。</div>
<div></div>
<div>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">void</span> <span style="color: #339933;">*</span>
ngx_palloc_block<span style="color: #009900;">&#40;</span>ngx_pool_t <span style="color: #339933;">*</span>pool<span style="color: #339933;">,</span> size_t size<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    u_char      <span style="color: #339933;">*</span>m<span style="color: #339933;">;</span>
    size_t       psize<span style="color: #339933;">;</span>
    ngx_pool_t  <span style="color: #339933;">*</span>p<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>new<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>current<span style="color: #339933;">;</span>
&nbsp;
    psize <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>size_t<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span>pool<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">end</span> <span style="color: #339933;">-</span> <span style="color: #009900;">&#40;</span>u_char <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> pool<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    m <span style="color: #339933;">=</span> ngx_alloc<span style="color: #009900;">&#40;</span>psize<span style="color: #339933;">,</span> pool<span style="color: #339933;">-&gt;</span>log<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>m <span style="color: #339933;">==</span> NULL<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> NULL<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    new <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>ngx_pool_t <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> m<span style="color: #339933;">;</span>
&nbsp;
    new<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">end</span> <span style="color: #339933;">=</span> m <span style="color: #339933;">+</span> psize<span style="color: #339933;">;</span>
    new<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">next</span> <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
    new<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">failed</span> <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
    m <span style="color: #339933;">+=</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>ngx_pool_data_t<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    m <span style="color: #339933;">=</span> ngx_align_ptr<span style="color: #009900;">&#40;</span>m<span style="color: #339933;">,</span> NGX_ALIGNMENT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    new<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">last</span> <span style="color: #339933;">=</span> m <span style="color: #339933;">+</span> size<span style="color: #339933;">;</span>
&nbsp;
    current <span style="color: #339933;">=</span> pool<span style="color: #339933;">-&gt;</span>current<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span>p <span style="color: #339933;">=</span> current<span style="color: #339933;">;</span> p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">next</span><span style="color: #339933;">;</span> p <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">next</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">failed</span><span style="color: #339933;">++</span> <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">4</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            current <span style="color: #339933;">=</span> p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">next</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    p<span style="color: #339933;">-&gt;</span>d.<span style="color: #202020;">next</span> <span style="color: #339933;">=</span> new<span style="color: #339933;">;</span>
&nbsp;
    pool<span style="color: #339933;">-&gt;</span>current <span style="color: #339933;">=</span> current <span style="color: #339933;">?</span> current <span style="color: #339933;">:</span> new<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> m<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

</div>
<div></div>
<div>ngx_palloc_block函数会往内存池链表里插入一个新的内存池结点，并返回请求分配的内存的起始地址。</div>
<div>注意在这时nginx会对p-&gt;current结点后的所有内存池结点的数据部分维护的failed的值加1,并当failed的值超过4时，则将p-&gt;current的值指向下一个内存池结点，这也就意味着内存池链表里每一个结点的可分配内存不一定会被分配完。</div>
<div></div>
<div>这里再提下ngx_align_ptr这个宏，NGX_ALIGNMENT取值32或者64（sizeof(unsigned long)）,这个宏会在这两个平台里对指针进行对齐，下面看看这个宏的定义。</div>
<div></div>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define ngx_align_ptr(p, a)                                                                                     \
    (u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) &amp; ~((uintptr_t) a - 1))</span></pre></td></tr></table></div>

<div>uintptr_t可以将指针类型转换为整数，由于这段代码跨平台，所以用uintptr_t更安全，因为有可能为4或者8.</div>
<div>从二进制来看，为32位平台时，进行指针对齐需要保证指针的值的最低两位为0，即为4的倍数。当最低两位有任意一位不为零时，则需要加上((uintptr_t) a &#8211; 1)) （这时候a取值为4）产生进位，再通过与~((uintptr_t) a &#8211; 1)(最低四位是为1100)做且运算，抹平指针最低两位，这时候对齐完成。</div>
<div>这段代码并不复杂，但是涉及的方面比较多，效率也很高，比较有意思。</div>
<div></div>
<p><br\></p>
<div><strong>三、分配大块内存</strong></div>
<p><br\></p>
<div></div>
<div>大块内存的分配相对来说逻辑上比较简单，这时候并不是从内存池里分配，而是直接跟系统申请（相当于直接用malloc分配），再将这块内存挂到内存池头部的large字段里。由于内存池主要是用来解决小内存的频繁分配问题，这里大内存直接向系统申请是可以忍受的。大块内存的组织结构可以参考上图。</div>
<div></div>
<div>注意每块大内存都有一个数据结构进行维护的:</div>
<div></div>
<div>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> ngx_pool_large_s <span style="color: #009900;">&#123;</span>
ngx_pool_large_t     <span style="color: #339933;">*</span>next<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//指向下一块大内存</span>
<span style="color: #993333;">void</span>                 <span style="color: #339933;">*</span>alloc<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//指向分配的大块内存</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</div>
<div></div>
<div>这个数据结构是在内存池里进行分配的，因为这部分信息占用的字节比较少。由于大块内存很多时候可能需要及时被释放，所以nginx提供了ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p)函数进行释放。其中p就是指向大块内存的地址。ngx_pfree只会释放分配的大块内存，但数据结构部分并不会被释放，会留下来供下次分配大内存使用。</div>
<div></div>
<p><br\></p>
<div><strong>四、资源回收</strong></div>
<p><br\></p>
<div></div>
<div>可以参考上图的cleanup部分，会发现所有需要被释放的资源会形成一个循环链表。每个需要释放的资源都会有一个头部结构：</div>
<div></div>
<div>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> ngx_pool_cleanup_s <span style="color: #009900;">&#123;</span>
ngx_pool_cleanup_pt   handler<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//释放资源的函数指针</span>
<span style="color: #993333;">void</span>                 <span style="color: #339933;">*</span>data<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//待释放的资源</span>
ngx_pool_cleanup_t   <span style="color: #339933;">*</span>next<span style="color: #339933;">;</span><span style="color: #666666; font-style: italic;">//指向下一个待释放的资源头部</span>
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

</div>
<div></div>
<div>这里可以看到，当挂载一个待释放的资源时，需要注册一个释放函数。这就意味着这里不单单可以进行内存的释放，相应的文件标识符等也可以在这里进行释放，只要注册相应的释放资源函数调用即可。</div>
<div></div>
<p><br\></p>
<div><strong>五、内存回收</strong></div>
<p><br\></p>
<div></div>
<div>一路看来，貌似nginx并没有提供释放内存的接口（除了大内存块），难道nginx的内存都是只申请不释放的，这样不行啊，内存再多也只有吃完的时候啊。但显然我的担心是多余了，nginx并不会这样，它针对特定的场景，如每一个request都会建一个内存池，当request被完成时内存池分配的内存也会一次性被回收，这样就保证了内存有分配也有释放的时候了。当然具体还有很多的场景，由于理解深度还不够这里暂不涉及。</div>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/web-server/232/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>twisted的BUG？</title>
		<link>http://www.colaghost.com/python/222</link>
		<comments>http://www.colaghost.com/python/222#comments</comments>
		<pubDate>Sat, 17 Mar 2012 12:02:08 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Twisted]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=222</guid>
		<description><![CDATA[最近在写一个加速服务，基于http协议，采用了twisted框架。测试中均无发现问题，后来部署在实际环境中，却一而再爆发出一些时延很大的问题。加速服务是部署在f5(请求分发器)跟wap农场之间，所有请求都经过加速器才转发到wap农场。监控组的同学发现这个加速服务一上后就减速了，每次请求时延都达到了5秒以上。
百思不得其解，后来无意中在刷新火狐时（将代理设为加速器），发现一瞬间变得很慢，看了一下加速器日志，发现一有304响应时就会timeout，这很奇怪。加速器的客户端是继承了HTTPPageGetter，由它来向后端的web server发起真正的http请求的，试着在dataReceived接口（当socket有数据时会调用此接口），发现HTTPageGetter层已经收到数据，但却迟迟不返回给上层调用，导致最终延迟。
跟了一下HTTPageGetter的代码，发现其在收到所有header字段时会调用handleEndHeaders这个函数，这个函数会的定义如下：

self.status是响应码，它会根据不同的响应码来调用不同的函数，但是它并没有定义handleStatus_304这个函数，因此默认是调用 了self.handleStatusDefault这个函数，这个函数只将self.failed这个成员附为1，视为错误情况，然后不处理。
问题就出在这里，这时候与web server的链接还保持着，但是它并没有将收到的数据返回给上层调用，而是一直阻塞在socket.recv里，等着接收body，但是当没有body时，就会一直等到超时或者web server断掉连接才返回。
知道问题就好改了，直接将handleStatusDefault这个函数的定义改为如下：

即在不存在content-length这个字段（当self.length==None时没有这个字段）或者值为0时直接返回响应。
更新代码，再次上线，很诡异的时候，uclb（f5后面的请求分发进程，进行会话保持）没有出现超时的情况，但监控组的同学依然表示还是一样，监控到的时延还是很大。
既然不是304导致的，那还会是什么问题呢？为什么用手机连到生产环境都没有问题，测试时也没有发现这个问题，偏偏监控时就会有问题呢？难道是监控脚本的问题？
试着让监控的同学对监控脚本发起请求的过程进行抓包，发现问题出在302响应里，每次加速器返回302头部给监控脚本时，监控脚本并不会马上跳转，而是会明显停顿4、5秒。但是监控脚本直接绕过加速器却没有这个问题，将两次抓包对比了下，发现经过加速器时返回的302 body部分不见了，但是还是带有content-length这个字段。看来监控时会有延长的原因找到了，监控脚本收到302时一直在等待接收body，但是加速器却没有返回body，导致每次耗时爆涨。
看来问题还是出在twisted里，果然，twisted在处理302时并不接收body部分（不管有没有content-length字段），直接在接收完头部时断掉与web server的连接，并返回数据给上层调用。看下代码：

原因找到了，这时候不返回body其实对于普通的浏览器来说都是没有问题的，因为它们根据头部里的location字段就可以进行跳转了，但是监控脚本太死板了，一直要等到body回来直到超时才肯乖乖去跳转。这时候也就加入处理302的函数了，在有body的情况下进行处理，以下是我的处理函数：

跟handleStatusDefault是一致的。
再次更新上线，这次监控脚本终于正常了。
后记：
这里不由得有一个思考，为何twisted在处理302跳转时会直接去掉body部分呢？一个猜想就是其实根据头部已经有足够的信息了，忽略掉body可以加快速度，但是这样对于标准来说是否合适？
另外一个问题就是，twisted在接收body数据时为什么不首先判断一下是否存在content-length或者长度是否为0再决定是否要马上返回响应或者是继续等待web server的响应数据呢？我们再回过头来看下它底层的接收函数：

rawDataReceived是在dataReceived被调用时且已经收完头部数据了被调用的，这时候不管是不是存在body，程序也都会一直在等待数据响应直到超时或连接断掉。这难道是twisted认为这种情况应该由开发者自己去处理？
]]></description>
			<content:encoded><![CDATA[<p>最近在写一个加速服务，基于http协议，采用了twisted框架。测试中均无发现问题，后来部署在实际环境中，却一而再爆发出一些时延很大的问题。加速服务是部署在f5(请求分发器)跟wap农场之间，所有请求都经过加速器才转发到wap农场。监控组的同学发现这个加速服务一上后就减速了，每次请求时延都达到了5秒以上。<br />
百思不得其解，后来无意中在刷新火狐时（将代理设为加速器），发现一瞬间变得很慢，看了一下加速器日志，发现一有304响应时就会timeout，这很奇怪。加速器的客户端是继承了HTTPPageGetter，由它来向后端的web server发起真正的http请求的，试着在dataReceived接口（当socket有数据时会调用此接口），发现HTTPageGetter层已经收到数据，但却迟迟不返回给上层调用，导致最终延迟。<br />
跟了一下HTTPageGetter的代码，发现其在收到所有header字段时会调用handleEndHeaders这个函数，这个函数会的定义如下：<br />
<a href="http://www.colaghost.com/wp-content/uploads/2012/03/1.jpg"><img class="aligncenter size-full wp-image-226" title="1" src="http://www.colaghost.com/wp-content/uploads/2012/03/1.jpg" alt="" width="567" height="74" /></a></p>
<p>self.status是响应码，它会根据不同的响应码来调用不同的函数，但是它并没有定义handleStatus_304这个函数，因此默认是调用 了self.handleStatusDefault这个函数，这个函数只将self.failed这个成员附为1，视为错误情况，然后不处理。<br />
问题就出在这里，这时候与web server的链接还保持着，但是它并没有将收到的数据返回给上层调用，而是一直阻塞在socket.recv里，等着接收body，但是当没有body时，就会一直等到超时或者web server断掉连接才返回。<br />
知道问题就好改了，直接将handleStatusDefault这个函数的定义改为如下：<br />
<a href="http://www.colaghost.com/wp-content/uploads/2012/03/2.jpg"><img class="aligncenter size-full wp-image-227" title="2" src="http://www.colaghost.com/wp-content/uploads/2012/03/2.jpg" alt="" width="255" height="77" /></a></p>
<p>即在不存在content-length这个字段（当self.length==None时没有这个字段）或者值为0时直接返回响应。</p>
<p>更新代码，再次上线，很诡异的时候，uclb（f5后面的请求分发进程，进行会话保持）没有出现超时的情况，但监控组的同学依然表示还是一样，监控到的时延还是很大。<br />
既然不是304导致的，那还会是什么问题呢？为什么用手机连到生产环境都没有问题，测试时也没有发现这个问题，偏偏监控时就会有问题呢？难道是监控脚本的问题？<br />
试着让监控的同学对监控脚本发起请求的过程进行抓包，发现问题出在302响应里，每次加速器返回302头部给监控脚本时，监控脚本并不会马上跳转，而是会明显停顿4、5秒。但是监控脚本直接绕过加速器却没有这个问题，将两次抓包对比了下，发现经过加速器时返回的302 body部分不见了，但是还是带有content-length这个字段。看来监控时会有延长的原因找到了，监控脚本收到302时一直在等待接收body，但是加速器却没有返回body，导致每次耗时爆涨。<br />
看来问题还是出在twisted里，果然，twisted在处理302时并不接收body部分（不管有没有content-length字段），直接在接收完头部时断掉与web server的连接，并返回数据给上层调用。看下代码：<br />
<a href="http://www.colaghost.com/wp-content/uploads/2012/03/3.jpg"><img class="aligncenter size-full wp-image-228" title="3" src="http://www.colaghost.com/wp-content/uploads/2012/03/3.jpg" alt="" width="515" height="419" /></a></p>
<p>原因找到了，这时候不返回body其实对于普通的浏览器来说都是没有问题的，因为它们根据头部里的location字段就可以进行跳转了，但是监控脚本太死板了，一直要等到body回来直到超时才肯乖乖去跳转。这时候也就加入处理302的函数了，在有body的情况下进行处理，以下是我的处理函数：<br />
<a href="http://www.colaghost.com/wp-content/uploads/2012/03/4.jpg"><img class="aligncenter size-full wp-image-229" title="4" src="http://www.colaghost.com/wp-content/uploads/2012/03/4.jpg" alt="" width="222" height="76" /></a></p>
<p>跟handleStatusDefault是一致的。</p>
<p>再次更新上线，这次监控脚本终于正常了。</p>
<p><strong>后记：</strong><br />
这里不由得有一个思考，为何twisted在处理302跳转时会直接去掉body部分呢？一个猜想就是其实根据头部已经有足够的信息了，忽略掉body可以加快速度，但是这样对于标准来说是否合适？<br />
另外一个问题就是，twisted在接收body数据时为什么不首先判断一下是否存在content-length或者长度是否为0再决定是否要马上返回响应或者是继续等待web server的响应数据呢？我们再回过头来看下它底层的接收函数：<br />
<a href="http://www.colaghost.com/wp-content/uploads/2012/03/5.jpg"><img class="aligncenter size-full wp-image-230" title="5" src="http://www.colaghost.com/wp-content/uploads/2012/03/5.jpg" alt="" width="444" height="156" /></a></p>
<p>rawDataReceived是在dataReceived被调用时且已经收完头部数据了被调用的，这时候不管是不是存在body，程序也都会一直在等待数据响应直到超时或连接断掉。这难道是twisted认为这种情况应该由开发者自己去处理？</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/python/222/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>archlinux下给cpu和显卡节能设置</title>
		<link>http://www.colaghost.com/os/unix_linux/219</link>
		<comments>http://www.colaghost.com/os/unix_linux/219#comments</comments>
		<pubDate>Sun, 28 Aug 2011 06:46:25 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[archlinux]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[温度]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=219</guid>
		<description><![CDATA[最近在折腾archlinux，把内核更新到3.0后，发现A卡的官方驱动上不了了，只能上下开源的驱动了，无奈开源驱动的电源管理实在不敢恭维，笔记本键盘部分老是暴热，受不鸟。
下面就从cpu和显卡两个发热大户入手吧！
1、显卡降低频率
从内核2.6.35起就加入了AMD开源驱动的电源管理，可以进行GPU频率调整、显存频率调整、电压调整和温度监控支持等。
我的是A卡，这时候就发挥了它的作用了。
可以用如下命令查看当前显卡的电源管理模式：
$ cat /sys/class/drm/card0/device/power_profile
默认的是&#8221;default&#8221;，这个使用显卡默认频率不做调整。可以将它改为auto,low,mid,high等模式，auto可以根据当前是使用电池或者电源来自动做调整。这里我将它设置为low，注意有的本本设置为low可能导致部分显示问题。
# echo low &#62; /sys/class/drm/card0/device/power_profile
注意这个设置只在当前运行时立即生效，要在下次启动时也有效的话可以手动将它加进/etc/rc.local配置文件里。
2、CPU动态调节频率功能
查了下有cpufrequtils这个小工具，可以实现自动/手动调节CPU频率，对于笔记本来说是很有用的。
通过pacman安装即可。
$ pacman -S cpufrequtils
安装完后先手动加载驱动。
# modprobe acpi-cpufreq
为了下次启动时自动加载可以把它加到/etc/rc.conf配置文件的MODULES列。
加载完驱动后，可以执行cpureq-info查看下cpu信息。
cpufreq提供了好几个电源调整方案，我用的是cpufreq_ondemand，这个可以根据系统负载动态调整CPU频率，这个也需要加入/etc/rc.conf的MODULES列里。
最后还需要配置下/etc/rc.d/cpufreq，将#governor=&#8221;ondemand&#8221;那句取消注释后保存即可。
设置好配置文件后，可以运行以下命令来启动守护进程：
# /etc/rc.d/cpufreq start
启动后再执行下cpufreq-info看看当前频率是不是已经降下来了！
若要在启动时自动守护进程，要将cpufreq加入/etc/rc.conf配置文件的DEAMONS列里。
总结
这样设置后温度大概会比原来降低十度左右，不过貌似还是没有安装闭源驱动fglrx时温度低，但总算没那么烫手了！
]]></description>
			<content:encoded><![CDATA[<p>最近在折腾archlinux，把内核更新到3.0后，发现A卡的官方驱动上不了了，只能上下开源的驱动了，无奈开源驱动的电源管理实在不敢恭维，笔记本键盘部分老是暴热，受不鸟。</p>
<p>下面就从cpu和显卡两个发热大户入手吧！</p>
<h2><strong>1、显卡降低频率</strong></h2>
<p>从内核2.6.35起就加入了AMD开源驱动的电源管理，可以进行GPU频率调整、显存频率调整、电压调整和温度监控支持等。</p>
<p>我的是A卡，这时候就发挥了它的作用了。</p>
<p>可以用如下命令查看当前显卡的电源管理模式：</p>
<p>$ cat /sys/class/drm/card0/device/power_profile</p>
<p>默认的是&#8221;default&#8221;，这个使用显卡默认频率不做调整。可以将它改为auto,low,mid,high等模式，auto可以根据当前是使用电池或者电源来自动做调整。这里我将它设置为low，注意有的本本设置为low可能导致部分显示问题。</p>
<p># echo low &gt; /sys/class/drm/card0/device/power_profile</p>
<p>注意这个设置只在当前运行时立即生效，要在下次启动时也有效的话可以手动将它加进/etc/rc.local配置文件里。</p>
<h2><strong>2、CPU动态调节频率功能</strong></h2>
<p>查了下有cpufrequtils这个小工具，可以实现自动/手动调节CPU频率，对于笔记本来说是很有用的。</p>
<p>通过pacman安装即可。</p>
<p>$ pacman -S cpufrequtils</p>
<p>安装完后先手动加载驱动。</p>
<p># modprobe acpi-cpufreq</p>
<p>为了下次启动时自动加载可以把它加到/etc/rc.conf配置文件的MODULES列。</p>
<p>加载完驱动后，可以执行cpureq-info查看下cpu信息。</p>
<p>cpufreq提供了好几个电源调整方案，我用的是cpufreq_ondemand，这个可以根据系统负载动态调整CPU频率，这个也需要加入/etc/rc.conf的MODULES列里。</p>
<p>最后还需要配置下/etc/rc.d/cpufreq，将#governor=&#8221;ondemand&#8221;那句取消注释后保存即可。</p>
<p>设置好配置文件后，可以运行以下命令来启动守护进程：</p>
<p># /etc/rc.d/cpufreq start</p>
<p>启动后再执行下cpufreq-info看看当前频率是不是已经降下来了！</p>
<p>若要在启动时自动守护进程，要将cpufreq加入/etc/rc.conf配置文件的DEAMONS列里。</p>
<h2><strong>总结</strong></h2>
<p>这样设置后温度大概会比原来降低十度左右，不过貌似还是没有安装闭源驱动fglrx时温度低，但总算没那么烫手了！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/os/unix_linux/219/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UC小记</title>
		<link>http://www.colaghost.com/life/217</link>
		<comments>http://www.colaghost.com/life/217#comments</comments>
		<pubDate>Sun, 17 Jul 2011 15:47:51 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[uc]]></category>
		<category><![CDATA[工作]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=217</guid>
		<description><![CDATA[到uc上班已经一个半月了，貌似打酱油的成分比较多， 这里说一下自己的感受吧。
氛围
技术氛围比较好，平时吃饭、中午休息时都会遇到一些同学（UC是大五文化，同事间称同学~）激烈的讨论声，这让我一次跟入职指引人笑说UC的技术讨论火药味比较重！
部门研发经理和主管都在我这边，没有什么上下级概念。对研发经理的印象最好了，当时面试我的就是他，脸上一直有笑容，平时一起吃饭时也总是笑着说话，让我感觉很舒服。
python
当时一直跟一个在UC的同学笑说内推我去UC写Python好了，没想到现在真的实现了。
得益于python的简洁性，工作时上手会快一些。要是是纯C++，光是了解语言特性本身就是一个挺高的门槛了。虽说总是自从为C++学得不错，像模板啊、对象模型这些都了解得不错，但是真看起一些国外的C++写的开源包，有时候还是被一些用法弄得糊里糊涂的。
小红花
小红花就差不多是一种鼓励、感谢的象征吧，这是UC文化的一部分。当你想鼓励一个人，或者别人在工作上（也可以是其他的）帮助了你，你就可以贴一朵小红花（写上原因）在他的办公桌上。
说真的，当时觉得这玩意儿有点傻，看旁边的人也都没有怎么动过这些东西，也就一直扔在桌旁一角。有一天上班时，竟然发现被贴了一朵小红花。当时还在YY是哪个女的贴的，看了一下才知道是小组主管贴的，说在最近的项目任务上完成得不错，上手很快，有点飘飘然的感觉了。
分享会
这个对我来说还是比较新鲜的，之前实习时一直没有这样类似的会议。
分享是局部于部门内，一周一次，小组里的每周轮流确定分享的技术心得。分享的人可能会辛苦点，因为可能随时被打乱，回答别人的疑问或者是听取别人的见解，往往是口头说得不爽了就动手了，直接拿起笔在白板上画，最后画的总会被XX得乱七八糟。
迷惑
貌似感觉这个半个月来进展很慢，没有方向，每天看看文档，看看代码，却发觉没有一个具体的目标，代码很多也看不懂，只能一边坚持看着，一边google下有没有相关的文档，很多时候找到的都是英文的，说句不好听的真的是看英文看到想吐了。
有一个感觉就是在一个小的范围内，如线程管理，假设集中于阅读这一方面的代码，能够很有sense，最终在小组某些同学的帮助下也大概能看懂。但是假设范围拉得太宽，没有一个集中的点，往往是搞了半天不知所云。想要集中一个方向，却发现在没有其他人的指引下一时找不到前进的方向，这让我相当迷惑和纠结。
也许我应该主动点，一个人看文档和看代码太闷，往往也会因为看不懂而看不下去，应该主动寻求其他同学的帮助，让入职引领人给我做一 些关于系统模块和各个流程的讲解，这样再来看代码，或许会更有效。
]]></description>
			<content:encoded><![CDATA[<p>到uc上班已经一个半月了，貌似打酱油的成分比较多， 这里说一下自己的感受吧。</p>
<h2><stong>氛围</stong></h2>
<p>技术氛围比较好，平时吃饭、中午休息时都会遇到一些同学（UC是大五文化，同事间称同学~）激烈的讨论声，这让我一次跟入职指引人笑说UC的技术讨论火药味比较重！</p>
<p>部门研发经理和主管都在我这边，没有什么上下级概念。对研发经理的印象最好了，当时面试我的就是他，脸上一直有笑容，平时一起吃饭时也总是笑着说话，让我感觉很舒服。</p>
<h2><stong>python</stong></h2>
<p>当时一直跟一个在UC的同学笑说内推我去UC写Python好了，没想到现在真的实现了。</p>
<p>得益于python的简洁性，工作时上手会快一些。要是是纯C++，光是了解语言特性本身就是一个挺高的门槛了。虽说总是自从为C++学得不错，像模板啊、对象模型这些都了解得不错，但是真看起一些国外的C++写的开源包，有时候还是被一些用法弄得糊里糊涂的。</p>
<h2><stong>小红花</stong></h2>
<p>小红花就差不多是一种鼓励、感谢的象征吧，这是UC文化的一部分。当你想鼓励一个人，或者别人在工作上（也可以是其他的）帮助了你，你就可以贴一朵小红花（写上原因）在他的办公桌上。</p>
<p>说真的，当时觉得这玩意儿有点傻，看旁边的人也都没有怎么动过这些东西，也就一直扔在桌旁一角。有一天上班时，竟然发现被贴了一朵小红花。当时还在YY是哪个女的贴的，看了一下才知道是小组主管贴的，说在最近的项目任务上完成得不错，上手很快，有点飘飘然的感觉了。</p>
<h2><stong>分享会</stong></h2>
<p>这个对我来说还是比较新鲜的，之前实习时一直没有这样类似的会议。</p>
<p>分享是局部于部门内，一周一次，小组里的每周轮流确定分享的技术心得。分享的人可能会辛苦点，因为可能随时被打乱，回答别人的疑问或者是听取别人的见解，往往是口头说得不爽了就动手了，直接拿起笔在白板上画，最后画的总会被XX得乱七八糟。</p>
<h2><stong>迷惑</stong></h2>
<p>貌似感觉这个半个月来进展很慢，没有方向，每天看看文档，看看代码，却发觉没有一个具体的目标，代码很多也看不懂，只能一边坚持看着，一边google下有没有相关的文档，很多时候找到的都是英文的，说句不好听的真的是看英文看到想吐了。</p>
<p>有一个感觉就是在一个小的范围内，如线程管理，假设集中于阅读这一方面的代码，能够很有sense，最终在小组某些同学的帮助下也大概能看懂。但是假设范围拉得太宽，没有一个集中的点，往往是搞了半天不知所云。想要集中一个方向，却发现在没有其他人的指引下一时找不到前进的方向，这让我相当迷惑和纠结。</p>
<p>也许我应该主动点，一个人看文档和看代码太闷，往往也会因为看不懂而看不下去，应该主动寻求其他同学的帮助，让入职引领人给我做一 些关于系统模块和各个流程的讲解，这样再来看代码，或许会更有效。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/life/217/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个典型的Twisted服务端应用程序</title>
		<link>http://www.colaghost.com/python/212</link>
		<comments>http://www.colaghost.com/python/212#comments</comments>
		<pubDate>Sun, 12 Jun 2011 11:36:43 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Twisted]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=212</guid>
		<description><![CDATA[简介
一个典型的twisted服务端应用程序一般包括三部分，分别是协议、工厂和启动服务器，其中协议负责接管建立连接后的工作，包括收发数据和决定是否关闭连接等；工厂的工作是管理连接事件。
这里是通过继承Twisted中的一些类来实现的！
基本框架
导入部分
这部分主要是供协议类和工厂类使用的

1
2
from twisted.internet import protocol
from twisted.protocols import baisc

协议
继承自basic.LineReceiver，可以进行行和原始数据两种方式的接收处理。

1
2
3
4
5
6
7
class Answer&#40;LineReceiver&#41;:
    def lineReceived&#40;self, line&#41;:
        #行数据接收处理方式
        pass
    def dataReceived&#40;self, data&#41;:
        #原始数据接收处理方式
        pass

工厂
继承自protocol.ServerFactory。

1
2
3
4
5
6
7
8
9
10
11
12
class AnswerServerFactory&#40;protocol.ServerFactory&#41;:
   [...]]]></description>
			<content:encoded><![CDATA[<h2><strong>简介</strong></h2>
<p>一个典型的twisted服务端应用程序一般包括三部分，分别是协议、工厂和启动服务器，其中协议负责接管建立连接后的工作，包括收发数据和决定是否关闭连接等；工厂的工作是管理连接事件。</p>
<p>这里是通过继承Twisted中的一些类来实现的！</p>
<h2><strong>基本框架</strong></h2>
<p><span style="text-decoration: underline;">导入部分</span></p>
<p>这部分主要是供协议类和工厂类使用的</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> protocol
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">protocols</span> <span style="color: #ff7700;font-weight:bold;">import</span> baisc</pre></td></tr></table></div>

<p><span style="text-decoration: underline;">协议</span></p>
<p>继承自basic.LineReceiver，可以进行行和原始数据两种方式的接收处理。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Answer<span style="color: black;">&#40;</span>LineReceiver<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> lineReceived<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, line<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;">#行数据接收处理方式</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> dataReceived<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, data<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;">#原始数据接收处理方式</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p><span style="text-decoration: underline;">工厂</span></p>
<p>继承自protocol.ServerFactory。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> AnswerServerFactory<span style="color: black;">&#40;</span>protocol.<span style="color: black;">ServerFactory</span><span style="color: black;">&#41;</span>:
    protocol=Answer<span style="color: #808080; font-style: italic;">#表明每次成功建立连接时要实例的协议类型</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> startFactory<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;">#在开始监听一个端口或连接器时被调用</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> stopFactory<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;">#在停止监听所有端口或连接器时被调用</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
    <span style="color: #ff7700;font-weight:bold;">def</span>  buildProtocol<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, addr<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;">#实例化Protocol的子类</span>
        protocol.<span style="color: black;">ServerFactory</span>.<span style="color: black;">buildProtocol</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, add<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p><span style="text-decoration: underline;">启动服务器</span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> reactor
reactor.<span style="color: black;">listenTCP</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">8000</span>,AnswerServerFactory<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
reactor.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>其中reactor是一个反应器，它主要用于实现事件循环，除了分发事件循环之外，还需做：定时任务、线程、建立网络连接和监听连接等。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/python/212/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ubuntu下自动切换声音输出设备</title>
		<link>http://www.colaghost.com/os/unix_linux/207</link>
		<comments>http://www.colaghost.com/os/unix_linux/207#comments</comments>
		<pubDate>Fri, 13 May 2011 13:20:05 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[Shell]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[pulseaudio]]></category>
		<category><![CDATA[声音设备]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=207</guid>
		<description><![CDATA[我有一个usb耳机，在ubuntu下驱动也正常，不过有一个蛋疼的地方就是每次插进usb耳机都不会自动切换到usb耳机对应的声音输出设备，次次都要手动去选择对应的，于是想着能不能写一个脚本来实现。
不过貌似关于这方面的中文资料不多，google了很久都没有什么结果，倒是找出一个freebsd上能实现的，就是sysctl，不过貌似ubuntu下实现不了。后来在stackoverflow上问老外才得知用pacmd可以列出各种可用的声音输出设备还有设置默认输出设备等操作神马的。
弄了一下，果真OK了，写随意写了一个脚本来测试了，这个脚本假设系统使用pulseaudio的。
原理也不难，就是检测所有的声音设备，找出当前默认的声音设备，然后把声音设备切换到下一个，重新运行脚本就可以把声音设备切换回原来默认的了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash
&#160;
declare -i count=`pacmd list-sinks &#124; grep -c index:&#91;&#91;:space:&#93;&#93;&#91;&#91;:digit:&#93;&#93;`
declare -i active=`pacmd list-sinks &#124; sed -n -e 's/\*[[:space:]]index:[[:space:]]\([[:digit:]]\)/\1/p'`
declare -i major=$count-1
declare -i next=0
&#160;
if &#91; $active -ne $major &#93; ; then
next=active+1
fi
&#160;
pacmd &#34;set-default-sink ${next}&#34;
&#160;
for app in $&#40;pacmd list-sink-inputs &#124; sed -n -e 's/index:[[:space:]]\([[:digit:]]\)/\1/p'&#41;;
do
pacmd &#34;move-sink-input $app $next&#34;
done
&#160;
declare -i ndx=0
pacmd list-sinks &#124; sed -n -e 's/device.description[[:space:]]=[[:space:]]&#34;\(.*\)&#34;/\1/p' &#124; while read line;
do
if &#91; $next [...]]]></description>
			<content:encoded><![CDATA[<p>我有一个usb耳机，在ubuntu下驱动也正常，不过有一个蛋疼的地方就是每次插进usb耳机都不会自动切换到usb耳机对应的声音输出设备，次次都要手动去选择对应的，于是想着能不能写一个脚本来实现。<br />
不过貌似关于这方面的中文资料不多，google了很久都没有什么结果，倒是找出一个freebsd上能实现的，就是sysctl，不过貌似ubuntu下实现不了。后来在stackoverflow上问老外才得知用pacmd可以列出各种可用的声音输出设备还有设置默认输出设备等操作神马的。<br />
弄了一下，果真OK了，写随意写了一个脚本来测试了，这个脚本假设系统使用pulseaudio的。<br />
原理也不难，就是检测所有的声音设备，找出当前默认的声音设备，然后把声音设备切换到下一个，重新运行脚本就可以把声音设备切换回原来默认的了。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">declare</span> <span style="color: #660033;">-i</span> <span style="color: #007800;">count</span>=<span style="color: #000000; font-weight: bold;">`</span>pacmd list-sinks <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-c</span> index:<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span>:space:<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span>:digit:<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #7a0874; font-weight: bold;">declare</span> <span style="color: #660033;">-i</span> <span style="color: #007800;">active</span>=<span style="color: #000000; font-weight: bold;">`</span>pacmd list-sinks <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/\*[[:space:]]index:[[:space:]]\([[:digit:]]\)/\1/p'</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #7a0874; font-weight: bold;">declare</span> <span style="color: #660033;">-i</span> <span style="color: #007800;">major</span>=<span style="color: #007800;">$count</span>-<span style="color: #000000;">1</span>
<span style="color: #7a0874; font-weight: bold;">declare</span> <span style="color: #660033;">-i</span> <span style="color: #007800;">next</span>=<span style="color: #000000;">0</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$active</span> <span style="color: #660033;">-ne</span> <span style="color: #007800;">$major</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
<span style="color: #007800;">next</span>=active+<span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
pacmd <span style="color: #ff0000;">&quot;set-default-sink <span style="color: #007800;">${next}</span>&quot;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">for</span> app <span style="color: #000000; font-weight: bold;">in</span> $<span style="color: #7a0874; font-weight: bold;">&#40;</span>pacmd list-sink-inputs <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/index:[[:space:]]\([[:digit:]]\)/\1/p'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">do</span>
pacmd <span style="color: #ff0000;">&quot;move-sink-input <span style="color: #007800;">$app</span> <span style="color: #007800;">$next</span>&quot;</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">declare</span> <span style="color: #660033;">-i</span> <span style="color: #007800;">ndx</span>=<span style="color: #000000;">0</span>
pacmd list-sinks <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-n</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">'s/device.description[[:space:]]=[[:space:]]&quot;\(.*\)&quot;/\1/p'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #c20cb9; font-weight: bold;">read</span> line;
<span style="color: #000000; font-weight: bold;">do</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$next</span> <span style="color: #660033;">-eq</span> <span style="color: #007800;">$ndx</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
notify-send <span style="color: #660033;">-i</span> notification-audio-volume-high <span style="color: #ff0000;">&quot;声音输出切换到&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$line</span>&quot;</span>
<span style="color: #7a0874; font-weight: bold;">exit</span>
<span style="color: #000000; font-weight: bold;">fi</span>
ndx+=<span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">done</span>;</pre></td></tr></table></div>

<p>脚本里在切换后会做notify-send的提示，假设找不到命令的可以执行sudo apt-get install libnotify-bin安装一下，但不安装也没有什么关系，只是一个提示而已。</p>
<p>为了方便可以将脚本复制到/usr/bin目录下，然后在“键盘快捷键”里面添加多一个快捷键，命令就是脚本名了，最后设定好想要的快捷键，以后就可以直接切换了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/os/unix_linux/207/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ubuntu下看flash视频时禁用屏保</title>
		<link>http://www.colaghost.com/os/unix_linux/199</link>
		<comments>http://www.colaghost.com/os/unix_linux/199#comments</comments>
		<pubDate>Sat, 23 Apr 2011 12:47:49 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[Shell]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[screensaver]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=199</guid>
		<description><![CDATA[最近两天在啃《unix环境高级编程》，一直转在ubuntu下。我吃饭时喜欢一边看电影，可是上优酷看flash视频时又有一个麻烦的地方，就是屏保并不会自动被禁用掉，而是得手动去禁用，看完又得去把它开启，甚是麻烦，就想着自己写一个脚本来实现开启/禁用屏保。
Google了下，关于这方面的结果倒是不少，下面是其中一个脚本：

1
2
3
4
5
6
7
8
#!/bin/sh
while true;
do
    if test -n &#34;`file /tmp/Flash*&#124;grep \&#34;Macromedia Flash Video\\&#124;MPEG v4\&#34;`&#34;;then
        gnome-screensaver-command -p
    fi
    sleep 30
done

可惜我发现我的tmp目录下并不会生成/tmp/Flash*，我原先以为是我用shockwave flash的原因，不是在tmp目录下生成缓存。就自己搜索任何可能的目录，看下具体在哪个目录里生成缓存，可惜找不到。
这时候想到linux下是可以通过lsof来监测某一个进程当前打开了哪些文件，结果发现了其实是有在/tmp目录下生成Flash*这样的文件的，只是生成后马上又被删除了，这时候虽说进程还可以进行读写操作，可是在目录下却无法看到。
因此想到了另外一种方法，由于shockwave flash做为chrome下的一个插件，只要监测到chrome载入libgcflashplayer.so的这一个进程打开的所有文件下有/tmp/Flash*类似的文件即可知道当前在播放flash视频，这时候只要运行&#8221;gnome-screensaver-commad -p&#8221;模拟活动一下即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
while true;
do
	pid=`ps aux &#124; grep /opt/google/chrome/libgcflashplayer.so &#124; grep -v grep &#124; awk '{print $2}'`
	if &#91; &#34;$pid&#34; != &#34;&#34; &#93;; then
		data=`lsof -p [...]]]></description>
			<content:encoded><![CDATA[<p>最近两天在啃《unix环境高级编程》，一直转在ubuntu下。我吃饭时喜欢一边看电影，可是上优酷看flash视频时又有一个麻烦的地方，就是屏保并不会自动被禁用掉，而是得手动去禁用，看完又得去把它开启，甚是麻烦，就想着自己写一个脚本来实现开启/禁用屏保。</p>
<p>Google了下，关于这方面的结果倒是不少，下面是其中一个脚本：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #c20cb9; font-weight: bold;">true</span>;
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #780078;">`file /tmp/Flash*|grep \&quot;Macromedia Flash Video\\|MPEG v4\&quot;`</span>&quot;</span>;<span style="color: #000000; font-weight: bold;">then</span>
        gnome-screensaver-command <span style="color: #660033;">-p</span>
    <span style="color: #000000; font-weight: bold;">fi</span>
    <span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #000000;">30</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

<p>可惜我发现我的tmp目录下并不会生成/tmp/Flash*，我原先以为是我用shockwave flash的原因，不是在tmp目录下生成缓存。就自己搜索任何可能的目录，看下具体在哪个目录里生成缓存，可惜找不到。</p>
<p>这时候想到linux下是可以通过lsof来监测某一个进程当前打开了哪些文件，结果发现了其实是有在/tmp目录下生成Flash*这样的文件的，只是生成后马上又被删除了，这时候虽说进程还可以进行读写操作，可是在目录下却无法看到。</p>
<p>因此想到了另外一种方法，由于shockwave flash做为chrome下的一个插件，只要监测到chrome载入libgcflashplayer.so的这一个进程打开的所有文件下有/tmp/Flash*类似的文件即可知道当前在播放flash视频，这时候只要运行&#8221;gnome-screensaver-commad -p&#8221;模拟活动一下即可。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #c20cb9; font-weight: bold;">true</span>;
<span style="color: #000000; font-weight: bold;">do</span>
	<span style="color: #007800;">pid</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">ps</span> aux <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>google<span style="color: #000000; font-weight: bold;">/</span>chrome<span style="color: #000000; font-weight: bold;">/</span>libgcflashplayer.so <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-v</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #ff0000;">'{print $2}'</span><span style="color: #000000; font-weight: bold;">`</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$pid</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #007800;">data</span>=<span style="color: #000000; font-weight: bold;">`</span>lsof <span style="color: #660033;">-p</span> <span style="color: #007800;">$pid</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>Flash<span style="color: #000000; font-weight: bold;">`</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$data</span>&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
			<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;gnome-screensaver-command&quot;</span>
			gnome-screensaver-command <span style="color: #660033;">-p</span>
		<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #000000; font-weight: bold;">fi</span>
	<span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #000000;">30</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/os/unix_linux/199/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>深信服实习结束</title>
		<link>http://www.colaghost.com/life/193</link>
		<comments>http://www.colaghost.com/life/193#comments</comments>
		<pubDate>Sat, 16 Apr 2011 06:38:43 +0000</pubDate>
		<dc:creator>colaghost</dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[实习]]></category>
		<category><![CDATA[深信服]]></category>

		<guid isPermaLink="false">http://www.colaghost.com/?p=193</guid>
		<description><![CDATA[两个月的期限到了，公司其实鼓励我们继续实习下去，但是接下去学校的一些事，加上一些累的情绪，还是早早选择回校了。这里说下两个月来的感受吧。
氛围
跟之前了解的一样，深信服从观念上有点类似于硅谷的企业，比较平民化，相对自由，没有明显的上下级观念，大家都是直呼名字，就算是主管人家也会拿来开玩笑，不要求应届生一定要拿到毕业证，上班不需要打卡，主管神马的都没有独立的办公室，甚至RDM的人都跟我们AC产品部门的在同一个大厅里，只是办公位置相对分隔开而已。
公司创始人来源于华为，这个对公司的加班文化有很大影响，高层总是强调危机感，强调现在还达不到不用加班就能保持竞争力的地步。我们现在周一、二、四都是要加班的，周末的话也是隔周就要上半天。很多人其实对这个硬性规定不爽的，其实我觉得可以放开这条规定，毕竟很多人其实都很拼周一到周五都会留到很晚才回去，硬性规定给人感觉上多多少少有点不信任的感觉。
定制
这是我所在部门的小组，其实就是满足客户一些特殊需求在正式版本上添加一些小功能，每个任务周期都很短，一般都是一个星期左右。
这个小组是部门里做的活最杂最累的，任务多，接触面杂，从linux底层驱动到前端js都有可能让你做。不过也拜这个所赐，让我在短短两个月里接触了js、php和CGI等，虽说比较分散，但从一定程度上拓宽了我的水平。也是从这里才开始明白，其实用什么语言写程序并不重要，更重要的是你的思路，你分析问题的能力，还有你的学习能力。
我导师有时候说，在定制组还是有好处的，以前不会去做的东西现在都做了，绩效也好写，毕竟做的任务多，随便一拈都有不少。当然这个也有玩笑的成分在，不过对于刚来的人还是有一定好处的，不会让自己限死在一个方向和模块。
注重
由于之前公司可能更多考虑的是生存，部门产品的旧版本代码实现比较乱，注重功能，却忽视了后期的可维护性。这貌似是很多新员工刚来纠结的问题，一个函数可以写上千行，然后不加一句注释，这不是让人吐血么？有能力做到一秒钟处理10G流量的数据包，却不愿意多写几行注释，不写注释害死后来者啊。不过现在公司也在开始考虑这个问题了，也有专门的小组在重构整个产品的代码了，不过三百万行级的代码量，似乎还没加上底层驱动，估计也得耗费很长一段时间。
学习
在深信服每个人成长都很快，这跟压力有关，也跟公司的技术和规模快速发展有关。
深信服貌似在技术培训上比较少，更多是依赖于个人的自己学习和与周边人的交流分享。
公司有内部自己的类似于技术文刊那样子的东西，主要都是重大技术突破、编码经验和一些创新点上的东西。产品每个核心模块都会录制相关视频，讲解它的设计，主要数据结构跟运用算法等等东西。
我们部门的副主管弄了一个AC产品知识库，主要是面向于新员工，里面包含了培训文档、员工成长练习题库，以及产品周边的各种基本知识PPT和产品用到的各种技术文档，甚至还有CGI的编写和LINUX驱动开发规范等。
公司里所有的核心技术跟代码都毫无保留地向所有员工公开，这点个人觉得做得比较好，你对哪块有兴趣你都可以自己拿代码跟文档去研究，公司也倾向于培养各个模块的专家，以便有人接手各个模块。
]]></description>
			<content:encoded><![CDATA[<p>两个月的期限到了，公司其实鼓励我们继续实习下去，但是接下去学校的一些事，加上一些累的情绪，还是早早选择回校了。这里说下两个月来的感受吧。</p>
<h2><strong>氛围</strong></h2>
<p>跟之前了解的一样，深信服从观念上有点类似于硅谷的企业，比较平民化，相对自由，没有明显的上下级观念，大家都是直呼名字，就算是主管人家也会拿来开玩笑，不要求应届生一定要拿到毕业证，上班不需要打卡，主管神马的都没有独立的办公室，甚至RDM的人都跟我们AC产品部门的在同一个大厅里，只是办公位置相对分隔开而已。</p>
<p>公司创始人来源于华为，这个对公司的加班文化有很大影响，高层总是强调危机感，强调现在还达不到不用加班就能保持竞争力的地步。我们现在周一、二、四都是要加班的，周末的话也是隔周就要上半天。很多人其实对这个硬性规定不爽的，其实我觉得可以放开这条规定，毕竟很多人其实都很拼周一到周五都会留到很晚才回去，硬性规定给人感觉上多多少少有点不信任的感觉。</p>
<h2><strong>定制</strong></h2>
<p>这是我所在部门的小组，其实就是满足客户一些特殊需求在正式版本上添加一些小功能，每个任务周期都很短，一般都是一个星期左右。</p>
<p>这个小组是部门里做的活最杂最累的，任务多，接触面杂，从linux底层驱动到前端js都有可能让你做。不过也拜这个所赐，让我在短短两个月里接触了js、php和CGI等，虽说比较分散，但从一定程度上拓宽了我的水平。也是从这里才开始明白，其实用什么语言写程序并不重要，更重要的是你的思路，你分析问题的能力，还有你的学习能力。</p>
<p>我导师有时候说，在定制组还是有好处的，以前不会去做的东西现在都做了，绩效也好写，毕竟做的任务多，随便一拈都有不少。当然这个也有玩笑的成分在，不过对于刚来的人还是有一定好处的，不会让自己限死在一个方向和模块。</p>
<h2><strong>注重</strong></h2>
<p>由于之前公司可能更多考虑的是生存，部门产品的旧版本代码实现比较乱，注重功能，却忽视了后期的可维护性。这貌似是很多新员工刚来纠结的问题，一个函数可以写上千行，然后不加一句注释，这不是让人吐血么？有能力做到一秒钟处理10G流量的数据包，却不愿意多写几行注释，不写注释害死后来者啊。不过现在公司也在开始考虑这个问题了，也有专门的小组在重构整个产品的代码了，不过三百万行级的代码量，似乎还没加上底层驱动，估计也得耗费很长一段时间。</p>
<h2><strong>学习</strong></h2>
<p>在深信服每个人成长都很快，这跟压力有关，也跟公司的技术和规模快速发展有关。</p>
<p>深信服貌似在技术培训上比较少，更多是依赖于个人的自己学习和与周边人的交流分享。</p>
<p>公司有内部自己的类似于技术文刊那样子的东西，主要都是重大技术突破、编码经验和一些创新点上的东西。产品每个核心模块都会录制相关视频，讲解它的设计，主要数据结构跟运用算法等等东西。</p>
<p>我们部门的副主管弄了一个AC产品知识库，主要是面向于新员工，里面包含了培训文档、员工成长练习题库，以及产品周边的各种基本知识PPT和产品用到的各种技术文档，甚至还有CGI的编写和LINUX驱动开发规范等。</p>
<p>公司里所有的核心技术跟代码都毫无保留地向所有员工公开，这点个人觉得做得比较好，你对哪块有兴趣你都可以自己拿代码跟文档去研究，公司也倾向于培养各个模块的专家，以便有人接手各个模块。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.colaghost.com/life/193/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

