??xml version="1.0" encoding="utf-8" standalone="yes"?>久久精品a亚洲国产v高清不卡,精品国产青草久久久久福利,久久无码AV中文出轨人妻http://www.shnenglu.com/ifeng/category/17826.htmlzh-cnTue, 10 Jan 2012 05:22:01 GMTTue, 10 Jan 2012 05:22:01 GMT60FastCGIq行模型学习(fn)ȝhttp://www.shnenglu.com/ifeng/archive/2012/01/05/163635.html冷锋冷锋Thu, 05 Jan 2012 08:58:00 GMThttp://www.shnenglu.com/ifeng/archive/2012/01/05/163635.htmlhttp://www.shnenglu.com/ifeng/comments/163635.htmlhttp://www.shnenglu.com/ifeng/archive/2012/01/05/163635.html#Feedback1http://www.shnenglu.com/ifeng/comments/commentRss/163635.htmlhttp://www.shnenglu.com/ifeng/services/trackbacks/163635.html

FastCGI的工作原?/p>

1、Web Server启动时蝲入FastCGIq程理器(IIS ISAPI或Apache Module)

2、FastCGIq程理器自w初始化Q启动多个CGI解释器进E?可见多个php-cgi)q等待来自Web Server的连接?/p>

3、当客户端请求到达W(wng)eb ServerӞFastCGIq程理器选择q连接到一个CGI解释器。Web serverCGI环境变量和标准输入发送到FastCGI子进Ephp-cgi?/p>

4、FastCGI子进E完成处理后标准输出和错误信息从同一q接q回Web Server。当FastCGI子进E关闭连接时Q请求便告处理完成。FastCGI子进E接着{待q处理来自FastCGIq程理?q行在Web Server?的下一个连接?在CGI模式中,php-cgi在此侉KZ(jin)?/p>

在上q情况中Q你可以惌CGI通常有多慢。每一个WebhPHP都必重新解析php.ini、重新蝲入全部扩展ƈ重初始化全部数据l构。用FastCGIQ所有这些都只在q程启动时发生一ơ。一个额外的好处是,持箋数据库连?Persistent database connection)可以工作?

 

q个很容易找到。也Ҏ(gu)理解Q但是l?/span>google之后Q发现自q概念又模p了(jin)?/span>

比如有些例子?/p>

spawn-fcgi

/usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -C 5 -u root -g root -f /usr/bin/php-cgi

 

参数含义如下

 

  1. -f <fcgiapp> 指定调用FastCGI的进E的执行E序位置Q根据系l上所装的PHP的情况具体设|?/span>
  2. -a <addr> l定到地址addr
  3. -p <port> l定到端口port
  4. -s <path> l定到unix socket的\径path
  5. -C <childs> 指定产生的FastCGI的进E数Q默认ؓ(f)5Q仅用于PHPQ?/span>
  6. -P <path> 指定产生的进E的PID文g路径
  7. -u?g FastCGI使用什么n份(-u 用户 -g 用户l)(j)q行QUbuntu下可以用www-dataQ其他的Ҏ(gu)情况配置Q如nobody、apache{?/span>

 

刚看?/span>FastCGI原理的时候,我想象中的运行模型是Q前端的反向代理服务器如Nginx收到hQ然后{发给cgiq程Q这?/span>cgiq程?/span>N个,从而实现ƈ发处理。但是接下来搜烦(ch)到的C语言实现?/span>FastCGI应用的例子好像又把这个模型给否定?jin)。ƈ?/span>fastcgi是语a无关的,N你要?/span>python写ƈ发?

#include "fcgi_stdio.h"
#include <stdlib.h>
int count;
void initialize(void)
{
    count=0;
}
void main(void)
{
initialize();
 
while (FCGI_Accept() >= 0)   {
   printf("Content-type: text/html“r“n"
     "“r“n"
     "<title>FastCGI Hello! (C, fcgi_stdio library)</title>"
     "<h1>FastCGI Hello! (C, fcgi_stdio library)</h1>"
     "Request number %d running on host <i>%s</i>“n",
     ++count, getenv("SERVER_HOSTNAME"));
    }
}

q个代码看不出来有Q何ƈ发处理的部分。比?/span>fork什么的?/span>

 

 

另外一U模型就是有一U叫做FastCGIq程理器的q程Q就像上面说的是理fastcgiq程的进E,h转发到管理器的时候,由它来进行选择相应的应用进E,卡就卡在q了(jin)Q这个管理器是怎么来选择q程的啊Q假如我?/span>N个不同逻辑的可执行文gQ它怎么知道要{发给哪个q程呢,google到的fastcgi配置都是针对反向代理的后端也即管理器讄的,没有发现有针对不同逻辑发给不同的应用进E的部分?/span>

 

l箋狂搜Q还是无果,都是cM的文章。网上搜索不到的问题Q要么就是很隑־偏,要么是很简单,单到不g提,很显?dng)我属于后者。{换思\Q开始考虑假如要自己来实现q个功能的话该怎么办。一步步地推理,在结合搜索到的文章,大概理清?jin)思\Q我的理解如下,不对的地方请指正?/p>

 

1.有一?/span>CGIq程理器,q个理器一般是用第3方的fastcgi开发套Ӟ比如上面提到?/span>spawn-fcgi Q用它可以启动指定可执行文g?/span>N个实例,关于之前选择q程的疑问,q里可以得到解释Q那是多个q程只是同一个可执行文g的实例,假如你想把不同的模块分开生成可执行文件的话估计就得再启动多一个管理器?jin)吧?/span>

 

