ホームページ  >  記事  >  バックエンド開発  >  Nginx のメモリ管理についての深い理解 (写真)

Nginx のメモリ管理についての深い理解 (写真)

不言
不言転載
2018-11-15 17:14:533738ブラウズ

この記事は、Nginx のメモリ管理 (写真) についての深い理解をもたらします。一定の参考価値があります。必要な友人は参照できます。お役に立てば幸いです。

1. 概要

  1. アプリケーションのメモリは、単純にヒープ メモリとスタック メモリに分けることができます。スタック メモリの場合、関数がコンパイルされると、コンパイラはスタック領域の自己管理を実現するためにスタックの現在のポインタ位置を移動するコードを挿入します。ヒープ メモリの場合、通常はプログラマが管理する必要があります。私たちが通常話しているメモリ管理は、ヒープ領域のメモリ管理のみです。

  2. メモリの使用は、メモリの適用、メモリの使用、メモリの解放の 3 つのステップに単純化できます。通常、メモリの申請やメモリの使用にはプログラマによる明示的な操作が必要ですが、メモリの解放には必ずしもプログラマによる明示的な操作が必要ではありません。現在、多くの高級言語ではガベージ コレクションのメカニズムが提供されており、メモリを解放するタイミングを選択できます。例: Go と Java はガベージ コレクションを実装していますが、リサイクル、C 言語はまだガベージ コレクションを実装していませんが、ガベージ コレクションはスマート ポインタを使用して C で実現できます。

  3. 言語レベルのメモリ管理に加えて、プログラム内で独自にメモリ管理を行う必要がある場合がありますが、一般的にメモリ管理では主に以下の問題を解決することが多いと思います。 :

  • #ユーザーがメモリを申請するとき、ユーザーのニーズを満たすメモリ ブロックを素早く見つけるにはどうすればよいでしょうか?

  • ユーザーがメモリを解放するときにメモリの断片化を回避するにはどうすればよいでしょうか?

言語レベルで実装されるメモリ管理であっても、アプリケーション自体によって実装されるメモリ管理であっても、メモリはほとんどの場合、サイズに応じていくつかのタイプに分類され、それぞれ異なる管理モードが使用されます。一般的な分類は、リンク リストを使用して、さまざまな種類のメモリを 2 の整数乗に分割することです。クエリを実行するときは、対応するサイズのリンク リストから検索します。見つからない場合は、より大きなメモリ ブロックから一部を取得することを検討できます。それを複数の小さな記憶ポイントに分割します。もちろん、特に大きなメモリの場合、言語レベルのメモリ管理はメモリ管理関連のシステム コールを直接呼び出すことができ、アプリケーション レベルのメモリ管理は言語レベルのメモリ管理を直接使用できます。

  1. nginx のメモリ管理は全体として 2 つの部分に分けることができます。

  • 最初の部分はコンベンショナル メモリです。プール、プロセスで必要なメモリ管理に使用;

  • 2 番目の部分は共有メモリの管理です。全体として、共有メモリはメモリ プールよりもはるかに複雑です。

#2. nginx メモリ プール管理

2.1 説明

  1. この部分で使用される nginx バージョンは 1.15.3です。

  2. 特定のソース コードについては、src/core/ngx_palloc.c ファイルを参照してください。

2.2 nginx の実装

2.2.1 使用プロセス

nginx メモリ プールの使用は比較的単純で、3 つのステップに分けることができます。

  • ngx_create_pool 関数を呼び出し、ngx_pool_t ポインターを取得します。

//size代表ngx_pool_t一块的大小
ngx_pool_t* ngx_create_pool(size_t size, ngx_log_t *log)
  • ngx_palloc を呼び出してメモリ使用量を適用します

//从pool中申请size大小的内存
void* ngx_palloc(ngx_pool_t *pool, size_t size)
  • メモリを解放します (解放可能)大きなブロックのメモリを使用するか、メモリ プール全体を解放します)

//释放从pool中申请的大块内存
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p)
//释放整个内存池
void ngx_destroy_pool(ngx_pool_t *pool)
2.2.2 具体的な実装

  1. 以下の図に示すように、nginx はメモリを分割します。小規模メモリと大規模メモリの 2 種類に分けられ、適用された領域が pool->max よりも大きい場合は大メモリ領域、それ以外の場合は小メモリ領域とみなされます。

  2. //创建内存池的参数size减去头部管理结构ngx_pool_t的大小
    pool->max = size - sizeof(ngx_pool_t);

Nginx のメモリ管理についての深い理解 (写真)

メモリ空間が小さい場合、nginx はまず、現在のメモリ ブロックに割り当てられる空間がユーザーのニーズを満たしているかどうかを確認します。次に、メモリのこの部分を直接返します。ユーザーのニーズを満たすことができない場合は、メモリ ブロックを再申請する必要があります。申請されたメモリ ブロックは、現在のブロック領域と同じサイズです。新しく申請されたメモリ ブロックは、以前のメモリ ブロックとリンクされています。リンク リストに関連付けられ、ユーザーが必要とするメモリ ブロックが新しいメモリ ブロックから割り当てられます。

小さいメモリは解放しません、申請後すぐに使用可能です、後で使用しなくなった場合でもメモリを解放する必要はありません。ユーザーは使用しているメモリ ブロックが大きいか小さいかわからない場合があるため、ngx_pfree 関数を呼び出して領域を解放することもできます。この関数は、大容量のリンク リストでメモリを検索し、見つかった場合にメモリを解放します。 。メモリが小さい場合、処理は行われません。

