最終更新:
library_task 2010年11月03日(水) 10:17:25履歴
Nginxの動きを把握するため、ソースを読み進めたTipsとして解析内容を残していく。
主にどうやってアクセスを処理しているかに注目するため
main()からではなく、ブラウザからアクセスを受け付けるところからのソースを追う。
主にどうやってアクセスを処理しているかに注目するため
main()からではなく、ブラウザからアクセスを受け付けるところからのソースを追う。
ワーカプロセスは、「ngx_epoll_module.c」のngx_epoll_process_events()関数にて
システムコールepoll_waitで待ち状態となっている。
ここでセットしているepoll_waitのタイマー値は、ngx_process_events_and_timers()関数にて定義されている。
ややこしいけど、confファイルのtimer_resolution定義をしているか、accept()を使うかで変わってくるみたい。
epoll_wait()の戻り値チェックとタイムアウト時の動作が下記です。
とすると、以降がエラーが発生していないときに動作するコード
長い引用ですが、for文でeventsの数だけ繰り返し==有効なファイルディスクリプタの数だけ繰り返しです。
epoll_waitシステムコールを知っていないとわけわからんので、知らない人はepoll,epoll_waitあたりを把握しましょう。
正常処理を追うと、eventsが502行目からの処理がデータ受信準備完了。
先のコードを読まないと断定はできないですが、変数名称からしておそらくリクエストデータ受信待ちかPOSTデータ受信待ちかで
処理が分岐しています。
新規のリクエストの場合、accept()するためにrev->handler(rev);でngx_event_accept()関数になります。
すでに接続済みでリクエストデータ受信の場合はrev->handler(rev);でngx_http_init_request関数・・・HTTP処理のコードとなっていきます。
epoll_waitで監視していたファイルディスクリプタがwriteできるようになった場合が
524以降のコードでしょう。
最初は新規接続が来たことを想定して、ngx_event_accept()を見てみます。
システムコールepoll_waitで待ち状態となっている。
386 ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) 387 { 388 int events; 389 uint32_t revents; 390 ngx_int_t instance, i; 391 ngx_uint_t level; 392 ngx_err_t err; 393 ngx_log_t *log; 394 ngx_event_t *rev, *wev, **queue; 395 ngx_connection_t *c; 396 397 /* NGX_TIMER_INFINITE == INFTIM */ 398 399 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, 400 "epoll timer: %M", timer); 401 402 events = epoll_wait(ep, event_list, (int) nevents, timer); 403
ここでセットしているepoll_waitのタイマー値は、ngx_process_events_and_timers()関数にて定義されている。
ややこしいけど、confファイルのtimer_resolution定義をしているか、accept()を使うかで変わってくるみたい。
epoll_wait()の戻り値チェックとタイムアウト時の動作が下記です。
404 if (events == -1) { 405 err = ngx_errno; 406 } else { 407 err = 0; 408 } 409 410 if (flags & NGX_UPDATE_TIME) { 411 ngx_time_update(0, 0); 412 } 413 414 if (err) { 415 if (err == NGX_EINTR) { 416 417 if (ngx_event_timer_alarm) { 418 ngx_event_timer_alarm = 0; 419 return NGX_OK; 420 } 421 422 level = NGX_LOG_INFO; 423 424 } else { 425 level = NGX_LOG_ALERT; 426 } 427 428 ngx_log_error(level, cycle->log, err, "epoll_wait() failed"); 429 return NGX_ERROR; 430 } 431 432 if (events == 0) { 433 if (timer != NGX_TIMER_INFINITE) { 434 return NGX_OK; 435 } 436 437 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, 438 "epoll_wait() returned no events without timeout"); 439 return NGX_ERROR; 440 }events=-1がエラー処理、events == 0がタイムアウトの処理ですね。
とすると、以降がエラーが発生していないときに動作するコード
441 442 ngx_mutex_lock(ngx_posted_events_mutex); 443 444 log = cycle->log; 445 446 for (i = 0; i < events; i++) { 447 c = event_list[i].data.ptr; 448 449 instance = (uintptr_t) c & 1; 450 c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); 451 452 rev = c->read; 453 454 if (c->fd == -1 || rev->instance != instance) { 455 456 /* 457 * the stale event from a file descriptor 458 * that was just closed in this iteration 459 */ 460 461 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, 462 "epoll: stale event %p", c); 463 continue; 464 } 465 466 #if (NGX_DEBUG0) 467 log = c->log ? c->log : cycle->log; 468 #endif 469 470 revents = event_list[i].events; 471 472 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, 473 "epoll: fd:%d ev:%04XD d:%p", 474 c->fd, revents, event_list[i].data.ptr); 475 476 if (revents & (EPOLLERR|EPOLLHUP)) { 477 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, 478 "epoll_wait() error on fd:%d ev:%04XD", 479 c->fd, revents); 480 } 481 482 #if 0 483 if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) { 484 ngx_log_error(NGX_LOG_ALERT, log, 0, 485 "strange epoll_wait() events fd:%d ev:%04XD", 486 c->fd, revents); 487 } 488 #endif 489 490 if ((revents & (EPOLLERR|EPOLLHUP)) 491 && (revents & (EPOLLIN|EPOLLOUT)) == 0) 492 { 493 /* 494 * if the error events were returned without EPOLLIN or EPOLLOUT, 495 * then add these flags to handle the events at least in one 496 * active handler 497 */ 498 499 revents |= EPOLLIN|EPOLLOUT; 500 } 501 502 if ((revents & EPOLLIN) && rev->active) { 503 504 if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { 505 rev->posted_ready = 1; 506 507 } else { 508 rev->ready = 1; 509 } 510 511 if (flags & NGX_POST_EVENTS) { 512 queue = (ngx_event_t **) (rev->accept ? 513 &ngx_posted_accept_events : &ngx_posted_events); 514 515 ngx_locked_post_event(rev, queue); 516 517 } else { 518 rev->handler(rev); 519 } 520 } 521 522 wev = c->write; 523 524 if ((revents & EPOLLOUT) && wev->active) { 525 526 if (flags & NGX_POST_THREAD_EVENTS) { 527 wev->posted_ready = 1; 528 529 } else { 530 wev->ready = 1; 531 } 532 533 if (flags & NGX_POST_EVENTS) { 534 ngx_locked_post_event(wev, &ngx_posted_events); 535 536 } else { 537 wev->handler(wev); 538 } 539 } 540 } 541 542 ngx_mutex_unlock(ngx_posted_events_mutex); 543 544 return NGX_OK; 545 }
長い引用ですが、for文でeventsの数だけ繰り返し==有効なファイルディスクリプタの数だけ繰り返しです。
epoll_waitシステムコールを知っていないとわけわからんので、知らない人はepoll,epoll_waitあたりを把握しましょう。
正常処理を追うと、eventsが502行目からの処理がデータ受信準備完了。
先のコードを読まないと断定はできないですが、変数名称からしておそらくリクエストデータ受信待ちかPOSTデータ受信待ちかで
処理が分岐しています。
502 if ((revents & EPOLLIN) && rev->active) { 503 504 if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { 505 rev->posted_ready = 1; 506 507 } else { 508 rev->ready = 1; 509 } 510 511 if (flags & NGX_POST_EVENTS) { 512 queue = (ngx_event_t **) (rev->accept ? 513 &ngx_posted_accept_events : &ngx_posted_events); 514 515 ngx_locked_post_event(rev, queue); 516 517 } else { 518 rev->handler(rev); 519 } 520 }
新規のリクエストの場合、accept()するためにrev->handler(rev);でngx_event_accept()関数になります。
すでに接続済みでリクエストデータ受信の場合はrev->handler(rev);でngx_http_init_request関数・・・HTTP処理のコードとなっていきます。
epoll_waitで監視していたファイルディスクリプタがwriteできるようになった場合が
524以降のコードでしょう。
最初は新規接続が来たことを想定して、ngx_event_accept()を見てみます。
このページへのコメント
IBkDCs <a href="http://cjxifohwuwvz.com/">cjxifohwuwvz</a>, [url=http://wdsiibgrpruu.com/]wdsiibgrpruu[/url], [link=http://ffeiigumizll.com/]ffeiigumizll[/link], http://gydjxpibigia.com/