2.假如你是?/span>python写的fastcgi的应用程序,那么当你用管理器启动?/span>100个实例的时候,也就相当于启动了(jin)100?/span>python解析器,如果是用C{静态语a写的话那q好Q只是跟你写的程序大有兟?/span>

 

可能是没有接触过CGIE序的原因,让我对这基本的模型都U结?jin)一下午Q希望这文章能帮些初学者?/span>




冷锋 2012-01-05 16:58 发表评论
]]>
服务器多U程Ҏ(gu)的选择http://www.shnenglu.com/ifeng/archive/2011/11/20/160587.html冷锋冷锋Sun, 20 Nov 2011 14:35:00 GMThttp://www.shnenglu.com/ifeng/archive/2011/11/20/160587.htmlhttp://www.shnenglu.com/ifeng/comments/160587.htmlhttp://www.shnenglu.com/ifeng/archive/2011/11/20/160587.html#Feedback11http://www.shnenglu.com/ifeng/comments/commentRss/160587.htmlhttp://www.shnenglu.com/ifeng/services/trackbacks/160587.html
最q想写个多线E模型的服务器,但是一直纠l要选哪U方式,参考了(jin)memcachedQ但是觉得不完美.
备选方案,当然q些都是NIO
1.一个IOU程Q专门处理连接读写数据,一个逻辑U程Q专门处理数据?/div>
2.一个IOU程Q一个线E池Q可L配置U程池的数量?/div>
先考虑1Q假设连接层用epoll的ET模式实现Q当IOU程发生可读事gӞ必须把接收缓冲区的数据全部收完,一直read直到发生EAGAIN错误Q否则就必须自己在上层维护一个可读队列?/div>
Ҏ(gu)a:每收C个协议包Q就转发l逻辑处理.处理完再接着收取剩下的包。但是TCP是无边界的,有可能收?.5个或?.5个包Q这时你得ؓ(f)每个q接准备个buf,q且每收C包都要跟逻辑U程同步加锁一?q有个很大的弊端是Q连接层已经跟逻辑协议相关?jin),q似乎不是很好?/div>
Ҏ(gu)b:IOU程把所有数据都收完再通知逻辑U程。当然这样也无法避免收到半个协议包的情况Q所以我是想l护一个recv到的数据队列QIOU程把每ơ收到的包都丢到q个队列?/div>
a,b2U方法都面(f)着send的麻?ch),现在send也有以下Ҏ(gu).
Ҏ(gu)a.每次需要write的时候就直接send发不完的加到发送队列中厅R在发送前必须要先判断一下队列是不是I,如果不ؓ(f)I就必须先处理队列,剩余数据待可M件发生时再处理,   于是脑子中又出现一大堆锁了(jin)。有2个线E可能对socketq行写操作?/div>
Ҏ(gu)b.每次需要send的时候都直接把数据丢到发送队列去Q等到可M件到来时再尽量把队列都发送完。但是响应可能没那么q速了(jin)?/div>
q两U方法都必须为每个数据包增加一个标识TCPq接的字D,因ؓ(f)socket fd是可以重复用的Q比如用户Aq接分配的socket?00Q逻辑U程正在为A处理数据Q但是用户A断开q接?jin),同时立即有另外个用户q接q来q且分配的socket?00Q这时?zhn)剧就发生了(jin)?/div>
再考虑下线E池?U情?
a.ȝE负责IOQ包括处理连接,dQ把d的数据加入recv队列Q子U程把需要写的加入send队列.
q个Ҏ(gu)有个很大的缺P(x)无法保证先到的请求先q回Q这是很致命的,只能通过客户端来保收到前一个请求的l果以后再发送下一个请求?/div>
b.ȝE只负责监听q接Q收到连接到来事件后Q通知U程池去acceptq接Q因此每个连接的数据都会(x)由同一个线E处理,也就保证?jin)顺序,但是q样的话子线E就必须承担起IO的Q务了(jin)Q这样好像就有些分工不清?jin),q个是memcached中用的方?
PS:用epoll的ET模式需要一直recv,q样有可能是使得z跃的连接占用了(jin)全部带宽Q因此需要在上层对连接进行限速,因此也就需要维护可M件了(jin)?/div>
U结好几天了(jin)Q第一ơ写多线E服务器Q一直ؓ(f)选方案纠l啊Q我本h們֐于线E池Q毕竟可以利用多核的优势啊。不知道大家实际上用的都是什么方案呢Q非常想知道Q请指教?br />再PSQ做?jin)个测试,nginx+memcached,下蝲一?00多K的文Ӟ开100个线E,每个U程下蝲100ơ,全部命中跟全部不命中的情况几乎没有差别,q是Z么呢Q难道linuxpȝ本n已l有cached?jin)吗Q?br />