大きなメモリ ブロックの場合、nginx はそれらをリンク リストに保存し、pool->large を通じて管理します。ユーザー管理の大きなメモリの ngx_pool_large_t 構造は、このメモリ プール内の小さなメモリ ブロックから適用されるため、これらのメモリを解放できないことは注目に値します。nginx は ngx_pool_large_t 構造を直接再利用します。ユーザーが大きなメモリ空間を申請する必要がある場合、C 関数ライブラリ malloc を使用して領域を申請し、それを特定の ngx_pool_large_t 構造体にマウントします。 nginx が新しい ngx_pool_large_t 構造体を必要とする場合、最初にプール -> ラージ リンク リストの最初の 3 つの要素をチェックして、利用可能なものが存在するかどうかを確認し、利用可能な場合は直接使用され、そうでない場合は新しい ngx_pool_large_t 構造体が作成されます。

3. nginx 共有メモリ管理

3.1 説明

  1. この中で使用される nginx のバージョン部分 1.15.3

  2. この部分のソースコードの詳細については、src/core/ngx_slab.c、src/core/ngx_shmtx.c

  3. を参照してください。
  4. ##nginx 共有メモリ 内容は比較的大きいため、この記事では概要のみを説明します。

3.2 共有メモリの直接使用

3.2.1 基本

  1. nginx の対話型セッション 排他ロックは、後で複数のプロセスを同期するために使用されます。また、nginx には設定 (stat_stub) などの統計情報が必要になる場合がありますが、これらの変数を特別に管理する必要はなく、共有スペースを開いて直接使用するだけで済みます。

  2. stat_stub 設定後に必要な統計情報も共有メモリに配置されますが、ここでは nginx のミューテックス ロックのみを使用して説明します。

3.2.2 nginx ミューテックス ロックの実装

  1. nginx ミューテックス ロックには 2 つのオプションがあります。システムがアトミック操作をサポートしている場合は、アトミック操作が使用されます。 、ファイル ロックはサポートされていない場合に使用されます。このセクションのソース コードについては、ngx_event_module_init 関数を参照してください。

  2. #次の図は、相互排他ロックを実装するファイル ロックの概略図です。

Nginx のメモリ管理についての深い理解 (写真)

#次の図は、ミューテックス ロックを実装するためのアトミック操作の概略図です。

Nginx のメモリ管理についての深い理解 (写真)#問題

  1. #リロードすると、新しく起動したマスターがマスターシグナル送信後すぐに終了します。古いマスターは設定 (ngx_init_cycle 関数) をリロードし、新しいワーカー プロセスを作成します。新しいワーカー プロセスは、古いワーカー プロセスと同じロックを使用します。

  2. スムーズなアップグレード中、古いマスターは新しいマスターを作成し、新しいマスターは古いマスターのリスニング ポートを継承します (リスニング ソケットに対応する fd は環境変数を介して渡されます)。新しいプロセスは再起動されません。リスニング ポートをバインドします。新しいワーカーと古いワーカーが同時に特定のポートをリッスンしている状況が発生する場合がありますが、この場合、オペレーティング システムは 1 つのプロセスのみがイベントを処理するようにします (ただし、epoll_wait は起動されます)。

3.3 スラブを介した共有メモリの管理

nginx を使用すると、ngx_http_limit_conn_module モジュールなどの各モジュールが使用する共有スペースを開くことができます。

  1. nginx 共有メモリ管理の基本的な考え方は次のとおりです:

  2. 1. ページに従ってメモリを割り当て、各ページのサイズは同様に、ここでは page_size に設定します。

  3. 2. メモリ ブロックを 2 の整数乗に従って分割します。最小値は 8 ビット、最大値は page_size/2 です。例えば、各ページのサイズを 4Kb とすると、メモリは 8、16、32、64、128、256、512、1024、2048 の 9 種類に分割され、それぞれがスロットに対応します。スロット配列のサイズ n は 9 です。小さなメモリ ブロックを申請する場合 (メモリ サイズ size

    3. 各ページは 1 種類のメモリ ブロックにのみ分割されます。たとえば、メモリを申請する場合、既存のメモリでは要件を満たせない場合、新しいページが使用され、今後この新しいページにはこのサイズのメモリのみが割り当てられます。

    4. 二重リンクリストを介してすべてのフリーページを接続します。図のngx_slab_pool_tのfree変数はフリーページのリンクに使用されます。

    5. スロット配列を介して、メモリのすべての小さなブロックで使用されるページをリンクします。

    6. ページサイズ以上のスペースリクエストの場合は、必要なページ数を計算し、連続した空きページを見つけ、その空きページのホームページアドレスをお客様に返信し、管理を通じて特定します。各ページの構造体 ngx_slab_page_t 。

    7. すべてのページには、アイドル状態、フルではない、フルの 3 つのステータスのみがあります。フリー ページとフル ページ以外のページは、双方向のリンク リストによって統合されます。フル ページはどのページにも存在しません。スペースが解放されると、リンク リストに追加されます。

    nginx 共有メモリの基本構造図は次のとおりです。

  • 上図では、共有メモリ領域にある、右端の ngx_slab_pool_t インターフェイスから始まるメモリ セクションを除き、他のメモリは共有メモリではありません。

  • 共有メモリは最終的にページから割り当てられます。

以上がNginx のメモリ管理についての深い理解 (写真)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。