Linuxメモリ管理メカニズム-カーネルスペース

4876 ワード

Linuxメモリにおける線形アドレスは4 G,0~3 Gはユーザ空間,3~4 Gはカーネル空間である
一、カーネル空間
カーネル空間は3~4 Gのメモリアドレスであり,主に高優先度のコードを格納するために用いられる.
X 86構造のカーネルアドレスには、次の3種類の領域があります.
         ZONE_DMAメモリ開始の16 m
         ZONE_NORMAL       16m~896m
         ZONE_HIGHMEM    896M~
 
ZONE_DMAはDMAが使用するページ(DMAはダイレクトパスアクセス、cpuキャッシュを介さずメモリにダイレクトアクセス)ZONE_NORMALは通常のアドレス可能なページです.ZONE_HIGHMEMはダイナミックマッピングのページです.Linuxはシステムのページを異なる領域に分割し,異なるメモリプールを形成し,用途に応じて割り当てることができる.中にはZONEもありますDMA 32は、32ビットのデバイスにしかアクセスできません.
ローエンドメモリは、物理メモリの1対1の線形マッピング(1 Gのみ)を実現し、ハイエンドメモリは、残りの物理メモリ空間を指すアドレスを一時的に格納します.
Linuxカーネルは、ハイエンドメモリをvmalloc_の3つの部分に分割します.start~vmalloc_end、kmap_base~fixaddr_startとfixaddr_start~4 G、alloc_を通過できますpage()は、ハイエンドメモリに対応するページを取得します.この関数は線形アドレスのみを取得します.ハイエンドメモリマッピングは、非線形メモリアドレスを一時的に格納します.
物理ページのLinuxでの表示
Linuxはstruct page構造によって物理ページを表し、システムメモリの最小単位である.
struct page {
        unsigned long flags; //flag            ,       (      32 , page-flags.h     )
         atomic_t  _count; //_count          ,  -1            ,    page_count()        (  0    ,         )
         void    *virtual;//                 ,            }

ハイエンドメモリのダイナミックマッピング
0~896 Mのメモリアドレスはローエンドメモリと呼ばれ、物理メモリとは一対一のマッピング関係にある.896 M~1 Gのメモリアドレスをハイエンドメモリと呼び、カーネル内の1対1マッピング以外の物理メモリへのアクセスを目的とした動的マッピングを実現している.プロセスAは4 Gからのメモリ容量を申請したが、メモリは0~896 Mの1対1マッピングしか実現できないため、このアドレスを一時的にハイエンドメモリに格納し、プロセスAが使用済みになってから解放する必要がある.これにより、すべての物理メモリアドレスにアクセスできます.
 
メモリ申請
カーネルでメモリを申請する方法は、kmalloc()、kzalloc()、vmalloc()、alloc_です.page()
1、Kmallocは物理メモリを申請するために使用され、アドレスに連続する必要がないため、性能が速い.対応するメモリ解放関数はkfree()です.
2、Kzallocはkmallocに対して一つ増えた_GFP_ZEROフラグ、このフラグビットは申請したメモリ内容をクリアします.対応するメモリ解放関数もkfree()です.get_zeroed_page()も同様の効果です.
3、Vmallocは仮想メモリを申請するために使用され、仮想メモリは一定の連続性を保証する必要があるため、性能が遅い(比較的大きなTLBジッタをもたらす可能性がある).オブジェクトは仮想メモリであるため、申請のメモリサイズに制限はなく、通常は大きなメモリ領域を申請するために使用されます.対応するメモリ解放関数はvfree()です.
4、alloc_Page()は連続した物理ページを申請するために使用され、page_address()は、指定したページを論理アドレスに変換します.
Kmalloc()と_get_free_pages()は、この2つの関数が物理アドレス上の論理アドレスを返すため、ハイエンドメモリを割り当てることができません.page構造ではなく、仮想アドレスにマッピングされていない可能性があります.allocだけPage()はハイエンドメモリを割り当てることができます
下位ページの割当てフラグビット
Linuxメモリ管理インタフェースは、unsigned long get_のようなフラグビットに関連します.zeroed_page(unsigned int gfp_mask). gfp_maskはいくつかのフラグの集合であり、これらのフラグは2つの種類に分けることができる:動作修飾子と領域修飾子.動作修飾子は、カーネルが必要なメモリをどのように割り当てるかを示します.エクステント修飾子は、メモリがどこから割り当てられるかを示します.
一般的な動作修飾子
                    
__GFP_WAIT                   
__GFP_IO                 I/O    
__GFP_FS                   I/O    
__GFP_HIGH                    

一般的なエクステント修飾子
                      
__GFP_DMA           ZONE_DMA      
__GFP_HIGHMEM      ZONE_HIGHMEM ZONE_NORMAL  ,          

Slab層
slabディスペンサは、小さなメモリを割り当てるために使用されます.このうちslabディスペンサはSLABを専用SLABと通常SLABの2種類に分類する.専用SLABは、特定の場合(例えば、TCPに独自のSLABがあり、TCPモジュールが小さなメモリを必要とする場合、独自のSLABから割り当てられる)に用いられ、通常のSLABは通常の割り当てに用いられる場合である./proc/slabinfoを見るとslabの状態がわかります
kmalloc-8のような一般的なSLABには、ZONE-DMA領域を特化したメモリを使用し、DMAモード申請メモリに便利なdma-kmalloc-8というタイプの一般的なSLABがあります.
slabでは、割り当て可能なメモリブロックをオブジェクトと呼びます.不通のslabに含まれるオブジェクトのサイズも異なります.kmalloc-8という一般的なSLABのように、中のすべてのオブジェクトは8 Bサイズで、同じように、kmalloc-16のオブジェクトは16 Bサイズです.メモリを申請すると、これらのオブジェクトに基づいて分割され、メモリの断片化を減らすことができます.そのうち申請の対象は釈放された後も彼のslabに戻る.
オブジェクトの所有者が1つのオブジェクトを解放すると、SLABの処理は、オブジェクトが空きとマークされるだけで、あまり処理されず、申請者が対応するサイズのオブジェクトを申請すると、SLABは最近解放されたオブジェクトを優先的に割り当て、ハードウェアキャッシュに存在する可能性さえある.管理領域のページボックスディスペンサのCPUごとにキャッシュするのと少し似ています.
         kmem_Cache(slabキャッシュ)はslabディスペンサの最上位層である.kmem_Cache構造は、SLAB(例えば、kmalloc−8、kmalloc−16など)を記述し、このSLAB内のすべてのオブジェクトを管理するために使用される.すべてのkmem_Cache構造はslab_で保存されますcachesはヘッドのチェーンテーブルとして使用されます.カーネルモジュールではkmem_cache_createは自分でkmemを作成します.Cacheは、自分のモジュールに属するSLABを管理するために使用される.Kmalloc()はslabに基づいて申請された.
Slabには3つの状態がある:満、部分満、空.メモリが割り当てられると、部分的に満たされたslabから優先的に分割されます.それぞれ3つのチェーンテーブルで表します.
        struct list_head slabs_full;
        struct list_head slabs_partial;
        struct list_head slabs_free;
 
二、ユーザー空間
(詳細は『linuxメモリ管理メカニズム——ユーザースペース』を参照)
ユーザ空間は0~3 Gのメモリアドレスであり、主に低優先度のコードを格納するために用いられ、構成は以下の通りである.