ホームページ  >  記事  >  バックエンド開発  >  nginxソースコード学習メモ(20) - イベントモジュール1 - 初期化

nginxソースコード学習メモ(20) - イベントモジュール1 - 初期化

WBOY
WBOYオリジナル
2016-07-29 09:11:01853ブラウズ

これまでの学習ノートを読んだ後、nginx の起動プロセスをある程度理解できたと思います。このセクションからは、各モジュールを深く掘り下げて、各モジュール内の主な操作を学びたいと思います。

この記事の引用元: http://blog.csdn.net/lengzijian/article/details/7598996

今日は、前回の起動で、各モジュールを多数呼び出すことについて説明しました。

のフック関数 このメソッドは主に ngx_event_conf_t 構造体を作成し、メモリ空間を割り当てます。 nginx 源码学习笔记(二十)—— event 模块一 ——初始化

2. 設定ファイルを読み取ります:

たとえば、読み取られたファイルには次の行があります:

[cpp] view 普通のコピープリント?

イベント

{

epoll を使用します

  1. }
  2. この場所でのイベントはブロック命令です。命令は括弧内で設定できます。これらの命令は src/event/ngx_event.c
  3. [cpp] ビューで定義されています。 普通のコピープリント?
  4. static ngx_command_t ngx_event_core_commands[] = {

{ ngx_string(

"worker_connections"

) 、
  1. NGX_EVENT_CONF|NGX_CONF_TAKE1、 ngx_event_connections ,
  2. 0,
  3. 0, NULL },
  4. ...(ここでは省略)
  5. { ngx_string(
  6. 「接続」
  7. ),
  8. NGX_EVENT_CONF|NGX_CONF_TAKE1、
  9. ngx_event_connections、
  10. 0、
  11. 0、 NULL }、
  12. {ngx_string(
  13. "使用"
  14. ) )、
  15. NGX_EVENT_CONF|NGX_CONF_TAKE1、
  16. ngx_event_use、
  17. 0、
  18. 0、 NULL }、
  19. ngx_null_command
  20. };
  21. イベントが解析されると、次の関数がコールバックされます:
  22. [cpp] view 普通のコピープリント?
    1. src/event/ngx_event.c
    2. static char *
    3. ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    4. {
    5. char *rv;  
    6. void ***ctx;  
    7. ngx_uint_t i;  
    8. ngx_conf_t pcf;  
    9. ngx_event_module_t *m;  
    10. /* イベントモジュールの数を数え、インデックスを設定します */
    11. //计算event模块数,并そして记录
    12. ngx_event_max_module = 0;  
    13. for (i = 0; ngx_modules[i]; i++) {
    14. if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
    15. 続けます;  
    16. }
    17. ngx_modules[i]->ctx_index = ngx_event_max_module++;  
    18. }
    19. ctx = ngx_pcalloc(cf->pool, sizeof(void *));  
    20. if (ctx == NULL) {
    21. return NGX_CONF_ERROR;  
    22. }
    23. //のために每一イベント模块割り当て空間、保存用响应配置结构的地址
    24. //共割了ngx_event_max_module个空间
    25. *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));  
    26. if (*ctx == NULL) {
    27. return NGX_CONF_ERROR;  
    28. }
    29. *(void **) conf = ctx;  
    30. for (i = 0; ngx_modules[i]; i++) {
    31. if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
    32. 続きます;  
    33. }
    34. m = ngx_modules[i]->ctx;
    35. if
    36. (m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
    37. ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
    38. pcf = *cf->ctx = ctx; cf->module_type = NGX_EVENT_MODULE
    39. cf-> ;cmd_type = NGX_EVENT_CONF;
    40. //イベントはブロック命令であるため、他の多くの命令をイベント ドメインで構成できます。 、ここでイベント ブロック内の命令の解析を開始し、初期化作業を完了します。
    41. rv = ngx_conf_parse(cf, NULL);
    42. *cf = pcf; if
    43. (rv != NGX_CONF_OK)
    44. if
    45. (ngx_modules [i] - > type!= ngx_event_module){
    46. m= ngx_modules [ i] - > ctx;//各イベントを実行するModuleのinit_conf関数は、「 ' to ' to use ' to ' to ' t d to d. t;init_conf(cf->cycle, (*ctx) [ngx_modules[i]->ctx_index]);
    47. }
    48. }

    49. ngx_events_block() 関数の最も重要なプロセスは、ngx_conf_parse(cf, NULL) を呼び出すことです。ここで ngx_conf_parse() を呼び出す関数は、設定ファイル内の events ブロックの解析を完了し、それによってすべてのイベントを呼び出します。命令のコールバック関数により、構成ファイルの解析の初期化が完了します。しかし、ここで個人的な質問がありますので、先輩方に質問した後、質問と回答を明記します******。

      2. confの初期化(init_conf)

      ngx_event_init_conf()

      このメソッドは主にngx_event_conf_t構造体を初期化します。

      3.ngx_event_module_init

      名前からするとモジュールの初期化操作ですが、各モジュールのソースコードを見るとinitコールバック関数を持たないモジュールが多いことが分かります。私も、すべてのコードを学習した後に答えを見つけたいと思っているので、なぜここにあるのか悩んでいます。

      [cpp]ビュー 普通のコピープリント?

      1. src/event/ngx_event.c
      2. static ngx_int_t
      3. ngx_event_module_init(ngx_cycle_t *cycle)
      4. {
      5. void ***cf;  
      6. u_char *共有;  
      7. size_t サイズ、cl;  
      8. ngx_shm_t shm;  
      9. ngx_time_t *tp;  
      10. ngx_core_conf_t *ccf;  
      11. ngx_event_conf_t *ecf;  
      12. // 判断ngx_events_module かどうか调用过初期化conf操作
      13. cf = ngx_get_conf(cycle-> conf_ctx、ngx_events_module);  
      14. if (cf == NULL) {
      15. ngx_log_error(NGX_LOG_EMERG, cycle->log, 0、
      16. 「設定に「イベント」セクションがありません」 );  
      17. return NGX_ERROR;  
      18. }
      19. //获取ngx_event_core_module模块の構成结构
      20. ecf = (*cf)[ngx_event_core_module.ctx_index];  
      21. //イベント内のモジュールであるかどうかを確認します。たとえば、使用します。。。。
      22. if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
      23. ngx_log_error(NGX _LOG_NOTICE, サイクル->ログ, 0 ,
      24. 「イベントメソッド」 , ecf->name);
      25. }
      26. //ngx_core_module モジュールの構成構造を取得します
      27. ccf = (ngx_core_conf_t *) ngx_ get_conf(cycle- >conf_ctx, ngx_core_module);
      28. // ngx_core_module モジュールの構成構造体から timer_resolution パラメータを取得します ngx_timer_resolution = ccf->timer_resolution;
      29. #if !(NGX_WIN32)
      30. {
      31. ngx_int_t 制限
      32. rlimit rlmt; //現在のプロセスの能力を取得します 開いているファイルの最大数 man getrlimit
      33. (getrlimit(rlimit_nofile、&rlmt)== -1){
      34. ngx_log_error(ngx_log_alert、cycle-&gt; log、ngx_errno、else{
      35. _モジュールへの最大接続数は無制限です
      36. / / または ngx_event_core_module 接続が ngx_core_module の最大接続数より大きいです
      37. (ECF-& GT; 接続 & GT; (ngx_uint_t) rlmt.rlim_cur
      38. (ccf-& gt; _NOFILE == ngx_conf_unset)
      39. limit = (ccf ->rlimit_nofile == NGX_CONF_UNSET) ?
      40. (ngx_int_t) rlmt.rlim_cur: ccf- & gt;
      41. " オープンファイルのリソース制限: %i" ); (NGX_WIN32) */
      42. //マスタープロセスが閉じている場合は、 return
      43. //マスタープロセスを閉じることは単一プロセスの作業メソッドを意味するため、
      44. //後続の操作では、ロックやその他の作業を実装するための共有メモリが作成されますが、これは単一プロセスには必要ありません。
      45. if (ccf->master == 0) {
      46. NGX_OK }
      47. // 受け入れミューテックスの場合すでに存在するため、再度作成する必要はありません。
      48. } /* cl はキャッシュ以上である必要がありますline size */
      49. cl = 128; // ここでサイズを作成します。この共有メモリは 3 つの等しいセグメントに分割されます
      50. サイズ= cl + cl ,
      51. shm.size = サイズ shm.name.len = sizeof
      52. (
      53. 「nginx_shared_zone」
      54. ); shm.name.data = (u_char *)
      55. "nginx_share d_zone";
      56. shm.log = サイクル->log
      57. (ngx_shm_alloc(&s)うーん) = NGX_OK ) {
      58. NGX_ERROR;
      59. ; .addr;
      60. //ミューテックスの取得を受け入れる共有メモリの最初の cl サイズメモリ
      61. ngx_accept_mutex_ptr = (ngx_atomic_t *) 共有メモリ
      62. ngx_accept_mutex.spin = (ngx_uint_t) -1; /* 受け入れミューテックスを作成します
      63. 受け入れミューテックスの実装は、アトミック操作をサポートするかどうか、および対応するアトミック操作があるかどうかによって異なります。 ; それ以外の場合は、受け入れミューテックスを実装するためにファイル ロックが使用されます。
      64. accept mutex の機能は、パニック グループを回避し、ワーカー プロセスの負荷分散を実現することです。
    50. */ngx_accept_mutex、共有、cycle-&gt; lock_file.data)
    51. != ngx_ok) //メモリの 2 番目のセグメントの cl サイズのアドレスを取得します
    52. ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl)
    53. (void
    54. ); ngx_atomic_cmp_set (ngx_connection_counter, 0, 1);
    55. ngx_log_debug2(NGX_LOG_DEBUG_EVENT, サイクル - >log, 0,
    56. x_connection_counter);
    57. //メモリ cl アドレスの 3 番目のセグメントのサイズを取得します。
    58. ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl)
    59. tp = ngx_timeofday() ;
    60. ngx_random_number = (tp-> ; msec << 16) + ngx_pid
    61. returnNGX_OK; 前述したように分析では、ワーカー プロセスが作成されると、ワーカー プロセスは最初にプロセスを初期化し、この時点で ngx_event_process_init 関数が呼び出されます。
    62. [cpp]ビュー 普通のコピープリント?
      1. src/event/ngx_event.c
      2. staticngx_int_t
      3. ngx_event_process_init(ngx_cycle_t *cycle)
      4. {
      5. ngx_uint_t m、私; ngx_event_t *rev、*wev;
      6. ngx_listening_t *ls;
      7. ngx_connection_t *c、*next、*old
      8. ; ngx_event_conf_t *ecf;
      9. ngx_event_module_t *module;
      10. //前と同様に、応答モジュールの構成構造を取得します
      11. ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx _コア_モジュール);
      12. ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
      13. //マスタープロセスがオープン、ワーカープロセスが1より大きい、accept_mutexが作成されました
      14. //cai accept mutex を開きます
      15. if
      16. (ccf->master &&ccf->worker_processes > 1 &&ecf->accept_mutex) { ngx_use_accept_mutex = 1; / /ミューテックスを使用する
      17. ngx_accept_mutex_held = 0; //受け入れミューテックスを取得するかどうか
      18. ngx_accept_mutex_lay = ecf->accept_mutex_lay; //ミューテックスの競合に失敗した後、待機中次のスクランブル時間間隔用
      19. } else {
      20. ngx_use_accept_mutex = 0 ;
      21. }
      22. #if (NGX_THREADS )
      23. //スレッドはさておき
      24. #endif
      25. // カウンターを初期化する、ここに赤が作成されます Black Tree、タイマー、後で詳しく説明します
      26. if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
      27. return NGX_ERROR;
      28. }
      29. for (m = 0; ngx_modules[m]; m++) {
      30. //前にここで述べたように、非 NGX_EVENT_MODULE モジュールをスキップします
      31. }
      32. // 使用しない構成命令で指定されたモジュールはスキップされます。Linux のデフォルトの epoll です。 ->use) { module = ngx_modules[m]->ctx;
      33. /*init を呼び出します特定の時間モジュールの関数
      34. (これらのモジュールは src/event/modules ディレクトリにあります)。したがって、nginx の時間モジュールに抽象化のレイヤーが作成されており、これにより、さまざまなシステムがさまざまなイベント モデルを使用しやすくなり、新しい時間モデルを拡張します。私たちは epoll に重点を置く必要があります。
      35. は、実際には ngx_epoll_init 関数を呼び出しています。 module->actions 構造は、epoll のすべてのインターフェイス関数をカプセル化します。 nginx は、アクション構造を通じて epoll をイベント抽象化レイヤーに登録します。
      36. アクションのタイプは、src/event/ngx_event.h にある ngx_event_action_t です
      37. これらの具体的な内容については、次のセクションで説明します。
      38. module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
      39. *faタル */
      40. exit(2)
      41. Break;
      42. }
      43. //内容の一部
      44. //すべての接続を保存するグローバル ngx_connection_t 配列を作成します
      45. //この処理は各ワーカープロセスで実行されるため、各ワーカーは独自の接続配列を持ちます
      46. cycle->connections =
      47. ngx_alloc(sizeof(ngx_connection_t) *cycle->connection_n 、サイクル>ログ);
      48. if (サイクル>接続 == NULL) {
      49. c = サイクル>接続; 创/ // 読み取り値のグループを作成します。
      50. if
      51. (cycle->read_events == NULL) { }
      52. rev =cycle->read_events;
      53. for (i = 0; i connection_n; i++) {
      54. rev[i].closed = 1 ;
      55. [i].instance = 1;
      56. #if (NGX_THREADS)
      57. rev[i].lock = &c[i].lock
      58. rev[ i].own_lock = &c[i].lock
      59. #endif
      60. }  
      61. //创建一写イベント数组
      62. cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle-& gt;connection_n、
      63. cycle->ログ);  
      64. if (cycle->write_events == NULL) {
      65. return NGX_ERROR;  
      66. }
      67. wev = cycle->write_events;  
      68. for (i = 0; i < cycle->connection_n; i++) {
      69. wev[i].closed = 1;  
      70. #if (NGX_THREADS)
      71. wev[i].lock = &c[i].lock;  
      72. wev[i].own_lock = &c[i].lock;  
      73. #endif
      74. }
      75. i = cycle->connection_n;  
      76. 次 = NULL;  
      77. //初化整个接続数组
      78. do {
      79. i--;  
      80. c[i].data = 次;  
      81. c[i].read = &cycle->read_events[i];  
      82. c[i].write = &cycle->write_events[i];  
      83. c[i].fd = (ngx_socket_t) -1;  
      84. next = &c[i];  
      85. #if (NGX_THREADS)
      86. c[i].lock = 0;  
      87. #endif
      88. } (i);
      89. サイクル->free_connection_n = サイクル->
      90. /* 各リスニング ソケット用 */
      91. //各リスニング ソケットの接続配列から接続、つまりスロット
      92. ls =cycle->listening を割り当てます。 els; solt
      93. に接続します c = ngx_get_connection(ls[i].fd,cycle->log)
      94. (c == NULL) {
      95. NGX_エラー }  
      96. c->log = &ls[i].log;  
      97. c->listening = &ls[i];  
      98. ls[i].connection = c;  
      99. rev = c->read;  
      100. rev->log = c->log;  
      101. rev->accept = 1; //读時間间発行,调用accept
      102. #if (NGX_HAVE_DEFERRED_ACCEPT)
      103. //省略
      104. #endif
      105. if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
      106. if (ls[i].previous) {
      107. /*
      108. * バインドされていた古い accept イベントを削除します
      109. * 古い サイクル 読み取り イベント 配列
      110. */
      111. old = ls[i].previous->connection;  
      112. if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)
      113. == NGX_ERROR)
      114. {
      115. return NGX _エラー;  
      116. }
      117. old->fd = (ngx_socket_t) -1;  
      118. }
      119. }
      120. //コールバック関数を登録します ngx_event_accept
      121. rev->handler = ngx_even t_accept;
      122. 当面はリスニングソケットを epoll に置かないでください。しかし、
      123. {{
      124. }}}
      125. eLSe
      126. {
      127. //使用した後、このリスニングソケットを epoll に置きます。 ️ #endif
      128. }
      129. return
      130. NGX_OK
      131. }
      132. ここまでで、イベント駆動型の初期化が完了しました。 以上、nginx ソースコード学習メモ (20) - イベント モジュール 1 - 初期化 (IOC とカウンターの内容を含む) を紹介しました。PHP チュートリアルに興味のある友人に役立つことを願っています。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。