冷锋 2011-11-20 22:35 发表评论
]]>有关TCP和UDP _包 消息保护边界(?http://www.shnenglu.com/ifeng/archive/2011/11/11/159950.html冷锋冷锋Fri, 11 Nov 2011 02:22:00 GMThttp://www.shnenglu.com/ifeng/archive/2011/11/11/159950.htmlhttp://www.shnenglu.com/ifeng/comments/159950.htmlhttp://www.shnenglu.com/ifeng/archive/2011/11/11/159950.html#Feedback0http://www.shnenglu.com/ifeng/comments/commentRss/159950.htmlhttp://www.shnenglu.com/ifeng/services/trackbacks/159950.html
在socket|络E序中,TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket~程Q收发两端(客户端和服务器端Q都要有一一成对的socketQ因此,发送端Z(jin)多个发往接收端的包,更有效的发到Ҏ(gu)Q用了(jin)优化Ҏ(gu)QNagle法Q,多ơ间隔较?yu)且数据量小的数据,合ƈ成一个大的数据块Q然后进行封包。这P接收端,难于分辨出来了(jin)Q必L供科学的拆包机制?/div>
对于UDPQ不?x)用块的合q优化算法,q样Q实际上目前认ؓ(f)Q是׃UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区Q采用了(jin)铑ּl构来记录每一个到辄UDP包,在每个UDP包中有?jin)消息头Q消息来源地址Q端口等信息Q,q样Q对于接收端来说Q就Ҏ(gu)q行区分处理?/div>
保护消息边界和流
那么什么是保护消息边界和流?
保护消息边界Q就是指传输协议把数据当作一条独立的消息在网?nbsp;
传输,接收端只能接收独立的消息.也就是说存在保护消息边界,接收 
端一ơ只能接收发送端发出的一个数据包. 
而面向流则是指无保护消息保护边界?如果发送端q箋发送数? 
接收端有可能在一ơ接收动作中,?x)接收两个或者更多的数据?
我们举个例子来说,例如,我们q箋发送三个数据包,大小分别?k, 
4k , 8k,q三个数据包,都已l到达了(jin)接收端的|络堆栈?如果?nbsp;
用UDP协议,不管我们使用多大的接收缓冲区L收数?我们必须?nbsp;
三次接收动作,才能够把所有的数据包接收完.而用TCP协议,我们 
只要把接收的~冲区大设|在14k以上,我们p够一ơ把所有的 
数据包接收下?只需要有一ơ接收动?
q就是因为UDP协议的保护消息边界得每一个消息都是独立的.?nbsp;
传?却把数据当作一串数据流,他不认ؓ(f)数据是一个一个的消息.
所以有很多人在使用tcp协议通讯的时?q不清楚tcp是基于流?nbsp;
传输,当连l发送数据的时?他们时常?x)认识tcp?x)丢?其实不然, 
因ؓ(f)当他们用的~冲够大?他们有可能会(x)一ơ接收到两个?nbsp;
x多的数据?而很多h往往?x)忽视这一?只解析检查了(jin)W一?nbsp;
数据?而已l接收的其他数据包却被忽略了(jin).所以大家如果要作这 
cȝ|络~程的时?必须要注意这一?
l论Q?/div>
Ҏ(gu)以上所_(d)可以q样理解QTCPZ(jin)保证可靠传输Q尽量减额?/div>
开销Q每ơ发包都要验证)(j)Q因此采用了(jin)式传输Q面向流的传输,
相对于面向消息的传输Q可以减发送包的数量。从而减了(jin)额外开
销。但是,对于数据传输频繁的程序来Ԍ使用TCP可能?x)容易粘包?/div>
当然Q对接收端的E序来讲Q如果机器负荷很重,也会(x)在接收缓冲里
_包。这P需要接收端额外拆包Q增加了(jin)工作量。因此,q个?/div>
别适合的是数据要求可靠传输Q但是不需要太频繁传输的场合(
两次操作间隔100msQ具体是由TCP{待发送间隔决定的Q取决于内核
中的socket的写法)(j)
而UDPQ由于面向的是消息传输,它把所有接收到的消息都挂接到缓?/div>
区的接受队列中,因此Q它对于数据的提取分d更加方便Q但是,
它没有粘包机Ӟ因此Q当发送数据量较小的时候,׃(x)发生数据?/div>
有效载荷较小的情况,也会(x)增加多次发送的pȝ发送开销Q系l调用,
写硬件等Q和接收开销。因此,应该最好设|一个比较合适的数据?/div>
的包长,来进行UDP数据的发送。(UDP最大蝲荷ؓ(f)1472Q因此最好能
每次传输接近q个数的数据量,q特别适合于视频,音频{大块数?/div>
的发送,同时Q通过减少握手来保证流媒体的实时性)(j)


冷锋 2011-11-11 10:22 发表评论
]]>一致性hash法http://www.shnenglu.com/ifeng/archive/2011/10/18/158611.html冷锋冷锋Tue, 18 Oct 2011 05:49:00 GMThttp://www.shnenglu.com/ifeng/archive/2011/10/18/158611.htmlhttp://www.shnenglu.com/ifeng/comments/158611.htmlhttp://www.shnenglu.com/ifeng/archive/2011/10/18/158611.html#Feedback0http://www.shnenglu.com/ifeng/comments/commentRss/158611.htmlhttp://www.shnenglu.com/ifeng/services/trackbacks/158611.htmlhttp://hbluojiahui.blog.163.com/blog/static/31064767201098114026211/

