Nginx婧愮爜鍒嗘瀽-Epoll妯″潡
Linux騫沖彴涓婏紝Nginx浣跨敤epoll瀹屾垚浜嬩歡椹卞姩錛屽疄鐜伴珮騫跺彂錛涙湰鏂囧皢涓嶅epoll鏈韓榪涜浠嬬粛錛堢綉涓婁竴鍫嗕竴鍫嗙殑鏂囩珷浠嬬粛epoll鐨勫師鐞嗗強浣跨敤鏂規硶錛岀敋鑷蟲簮鐮佸垎鏋愮瓑錛夛紝浠呯湅涓涓婲ginx鏄浣曚嬌鐢╡poll鐨勩?/p>
Nginx鍦╡poll妯″潡涓畾涔変簡濂藉嚑涓嚱鏁幫紝榪欎簺鍑芥暟鍩烘湰閮芥槸浣滀負鍥炶皟娉ㄥ唽鍒頒簨浠舵娊璞″眰鐨勫搴旀帴鍙d笂錛屼粠鑰屽疄鐜頒簡浜嬩歡椹卞姩鐨勫叿浣撳寲錛屾垜浠湅濡備笅鐨勪竴孌典唬鐮侊細
ngx_event_module_t ngx_epoll_module_ctx = {
&epoll_name,
ngx_epoll_create_conf, /* create configuration */
ngx_epoll_init_conf, /* init configuration */
{
ngx_epoll_add_event, /* add an event */
ngx_epoll_del_event, /* delete an event */
ngx_epoll_add_event, /* enable an event */
ngx_epoll_del_event, /* disable an event */
ngx_epoll_add_connection, /* add an connection */
ngx_epoll_del_connection, /* delete an connection */
NULL, /* process the changes */
ngx_epoll_process_events, /* process the events */
ngx_epoll_init, /* init the events */
ngx_epoll_done, /* done the events */
}
};
榪欐浠g爜灝辨槸epoll鐨勭浉鍏沖嚱鏁版敞鍐屽埌浜嬩歡鎶借薄灞傦紝榪欓噷鎵璋撶殑浜嬩歡鎶借薄灞傚湪鍓嶉潰鐨勫崥鏂囦腑鏈夋彁榪囷紝灝辨槸Nginx涓轟簡鏂逛究鏀寔鍜屽紑鍙戝叿浣撶殑I/O妯″瀷錛屼粠鑰屽疄鐜扮殑涓灞傛娊璞°備唬鐮佸悗闈㈢殑娉ㄩ噴灝嗗姛鑳借鏄庡緱寰堣緇嗕簡錛屾湰鏂囧氨鍙噸鐐瑰叧娉╪gx_epoll_init鍜宯gx_epoll_process_events涓や釜鍑芥暟錛屽叾浠栧嚑涓嚱鏁板氨鏆備笖蹇界暐浜嗐?/p>
ngx_epoll_init涓昏鏄畬鎴恊poll鐨勭浉鍏沖垵濮嬪寲宸ヤ綔錛屼唬鐮佸垎鏋愬涓嬶細
static ngx_int_t
ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
ngx_epoll_conf_t *epcf;
/*鍙栧緱epoll妯″潡鐨勯厤緗粨鏋?/
epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
/*ep鏄痚poll妯″潡瀹氫箟鐨勪竴涓叏灞鍙橀噺錛屽垵濮嬪寲涓?1*/
if (ep == -1) {
/*鍒涗竴涓猠poll瀵硅薄錛屽閲忎負鎬昏繛鎺ユ暟鐨勪竴鍗?/
ep = epoll_create(cycle->connection_n / 2);
if (ep == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"epoll_create() failed");
return NGX_ERROR;
}
}
/*nevents涔熸槸epoll妯″潡瀹氫箟鐨勪竴涓叏灞鍙橀噺錛屽垵濮嬪寲涓?*/
if (nevents events) {
if (event_list) {
ngx_free(event_list);
}
/*event_list瀛樺偍浜х敓浜嬩歡鐨勬暟緇?/
event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
cycle->log);
if (event_list == NULL) {
return NGX_ERROR;
}
}
nevents = epcf->events;
/*鍒濆鍖栧叏灞鍙橀噺ngx_io, ngx_os_is瀹氫箟涓猴細
ngx_os_io_t ngx_os_io = {
ngx_unix_recv,
ngx_readv_chain,
ngx_udp_unix_recv,
ngx_unix_send,
ngx_writev_chain,
0
};錛堜綅浜巗rc/os/unix/ngx_posix_init.c錛?
*/
ngx_io = ngx_os_io;
/*榪欓噷灝辨槸灝唀poll鐨勫叿浣撴帴鍙e嚱鏁版敞鍐屽埌浜嬩歡鎶借薄灞傛帴鍙gx_event_actions涓娿?
鍏蜂綋鏄笂鏂囨彁鍒扮殑ngx_epoll_module_ctx涓皝瑁呯殑濡備笅鍑犱釜鍑芥暟
ngx_epoll_add_event,
ngx_epoll_del_event,
ngx_epoll_add_event,
ngx_epoll_del_event,
ngx_epoll_add_connection,
ngx_epoll_del_connection,
ngx_epoll_process_events,
ngx_epoll_init,
ngx_epoll_done,
*/
ngx_event_actions = ngx_epoll_module_ctx.actions;
#if (NGX_HAVE_CLEAR_EVENT)
/*epoll灝嗘坊鍔犺繖涓爣蹇?涓昏涓轟簡瀹炵幇杈圭紭瑙﹀彂*/
ngx_event_flags = NGX_USE_CLEAR_EVENT
#else
/*姘村鉤瑙﹀彂*/
ngx_event_flags = NGX_USE_LEVEL_EVENT
#endif
|NGX_USE_GREEDY_EVENT /*io鐨勬椂鍊欙紝鐩村埌EAGAIN涓烘*/
|NGX_USE_EPOLL_EVENT; /*epoll鏍囧織*/
return NGX_OK;
}
epoll鍒濆鍖栧伐浣滄病鏈夋兂璞′腑鐨勫鏉傦紝鍜屾垜浠鉤鏃朵嬌鐢╡poll閮戒竴鏍鳳紝涓嬮潰鐪媙gx_epoll_process_events錛岃繖涓嚱鏁頒富瑕佺敤鏉ュ畬鎴愪簨浠剁殑絳夊緟騫跺鐞嗐?/p>
static ngx_int_t
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
int events;
uint32_t revents;
ngx_int_t instance, i;
ngx_uint_t level;
ngx_err_t err;
ngx_log_t *log;
ngx_event_t *rev, *wev, **queue;
ngx_connection_t *c;
/*涓寮濮嬪氨鏄瓑寰呬簨浠訛紝鏈闀跨瓑寰呮椂闂翠負timer錛沶ginx涓轟簨浠?
涓撻棬鐢ㄧ孩榛戞爲緇存姢浜嗕竴涓鏃跺櫒銆傚悗緇榪欎釜timer鍗曠嫭鍒嗘瀽銆?
*/
events = epoll_wait(ep, event_list, (int) nevents, timer);
if (events == -1) {
err = ngx_errno;
} else {
err = 0;
}
if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
/*鎵ц涓嬈℃椂闂存洿鏂? nginx灝嗘椂闂寸紦瀛樺埌浜嗕竴緇勫叏灞鍙橀噺涓紝鏂逛究紼嬪簭楂樻晥鐨勮幏鍙栦簨浠躲?/
ngx_time_update();
}
/*澶勭悊wait閿欒*/
if (err) {
if (err == NGX_EINTR) {
if (ngx_event_timer_alarm) {
ngx_event_timer_alarm = 0;
return NGX_OK;
}
level = NGX_LOG_INFO;
} else {
level = NGX_LOG_ALERT;
}
ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
return NGX_ERROR;
}
/*wait榪斿洖浜嬩歡鏁?錛屽彲鑳芥槸timeout榪斿洖錛屼篃鍙兘鏄潪timeout榪斿洖錛涢潪timeout榪斿洖鍒欐槸error*/
if (events == 0) {
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"epoll_wait() returned no events without timeout");
return NGX_ERROR;
}
log = cycle->log;
/*for寰幆寮濮嬪鐞嗘敹鍒扮殑鎵鏈変簨浠?/
for (i = 0; i read;
銆傘傘傘傘傘傘傘傘傘傘傘傘?
/*鍙栧緱鍙戠敓涓涓簨浠?/
revents = event_list[i].events;
/*璁板綍wait鐨勯敊璇繑鍥炵姸鎬?/
if (revents & (EPOLLERR|EPOLLHUP)) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
"epoll_wait() error on fd:%d ev:%04XD",
c->fd, revents);
}
if ((revents & (EPOLLERR|EPOLLHUP))
&& (revents & (EPOLLIN|EPOLLOUT)) == 0)
{
/*
* if the error events were returned without EPOLLIN or EPOLLOUT,
* then add these flags to handle the events at least in one
* active handler
*/
revents |= EPOLLIN|EPOLLOUT;
}
/*璇ヤ簨浠舵槸涓涓浜嬩歡錛屽茍璇ヨ繛鎺ヤ笂娉ㄥ唽鐨勮浜嬩歡鏄痑ctive鐨?/
if ((revents & EPOLLIN) && rev->active) {
if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
rev->posted_ready = 1;
} else {
rev->ready = 1;
}
/*浜嬩歡鏀懼叆鐩稿簲鐨勯槦鍒椾腑錛涘叧浜庢澶勭殑鍏堝叆闃熷啀澶勭悊錛屽湪鍓嶉潰鐨勬枃绔犱腑宸茬粡浠嬬粛榪囦簡銆?/
if (flags & NGX_POST_EVENTS) {
queue = (ngx_event_t **) (rev->accept ?
&ngx_posted_accept_events : &ngx_posted_events);
ngx_locked_post_event(rev, queue); /*鍏ラ槦*/
} else {
rev->handler(rev);
}
}
wev = c->write;
/*鍙戠敓鐨勬槸涓涓啓浜嬩歡錛屽拰璇諱簨浠跺畬鍏ㄤ竴鏍風殑閫昏緫榪囩▼*/
if ((revents & EPOLLOUT) && wev->active) {
if (flags & NGX_POST_THREAD_EVENTS) {
wev->posted_ready = 1;
} else {
wev->ready = 1;
}
/*鍏堝叆闃熷啀澶勭悊*/
if (flags & NGX_POST_EVENTS) {
ngx_locked_post_event(wev, &ngx_posted_events);
} else {
wev->handler(wev);
}
}
}
return NGX_OK;
}
鏈枃灝嗗叧娉ㄧ殑涓や釜epoll鍑芥暟涔熷氨榪欎箞涓鐐逛唬鐮佷簡錛屼絾鏁翠釜epoll榪樻湁娣誨姞浜嬩歡鍜屽垹闄や簨浠剁瓑鐨勭浉鍏沖嚱鏁幫紝浠g爜閮藉緢綆鍗曪紝鏈枃灝變笉鍋氬叿浣撶殑鍒嗘瀽浜嗐?/p>




