これまでの学習ノートを読んだ後、nginx の起動プロセスをある程度理解できたと思います。このセクションからは、各モジュールを深く掘り下げて、各モジュール内の主な操作を学びたいと思います。
この記事の引用元: http://blog.csdn.net/lengzijian/article/details/7598996
今日は、前回の起動で、各モジュールを多数呼び出すことについて説明しました。
のフック関数 このメソッドは主に ngx_event_conf_t 構造体を作成し、メモリ空間を割り当てます。
2. 設定ファイルを読み取ります:
たとえば、読み取られたファイルには次の行があります:
[cpp] view
普通のコピープリント?
イベント
{
epoll を使用します
- }
- この場所でのイベントはブロック命令です。命令は括弧内で設定できます。これらの命令は src/event/ngx_event.c
-
[cpp] ビューで定義されています。
普通のコピープリント?
- static ngx_command_t ngx_event_core_commands[] = {
{ ngx_string(
"worker_connections"
) 、
-
NGX_EVENT_CONF|NGX_CONF_TAKE1、 ngx_event_connections ,
-
0,
-
0, NULL },
-
...(ここでは省略)
-
-
{ ngx_string(
「接続」- ),
-
NGX_EVENT_CONF|NGX_CONF_TAKE1、
-
ngx_event_connections、
-
0、
-
0、 NULL }、
-
-
{ngx_string(
"使用"- ) )、
-
NGX_EVENT_CONF|NGX_CONF_TAKE1、
-
ngx_event_use、
-
0、
- 0、 NULL }、
- ngx_null_command
- };
- イベントが解析されると、次の関数がコールバックされます:
-
[cpp] view
普通のコピープリント?
- src/event/ngx_event.c
- static char *
-
ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
- {
- char *rv;
- void ***ctx;
- ngx_uint_t i;
- ngx_conf_t pcf;
- ngx_event_module_t *m;
-
- /* イベントモジュールの数を数え、インデックスを設定します */
- //计算event模块数,并そして记录
- ngx_event_max_module = 0;
- for (i = 0; ngx_modules[i]; i++) {
- if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
- 続けます;
- }
-
- ngx_modules[i]->ctx_index = ngx_event_max_module++;
- }
-
- ctx = ngx_pcalloc(cf->pool, sizeof(void *));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
- //のために每一イベント模块割り当て空間、保存用响应配置结构的地址
- //共割了ngx_event_max_module个空间
- *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
- if (*ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *(void **) conf = ctx;
-
- for (i = 0; ngx_modules[i]; i++) {
- if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
- 続きます;
- }
-
- m = ngx_modules[i]->ctx;
-
if -
(m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
-
((*ctx)[ngx_modules[i]->ctx_index] == NULL) { -
- pcf = *cf->ctx = ctx; cf->module_type = NGX_EVENT_MODULE
- cf-> ;cmd_type = NGX_EVENT_CONF;
- //イベントはブロック命令であるため、他の多くの命令をイベント ドメインで構成できます。 、ここでイベント ブロック内の命令の解析を開始し、初期化作業を完了します。
- rv = ngx_conf_parse(cf, NULL);
- *cf = pcf; if
(rv != NGX_CONF_OK) -
-
if
- (ngx_modules [i] - > type!= ngx_event_module){
- 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]);
- }
- }
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]ビュー
普通のコピープリント?
- src/event/ngx_event.c
- static ngx_int_t
-
ngx_event_module_init(ngx_cycle_t *cycle)
- {
- void ***cf;
- u_char *共有;
- size_t サイズ、cl;
- ngx_shm_t shm;
- ngx_time_t *tp;
- ngx_core_conf_t *ccf;
- ngx_event_conf_t *ecf;
-
- // 判断ngx_events_module かどうか调用过初期化conf操作
- cf = ngx_get_conf(cycle-> conf_ctx、ngx_events_module);
-
- if (cf == NULL) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, 0、
- 「設定に「イベント」セクションがありません」 );
- return NGX_ERROR;
- }
-
-
//获取ngx_event_core_module模块の構成结构
- ecf = (*cf)[ngx_event_core_module.ctx_index];
-
- //イベント内のモジュールであるかどうかを確認します。たとえば、使用します。。。。
- if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
- ngx_log_error(NGX _LOG_NOTICE, サイクル->ログ, 0 ,
- 「イベントメソッド」 , ecf->name);
- }
- //ngx_core_module モジュールの構成構造を取得します
ccf = (ngx_core_conf_t *) ngx_ get_conf(cycle- >conf_ctx, ngx_core_module); // ngx_core_module モジュールの構成構造体から timer_resolution パラメータを取得します ngx_timer_resolution = ccf->timer_resolution; -
- #if !(NGX_WIN32)
-
{
-
ngx_int_t 制限
- rlimit rlmt; //現在のプロセスの能力を取得します 開いているファイルの最大数 man getrlimit
- (getrlimit(rlimit_nofile、&rlmt)== -1){
- ngx_log_error(ngx_log_alert、cycle-&gt; log、ngx_errno、else{
- _モジュールへの最大接続数は無制限です
- / / または ngx_event_core_module 接続が ngx_core_module の最大接続数より大きいです
- (ECF-& GT; 接続 & GT; (ngx_uint_t) rlmt.rlim_cur
- (ccf-& gt; _NOFILE == ngx_conf_unset)
limit = (ccf ->rlimit_nofile == NGX_CONF_UNSET) ? (ngx_int_t) rlmt.rlim_cur: ccf- & gt; -
- " オープンファイルのリソース制限: %i" ); (NGX_WIN32) */
-
- //マスタープロセスが閉じている場合は、 return
- //マスタープロセスを閉じることは単一プロセスの作業メソッドを意味するため、
- //後続の操作では、ロックやその他の作業を実装するための共有メモリが作成されますが、これは単一プロセスには必要ありません。
- if (ccf->master == 0) {
-
NGX_OK }
-
-
// 受け入れミューテックスの場合すでに存在するため、再度作成する必要はありません。 - } /* cl はキャッシュ以上である必要がありますline size */
-
- cl = 128; // ここでサイズを作成します。この共有メモリは 3 つの等しいセグメントに分割されます
-
- サイズ= cl + cl ,
-
- shm.size = サイズ shm.name.len = sizeof
( - 「nginx_shared_zone」
); shm.name.data = (u_char *) - "nginx_share d_zone";
- shm.log = サイクル->log
- (ngx_shm_alloc(&s)うーん) = NGX_OK ) {
- NGX_ERROR;
-
- ; .addr;
-
//ミューテックスの取得を受け入れる共有メモリの最初の cl サイズメモリ
-
ngx_accept_mutex_ptr = (ngx_atomic_t *) 共有メモリ
- ngx_accept_mutex.spin = (ngx_uint_t) -1; /* 受け入れミューテックスを作成します
- 受け入れミューテックスの実装は、アトミック操作をサポートするかどうか、および対応するアトミック操作があるかどうかによって異なります。 ; それ以外の場合は、受け入れミューテックスを実装するためにファイル ロックが使用されます。
-
-
accept mutex の機能は、パニック グループを回避し、ワーカー プロセスの負荷分散を実現することです。
- */ngx_accept_mutex、共有、cycle-&gt; lock_file.data)
- != ngx_ok) //メモリの 2 番目のセグメントの cl サイズのアドレスを取得します
- ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl)
- (void
); ngx_atomic_cmp_set (ngx_connection_counter, 0, 1); - ngx_log_debug2(NGX_LOG_DEBUG_EVENT, サイクル - >log, 0,
- x_connection_counter);
- //メモリ cl アドレスの 3 番目のセグメントのサイズを取得します。
- ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl)
- tp = ngx_timeofday() ;
-
ngx_random_number = (tp-> ; msec << 16) + ngx_pid
- returnNGX_OK; 前述したように分析では、ワーカー プロセスが作成されると、ワーカー プロセスは最初にプロセスを初期化し、この時点で ngx_event_process_init 関数が呼び出されます。
- [cpp]ビュー
普通のコピープリント?
- src/event/ngx_event.c
- staticngx_int_t
- ngx_event_process_init(ngx_cycle_t *cycle)
- {
- ngx_uint_t m、私; ngx_event_t *rev、*wev;
- ngx_listening_t *ls;
- ngx_connection_t *c、*next、*old
- ; ngx_event_conf_t *ecf;
- ngx_event_module_t *module;
-
- //前と同様に、応答モジュールの構成構造を取得します
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx _コア_モジュール); - ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
-
//マスタープロセスがオープン、ワーカープロセスが1より大きい、accept_mutexが作成されました -
-
//cai accept mutex を開きます -
if-
(ccf->master &&ccf->worker_processes > 1 &&ecf->accept_mutex) { ngx_use_accept_mutex = 1; / /ミューテックスを使用する
- ngx_accept_mutex_held = 0; //受け入れミューテックスを取得するかどうか
- ngx_accept_mutex_lay = ecf->accept_mutex_lay; //ミューテックスの競合に失敗した後、待機中次のスクランブル時間間隔用
-
- } else {
- ngx_use_accept_mutex = 0 ;
} -
- #if (NGX_THREADS )
- //スレッドはさておき
-
#endif
-
// カウンターを初期化する、ここに赤が作成されます Black Tree、タイマー、後で詳しく説明します
-
if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
- return NGX_ERROR;
- }
- for (m = 0; ngx_modules[m]; m++) {
- //前にここで述べたように、非 NGX_EVENT_MODULE モジュールをスキップします
-
- }
-
// 使用しない構成命令で指定されたモジュールはスキップされます。Linux のデフォルトの epoll です。 ->use) { module = ngx_modules[m]->ctx;
/*init を呼び出します特定の時間モジュールの関数 - (これらのモジュールは src/event/modules ディレクトリにあります)。したがって、nginx の時間モジュールに抽象化のレイヤーが作成されており、これにより、さまざまなシステムがさまざまなイベント モデルを使用しやすくなり、新しい時間モデルを拡張します。私たちは epoll に重点を置く必要があります。
-
-
- は、実際には ngx_epoll_init 関数を呼び出しています。 module->actions 構造は、epoll のすべてのインターフェイス関数をカプセル化します。 nginx は、アクション構造を通じて epoll をイベント抽象化レイヤーに登録します。
-
アクションのタイプは、src/event/ngx_event.h にある ngx_event_action_t です
-
これらの具体的な内容については、次のセクションで説明します。
- module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
- *faタル */
exit(2) -
Break;
- }
- //内容の一部
-
//すべての接続を保存するグローバル ngx_connection_t 配列を作成します -
- //この処理は各ワーカープロセスで実行されるため、各ワーカーは独自の接続配列を持ちます
-
cycle->connections =
- ngx_alloc(sizeof(ngx_connection_t) *cycle->connection_n 、サイクル>ログ);
- if (サイクル>接続 == NULL) {
- c = サイクル>接続; 创/ // 読み取り値のグループを作成します。
-
if
- (cycle->read_events == NULL) { }
- rev =cycle->read_events;
- for (i = 0; i connection_n; i++) {
- rev[i].closed = 1 ;
- [i].instance = 1;
- #if (NGX_THREADS)
-
rev[i].lock = &c[i].lock
- rev[ i].own_lock = &c[i].lock
#endif-
}
- //创建一写イベント数组
- cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle-& gt;connection_n、
- cycle->ログ);
- if (cycle->write_events == NULL) {
- return NGX_ERROR;
- }
-
- wev = cycle->write_events;
- for (i = 0; i < cycle->connection_n; i++) {
- wev[i].closed = 1;
- #if (NGX_THREADS)
- wev[i].lock = &c[i].lock;
- wev[i].own_lock = &c[i].lock;
- #endif
- }
-
- i = cycle->connection_n;
- 次 = NULL;
- //初化整个接続数组
- do {
- i--;
-
- c[i].data = 次;
- 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
- } (i);
- サイクル->free_connection_n = サイクル->
- /* 各リスニング ソケット用 */
- //各リスニング ソケットの接続配列から接続、つまりスロット
ls =cycle->listening を割り当てます。 els; solt- に接続します c = ngx_get_connection(ls[i].fd,cycle->log)
- (c == NULL) {
-
NGX_エラー }
-
- c->log = &ls[i].log;
-
- c->listening = &ls[i];
- ls[i].connection = c;
-
- rev = c->read;
-
- rev->log = c->log;
- rev->accept = 1; //读時間间発行,调用accept
-
- #if (NGX_HAVE_DEFERRED_ACCEPT)
- //省略
- #endif
-
- if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
- if (ls[i].previous) {
-
- /*
- * バインドされていた古い accept イベントを削除します
- * 古い サイクル 読み取り イベント 配列
- */
-
- old = ls[i].previous->connection;
-
- if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)
- == NGX_ERROR)
- {
- return NGX _エラー;
- }
-
- old->fd = (ngx_socket_t) -1;
- }
- }
-
- //コールバック関数を登録します ngx_event_accept
- rev->handler = ngx_even t_accept;
- 当面はリスニングソケットを epoll に置かないでください。しかし、
-
{{
-
}}}
eLSe- {
- //使用した後、このリスニングソケットを epoll に置きます。 ️ #endif
-
-
- }
- return
NGX_OK - }
-
ここまでで、イベント駆動型の初期化が完了しました。
以上、nginx ソースコード学習メモ (20) - イベント モジュール 1 - 初期化 (IOC とカウンターの内容を含む) を紹介しました。PHP チュートリアルに興味のある友人に役立つことを願っています。
-