冷锋 2011-10-18 13:49 发表评论
]]>
mysql字符串{义函?/title><link>http://www.shnenglu.com/ifeng/archive/2011/10/17/158523.html</link><dc:creator>冷锋</dc:creator><author>冷锋</author><pubDate>Mon, 17 Oct 2011 03:43:00 GMT</pubDate><guid>http://www.shnenglu.com/ifeng/archive/2011/10/17/158523.html</guid><wfw:comment>http://www.shnenglu.com/ifeng/comments/158523.html</wfw:comment><comments>http://www.shnenglu.com/ifeng/archive/2011/10/17/158523.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/ifeng/comments/commentRss/158523.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ifeng/services/trackbacks/158523.html</trackback:ping><description><![CDATA[<div><div>在mysql插入数据表,如果数据中带?\“?x)造成语法错误Q这个不用解释,你懂的,因此需要写个{义函敎ͼ一开始想直接用string的replaceQ但是这个方法要调用3?/div><div>攑֜服务端感觉效率太低了(jin)Q于是用C写了(jin)个,感觉q可以,旉复杂度跟需要{义字W的个数无关Q如果源串没有匹配的话不需要copy操作.<br /><span id="q6wg6oc" class="Apple-style-span" style="font-size: 13px; background-color: #eeeeee; "><span style="color: #008000; ">//</span><span style="color: #008000; ">转义函数,‘转成\'</span></span></div><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #0000FF; ">bool</span><span style="color: #000000; "> ConverToDBStr( </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; "> src,</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">dst )<br />{<br />    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> i </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">记录上次匚w的位|?/span><span style="color: #008000; "><br /></span><span style="color: #000000; ">    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> dOffset </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">目标字符串游?/span><span style="color: #008000; "><br /></span><span style="color: #000000; ">    </span><span style="color: #0000FF; ">int</span><span style="color: #000000; "> nCopy </span><span style="color: #000000; ">=</span><span style="color: #000000; "> </span><span style="color: #000000; ">0</span><span style="color: #000000; ">;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">本次需要成 copy的字节数</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">    </span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">p </span><span style="color: #000000; ">=</span><span style="color: #000000; "> src;<br />    </span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">( </span><span style="color: #000000; ">*</span><span style="color: #000000; ">p )<br />    {<br />        </span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">( </span><span style="color: #000000; ">*</span><span style="color: #000000; ">p</span><span style="color: #000000; ">==</span><span style="color: #000000; ">'</span><span style="color: #000000; ">\\</span><span style="color: #000000; ">'</span><span style="color: #000000; ">||*</span><span style="color: #000000; ">p</span><span style="color: #000000; ">==</span><span style="color: #000000; ">'</span><span style="color: #000000; ">\</span><span style="color: #000000; ">''</span><span style="color: #000000; ">||*p==</span><span style="color: #000000; ">'"</span><span style="color: #000000; ">' )</span><span style="color: #000000; "><br /></span><span style="color: #000000; ">        {<br />            nCopy </span><span style="color: #000000; ">=</span><span style="color: #000000; "> p</span><span style="color: #000000; ">-</span><span style="color: #000000; ">src</span><span style="color: #000000; ">-</span><span style="color: #000000; ">i</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />            memcpy( dst</span><span style="color: #000000; ">+</span><span style="color: #000000; ">dOffset,src</span><span style="color: #000000; ">+</span><span style="color: #000000; ">i</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,nCopy );<br />            dOffset</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">nCopy;<br />            </span><span style="color: #000000; ">*</span><span style="color: #000000; ">(dst</span><span style="color: #000000; ">+</span><span style="color: #000000; ">Offset)</span><span style="color: #000000; ">=</span><span style="color: #000000; ">'</span><span style="color: #000000; ">\\</span><span style="color: #000000; ">'</span><span style="color: #000000; ">;<br />            </span><span style="color: #000000; ">*</span><span style="color: #000000; ">(dst</span><span style="color: #000000; ">+</span><span style="color: #000000; ">dOffset</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)</span><span style="color: #000000; ">=*</span><span style="color: #000000; ">p;<br />            dOffset</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />            i </span><span style="color: #000000; ">=</span><span style="color: #000000; "> p</span><span style="color: #000000; ">-</span><span style="color: #000000; ">src;<br />        }<br />        p</span><span style="color: #000000; ">++</span><span style="color: #000000; ">;<br />    }<br />    </span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">( dOffset</span><span style="color: #000000; ">></span><span style="color: #000000; ">0</span><span style="color: #000000; "> )</span><span style="color: #008000; ">//</span><span style="color: #008000; ">有匹配到Qcopy最后的字符?/span><span style="color: #008000; "><br /></span><span style="color: #000000; ">    {<br />        memcpy( dst</span><span style="color: #000000; ">+</span><span style="color: #000000; ">dOffset,src</span><span style="color: #000000; ">+</span><span style="color: #000000; ">i</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,p</span><span style="color: #000000; ">-</span><span style="color: #000000; ">src</span><span style="color: #000000; ">-</span><span style="color: #000000; ">i );<br />        </span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">;<br />    }<br />    </span><span style="color: #0000FF; ">return</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">false</span><span style="color: #000000; ">;<br /></span></div><div><span id="weuseea" class="Apple-style-span" style="font-size: 13px; background-color: #eeeeee; ">}<br />可以看到Q这个函数稍微改动下可以实现replace</span></div></div><img src ="http://www.shnenglu.com/ifeng/aggbug/158523.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ifeng/" target="_blank">冷锋</a> 2011-10-17 11:43 <a href="http://www.shnenglu.com/ifeng/archive/2011/10/17/158523.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>nginxW记http://www.shnenglu.com/ifeng/archive/2011/09/30/157201.html冷锋冷锋Fri, 30 Sep 2011 01:45:00 GMThttp://www.shnenglu.com/ifeng/archive/2011/09/30/157201.htmlhttp://www.shnenglu.com/ifeng/comments/157201.htmlhttp://www.shnenglu.com/ifeng/archive/2011/09/30/157201.html#Feedback0http://www.shnenglu.com/ifeng/comments/commentRss/157201.htmlhttp://www.shnenglu.com/ifeng/services/trackbacks/157201.html

ngx_connection_t,抽象的连接,?/span>core模块?/span>ngx_event_process_init 函数中预先分配好?span class="Apple-style-span" style="font-family: verdana, 'courier new'; background-color: #eeeeee; ">ngx_event_process_init预分配connectsQread\write 事g的数l,

q依ơ初始化Qƈ依次初始化各q接的链表关p,也就是在data上存下一个connection的指?nbsp;
 cycle
->connections =
        ngx_alloc(
sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
    
if (cycle->connections == NULL) {
        
return NGX_ERROR;
    }
.

 c 
= cycle->connections;
.
    
do {
        i
--;

        c[i].data 
= next;
        c[i].read 
= &cycle->read_events[i];
        c[i].write 
= &cycle->write_events[i];
        c[i].fd 
= (ngx_socket_t) -1;
        next 
= &c[i];
#if (NGX_THREADS)
        c[i].
lock = 0;
#endif
    } 
while (i);
    cycle
->free_connections = next;
    cycle
->free_connection_n = cycle->connection_n;

//初始化linsten socketQƈ讄listen的处理函Cؓ(f) rev->handler = ngx_event_acceptex;
Rev->accept=1;
 
for (i = 0; i < cycle->listening.nelts; i++) {

        c 
= ngx_get_connection(ls[i].fd, cycle->log);

        
if (c == NULL) {
            
return NGX_ERROR;
        }
}Q结构体部分成员Q?/span>
struct ngx_connection_s {
    
void               *data;
    ngx_event_t        
*read;//M件处?/span>
    ngx_event_t        *write;//写事件处?/span>
    ngx_socket_t        fd;//q接对应的socket
    ngx_listening_t    *listening;/

    ngx_log_t          
*log;

    ngx_pool_t         
*pool;

         
//q_相关的读写,对应socket的send,recv
        ngx_recv_pt         recv;
    ngx_send_pt         send;

    
struct sockaddr    *sockaddr;//地址
    socklen_t           socklen;
    ngx_str_t           addr_text;
}

ngx_get_connection:?/span>freeconnect队头取出一?/span>connection,q将socketl定?/span>connection

在上层应用(比如HTTPQ,使用ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)加入M件?/span>

 

在ngx_epoll_process_events函数中,
 
if (flags & NGX_POST_EVENTS) {
                ngx_locked_post_event(wev, 
&ngx_posted_events);

            } 
else {
                wev
->handler(wev);
            }

如果带有NGX_POST_EVENTS标记Q就把事件投递到队列中不立即处理?br />在ngx_process_events_and_timers 中,?x)在每个循环调用ngx_event_process_posted(cycle, 
&ngx_posted_events);不断取出事g队列q行处理?br /> NGX_POST_EVENTS是ؓ(f)?jin)进行耗时操作前先释放q程锁,攑օ队列E后再处?用进E锁应该是避免N个进EacceptD的惊,新版linux已经不会(x)出现q个问题)?br />  if (ngx_posted_events) {
        
if (ngx_threaded) {
            ngx_wakeup_worker_thread(cycle);

        } 
else {
            ngx_event_process_posted(cycle, 
&ngx_posted_events);
        }
    }

 



