最終更新: library_task 2010年11月03日(水) 11:05:59履歴
epoll_waitでファイルディスクリプタに新規接続が来たことがわかります。
この関数でaccept()します。
accept()とエラー処理です。
特に特筆すべきことはないですね。
ngx_cycle->connection_nは設定ファイルworker_connectionsの設定。
それを8で割って、空いているコネクションの数で引き算。
ううむ。
次の関数ではaccept()したファイルディスクリプタをngx_connection_t構造体に登録しています。
煩わしいメモリ管理はpoolを使う点は変わらないのですね。
poll領域作成、accept()によって接続先のアドレス情報が格納された情報をc->sockaddrにセットです。
AIOを使う場合はブロッキングモード、そうではない場合ノンブロッキングモード。
AIOはまだ勉強していないんだよな・・・。
手元のCentOSの場合は、ノンブロッキングモードなのでAIOは自分の課題とします。
コネクションの処理では、ngx_connection_t構造体が肝になるのでしょう。
ngx_recvやngx_sendって何だ!?と思ったらngx_event.hにありました。
Linuxの場合はngx_linux_init.cでngx_os_io_t構造体の値を定義していました。
デバック処理を経て、ls->handler(c);よりngx_http_init_connection()へ。
次はngx_http_init_connectionを見ます。
この関数でaccept()します。
17 void 18 ngx_event_accept(ngx_event_t *ev) 19 { 20 socklen_t socklen; 21 ngx_err_t err; 22 ngx_log_t *log; 23 ngx_socket_t s; 24 ngx_event_t *rev, *wev; 25 ngx_listening_t *ls; 26 ngx_connection_t *c, *lc; 27 ngx_event_conf_t *ecf; 28 u_char sa[NGX_SOCKADDRLEN]; 29 30 ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module); 31 32 if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { 33 ev->available = 1; 34 35 } else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) { 36 ev->available = ecf->multi_accept; 37 } 38 39 lc = ev->data; 40 ls = lc->listening; 41 ev->ready = 0; 42 43 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, 44 "accept on %V, ready: %d", &ls->addr_text, ev->available); 45 46 do { 47 socklen = NGX_SOCKADDRLEN; 48 49 s = accept(lc->fd, (struct sockaddr *) sa, &socklen); 50 51 if (s == -1) { 52 err = ngx_socket_errno; 53 54 if (err == NGX_EAGAIN) { 55 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err, 56 "accept() not ready"); 57 return; 58 } 59 60 ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ? 61 NGX_LOG_ERR : NGX_LOG_ALERT), 62 ev->log, err, "accept() failed"); 63 64 if (err == NGX_ECONNABORTED) { 65 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { 66 ev->available--; 67 } 68 69 if (ev->available) { 70 continue; 71 } 72 } 73 74 return; 75 }
accept()とエラー処理です。
特に特筆すべきことはないですね。
81 ngx_accept_disabled = ngx_cycle->connection_n / 8 82 - ngx_cycle->free_connection_n; 83 84 c = ngx_get_connection(s, ev->log); 85 86 if (c == NULL) { 87 if (ngx_close_socket(s) == -1) { 88 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, 89 ngx_close_socket_n " failed"); 90 } 91 92 return; 93 }このコードは・・・何でしょう。
ngx_cycle->connection_nは設定ファイルworker_connectionsの設定。
それを8で割って、空いているコネクションの数で引き算。
ううむ。
次の関数ではaccept()したファイルディスクリプタをngx_connection_t構造体に登録しています。
99 c->pool = ngx_create_pool(ls->pool_size, ev->log); 100 if (c->pool == NULL) { 101 ngx_close_accepted_connection(c); 102 return; 103 } 104 105 c->sockaddr = ngx_palloc(c->pool, socklen); 106 if (c->sockaddr == NULL) { 107 ngx_close_accepted_connection(c); 108 return; 109 } 110 111 ngx_memcpy(c->sockaddr, sa, socklen); 112 113 log = ngx_palloc(c->pool, sizeof(ngx_log_t)); 114 if (log == NULL) { 115 ngx_close_accepted_connection(c); 116 return; 117 }pool・・・名前からしてApacheと同じでしょう。
煩わしいメモリ管理はpoolを使う点は変わらないのですね。
poll領域作成、accept()によって接続先のアドレス情報が格納された情報をc->sockaddrにセットです。
119 /* set a blocking mode for aio and non-blocking mode for others */ 120 121 if (ngx_inherited_nonblocking) { 122 if (ngx_event_flags & NGX_USE_AIO_EVENT) { 123 if (ngx_blocking(s) == -1) { 124 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, 125 ngx_blocking_n " failed"); 126 ngx_close_accepted_connection(c); 127 return; 128 } 129 } 130 131 } else { 132 if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) { 133 if (ngx_nonblocking(s) == -1) { 134 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno, 135 ngx_nonblocking_n " failed"); 136 ngx_close_accepted_connection(c); 137 return; 138 } 139 } 140 }コメントの通り、らしいです。
AIOを使う場合はブロッキングモード、そうではない場合ノンブロッキングモード。
AIOはまだ勉強していないんだよな・・・。
手元のCentOSの場合は、ノンブロッキングモードなのでAIOは自分の課題とします。
142 *log = ls->log; 143 144 c->recv = ngx_recv; 145 c->send = ngx_send; 146 c->recv_chain = ngx_recv_chain; 147 c->send_chain = ngx_send_chain; 148 149 c->log = log; 150 c->pool->log = log; 151 152 c->socklen = socklen; 153 c->listening = ls; 154 c->local_sockaddr = ls->sockaddr; 155 c->local_socklen = ls->socklen; 156 157 c->unexpected_eof = 1; 158 159 rev = c->read; 160 wev = c->write; 161 162 wev->ready = 1; 163 164 if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) { 165 /* rtsig, aio, iocp */ 166 rev->ready = 1; 167 } 168 169 if (ev->deferred_accept) { 170 rev->ready = 1; 171 #if (NGX_HAVE_KQUEUE) 172 rev->available = 1; 173 #endif 174 } 175 176 rev->log = log; 177 wev->log = log;accept()したファイルディスクリプタが入ったngx_connection_t構造体にガシガシ初期値を格納。
コネクションの処理では、ngx_connection_t構造体が肝になるのでしょう。
ngx_recvやngx_sendって何だ!?と思ったらngx_event.hにありました。
extern ngx_os_io_t ngx_io; #define ngx_recv ngx_io.recv #define ngx_recv_chain ngx_io.recv_chain #define ngx_udp_recv ngx_io.udp_recv #define ngx_send ngx_io.send #define ngx_send_chain ngx_io.send_chainngx_os_io_t構造体はngx_os.hにあってこんな感じ
typedef struct { ngx_recv_pt recv; ngx_recv_chain_pt recv_chain; ngx_recv_pt udp_recv; ngx_send_pt send; ngx_send_chain_pt send_chain; ngx_uint_t flags; } ngx_os_io_t;
Linuxの場合はngx_linux_init.cでngx_os_io_t構造体の値を定義していました。
static ngx_os_io_t ngx_linux_io = { ngx_unix_recv, ngx_readv_chain, ngx_udp_unix_recv, ngx_unix_send, #if (NGX_HAVE_SENDFILE) ngx_linux_sendfile_chain, NGX_IO_SENDFILE #else ngx_writev_chain, 0 #endif };
179 /* 180 * TODO: MT: - ngx_atomic_fetch_add() 181 * or protection by critical section or light mutex 182 * 183 * TODO: MP: - allocated in a shared memory 184 * - ngx_atomic_fetch_add() 185 * or protection by critical section or light mutex 186 */ 187 188 c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); 189 190 #if (NGX_STAT_STUB) 191 (void) ngx_atomic_fetch_add(ngx_stat_handled, 1); 192 #endif 193 194 #if (NGX_THREADS) 195 rev->lock = &c->lock; 196 wev->lock = &c->lock; 197 rev->own_lock = &c->lock; 198 wev->own_lock = &c->lock; 199 #endif 200 201 if (ls->addr_ntop) { 202 c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len); 203 if (c->addr_text.data == NULL) { 204 ngx_close_accepted_connection(c); 205 return; 206 } 207 208 c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->addr_text.data, 209 ls->addr_text_max_len, 0); 210 if (c->addr_text.len == 0) { 211 ngx_close_accepted_connection(c); 212 return; 213 } 214 } 215 216 #if (NGX_DEBUG) 217 { 218 219 in_addr_t i; 220 ngx_event_debug_t *dc; 221 struct sockaddr_in *sin; 222 223 sin = (struct sockaddr_in *) sa; 224 dc = ecf->debug_connection.elts; 225 for (i = 0; i < ecf->debug_connection.nelts; i++) { 226 if ((sin->sin_addr.s_addr & dc[i].mask) == dc[i].addr) { 227 log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL; 228 break; 229 } 230 } 231 232 } 233 #endif 234 235 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, 236 "*%d accept: %V fd:%d", c->number, &c->addr_text, s); 237 238 if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) { 239 if (ngx_add_conn(c) == NGX_ERROR) { 240 ngx_close_accepted_connection(c); 241 return; 242 } 243 } 244 245 log->data = NULL; 246 log->handler = NULL; 247 248 ls->handler(c); 249 250 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { 251 ev->available--; 252 } 253 254 } while (ev->available); 255 }201行目からの処理は、たぶんIPアドレスを取得してngx_connection_t構造体にセットしていると思われます。
デバック処理を経て、ls->handler(c);よりngx_http_init_connection()へ。
次はngx_http_init_connectionを見ます。
このページへのコメント
yxX9K7 <a href="http://bygieopvkskd.com/">bygieopvkskd</a>, [url=http://nswlapglxbzw.com/]nswlapglxbzw[/url], [link=http://ribatezajhig.com/]ribatezajhig[/link], http://eleitvnvhmzx.com/