冷锋 2011-09-30 09:45 发表评论
]]>EPOLL下的accept(转蝲)http://www.shnenglu.com/ifeng/archive/2011/09/29/157141.html冷锋冷锋Thu, 29 Sep 2011 09:08:00 GMThttp://www.shnenglu.com/ifeng/archive/2011/09/29/157141.htmlhttp://www.shnenglu.com/ifeng/comments/157141.htmlhttp://www.shnenglu.com/ifeng/archive/2011/09/29/157141.html#Feedback1http://www.shnenglu.com/ifeng/comments/commentRss/157141.htmlhttp://www.shnenglu.com/ifeng/services/trackbacks/157141.html阅读全文

冷锋 2011-09-29 17:08 发表评论
]]>
nginx源码单分?/title><link>http://www.shnenglu.com/ifeng/archive/2011/09/27/156948.html</link><dc:creator>冷锋</dc:creator><author>冷锋</author><pubDate>Tue, 27 Sep 2011 03:26:00 GMT</pubDate><guid>http://www.shnenglu.com/ifeng/archive/2011/09/27/156948.html</guid><wfw:comment>http://www.shnenglu.com/ifeng/comments/156948.html</wfw:comment><comments>http://www.shnenglu.com/ifeng/archive/2011/09/27/156948.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ifeng/comments/commentRss/156948.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ifeng/services/trackbacks/156948.html</trackback:ping><description><![CDATA[<p>׃工作需要,分析?jin)nginx的连接层事g处理模块Q只是初步的大体分析?br /><br />mian函数(nginx.c)里面做一些初始化的工作,最主要的部分,是调用ngx_init_cycleQngx_master_process_cycleQ主q程循环Q,<br />ngx_init_cycle主要是做一些初始化的工作,包括调用ngx_open_listening_sockets打开socket端口监听{?br />ngx_master_process_cycle函数中,先设|一下需要阻塞的信号Q然后是调用ngx_start_worker_processes函数创徏workerq程Q然后进入一个死循环。里面应该是理workerq程的,d@环里面调用了(jin)sigsuspend函数挂v{待信号Q具体怎么理q没研究?/p> <p>ngx_start_worker_processesQ调用ngx_spawn_processQ@环创建N个workerq程<br />ngx_spawn_processQ调用socketpair创徏用于父子q程通信的socket,里面q行?jin)一大堆socket参数讄Q然后调用workerq程的主循环ngx_worker_process_cycleQ?br />然后主进E设|进E表相应信息?br />ngx_worker_process_cycleQ先调用ngx_worker_process_init初始化进E,里面应该是设|成守护q程{等Q有初始化模块信息,关闭对等socket的其中一个channel,其中比较关键的是调用ngx_add_channel_event。里面调用ngx_get_connectionq回一个free的ngx_connection_t,最关键的是ngx_add_connQ其对应到epoll模块的ngx_epoll_add_connectionQ在q里是d相应的监听socketq监听队列,q设|连接ؓ(f)Ȁzȝ态,可以看到q里epoll是用的ET模式?/p> <p>接下来在ngx_worker_process_cycle中,(g)查是否配|了(jin)多线E模式,如果有,创建多U程Q我只关注多q程Q因此先无视它,关键Ҏ(gu)调用ngx_process_events_and_timers函数Q?br />ngx_process_events_and_timersQ调用ngx_process_events和ngx_event_process_postedQ?br />ngx_process_events对应是ngx_epoll_process_eventsQ这里会(x)调用epoll_waitQ就跟^常的epoll使用一栗?br />ngx_event_process_posted(cycle, &ngx_posted_accept_events);处理accept队列中所有事Ӟngx_posted_accept_events没有扑ֈ初始化的地方Q估计是~译脚本自动生成的,估计?x)对应到ngx_event_accept函数q行处理Q里面就是普通的accept操作Q返回fd,q生成一条ngx connection,然后调用ngx_add_conn加入epoll监听队列?br />xQ整个流E完成?br />虽然q有很多地方不懂Q但ȝ?jin)解了(jin)大体流E了(jin)。以上分析不保证正确Q仅供参考,仅作Z人学?fn)笔讎ͼƢ迎指正?/p><img src ="http://www.shnenglu.com/ifeng/aggbug/156948.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ifeng/" target="_blank">冷锋</a> 2011-09-27 11:26 <a href="http://www.shnenglu.com/ifeng/archive/2011/09/27/156948.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.ccbaocheng.cn" target="_blank">þˬˬAVƬ</a>| <a href="http://www.pic789.cn" target="_blank">޾Ʒҹvaþ</a>| <a href="http://www.hycv.cn" target="_blank">ŷƷƵһþþþƷ</a>| <a href="http://www.zhunsan.cn" target="_blank">޾Ʒþþþ</a>| <a href="http://www.njcwhs.cn" target="_blank">þۺ77777鶹</a>| <a href="http://www.abroadapp.cn" target="_blank">ŷƷ˾þ</a>| <a href="http://www.94555.com.cn" target="_blank">99ھƷþþþþþ</a>| <a href="http://www.dyssnv.cn" target="_blank">һaƬþëƬ</a>| <a href="http://www.jamesauto.cn" target="_blank">AAAþþþƷ</a>| <a href="http://www.more1.cn" target="_blank">þwww˳ɾƷ㽶</a>| <a href="http://www.fmd3.cn" target="_blank">ھƷŷþþƷ</a>| <a href="http://www.dgltjsh.cn" target="_blank">þɫ</a>| <a href="http://www.jn104.cn" target="_blank">ھƷþþþӰԺ޹² </a>| <a href="http://www.ubmz.cn" target="_blank">һɫۺϾþ</a>| <a href="http://www.68admin.cn" target="_blank">þרƷ </a>| <a href="http://www.zjslzy.com.cn" target="_blank">þþþAVƬ</a>| <a href="http://www.sangaotang.cn" target="_blank">ҹҹݺݾþö </a>| <a href="http://www.phpluck.cn" target="_blank">þþƷ</a>| <a href="http://www.aeuou.cn" target="_blank">re99þþƷ99</a>| <a href="http://www.uxgj.cn" target="_blank">һֻƴƬ99þ</a>| <a href="http://www.yt-tongyong.cn" target="_blank">99þþùƷţ</a>| <a href="http://www.qiaoyishiqy6.com.cn" target="_blank">99Ʒ˾þþô߽</a>| <a href="http://www.diycook.cn" target="_blank">ŷԴսþþþþ</a>| <a href="http://www.baomintv.cn" target="_blank">޾þþһ</a>| <a href="http://www.kdplastics.cn" target="_blank">999þþƷ</a>| <a href="http://www.hxsnw.com.cn" target="_blank">þseֻоƷ</a>| <a href="http://www.shensizxw.cn" target="_blank">Ʒþþþù3d</a>| <a href="http://www.hzlike.cn" target="_blank">ھƷþþþþ99</a>| <a href="http://www.viples.cn" target="_blank">þԾƷ</a>| <a href="http://www.dyph.net.cn" target="_blank">ƷŷþþӰ</a>| <a href="http://www.bb657.cn" target="_blank">ŷձþþƷ</a>| <a href="http://www.huangjiguang.cn" target="_blank">vaþþþúݺ</a>| <a href="http://www.cd-hk.cn" target="_blank">þùҹƵ</a>| <a href="http://www.818jk.cn" target="_blank">ŷ˾þþƷ</a>| <a href="http://www.chefax.cn" target="_blank">wwþþþþþþþ</a>| <a href="http://www.xmjbjd.cn" target="_blank">˾ƷǾþ</a>| <a href="http://www.37000.com.cn" target="_blank">ۺϾƷ㽶þ97</a>| <a href="http://www.qianhongg.cn" target="_blank">þþƷAV㽶</a>| <a href="http://www.sanghuan.cn" target="_blank">ƷVIDEOSSEXþ÷</a>| <a href="http://www.51uhq.cn" target="_blank">Ļþþþ</a>| <a href="http://www.uqtl.cn" target="_blank">޹˾þۺһ77</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>