カーネル内のドライバに関連するメモリ操作の8(ページ向けメモリ割り当て)

2747 ワード

1.概要:
カーネル駆動コードに大量のメモリを使用する必要がある場合は、一般的にページ向けのメモリ管理を推奨する.ページ向けのメモリ管理には、次の利点があります.
      ,         .                    .

ページ向けのメモリ管理は、その名の通り、ページを基本単位としてメモリを操作する.kmalloc()よりもメモリの使用効率が高い.主に2つのポリシーのメモリ粒度が異なる.ページ向けメモリ管理の粒度はpageであり、kmallocの粒度はcharである.ページ向けのメモリ管理を使用するとメモリの無駄は生じないが、kmallocが割り当てるメモリは、その粒度やシステムの位置合わせの要求によりメモリの使用上の一定の無駄を招く.
 
2.カーネル内のページメモリへの割り当てに関するAPI:
    2-1:alloc_pages():
カーネル内のページメモリへの割り当てに関するAPIのコアはalloc_です.pages()は、他の関数が基本的にカプセル化されています.
関数のプロトタイプ:
static inline struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
{
	if (unlikely(order >= MAX_ORDER))
		return NULL;

	return alloc_pages_current(gfp_mask, order);
}

 
関数の機能:
          .

 
パラメータの説明:
gfp_mask:

このパラメータはkmallocの用法と同じである.GFP_をよく使うKERNELまたはGFP_ATOMIC、おそらく_GFP_DMAフラグ(ISA DMA動作で使用可能なメモリを与える)または___GFP_HIGHMEMは、ハイエンドメモリを使用する可能性がある場合に用いる.
order:

orderは、要求または解放されたページ数の2をベースとする対数(すなわちlog 2 N)である.たとえば、1ページorderが0である場合、8ページを要求すると3(2^3=8)になります.
戻り値:
                  ;    NULL.

 
2-2:共通申請ページAPI:より一般的な申請ページAPIは以下の通りである.
get_zeroed_page(unsigned int flags);

ページを割り当ててゼロにします.
__get_free_page(gfp_mask);

get_に似ていますzeroed_pageですが、このページはクリアされていません.
__get_free_pages(unsigned int flags, unsigned int order); 

メモリ領域の最初のバイトを指すポインタを割り当てて返す、メモリ領域はいくつかの(物理的に連続する)ページ長であるが、クリアされていない可能性がある.
ここで、flags、gfp_maskと上記alloc_pagesのパラメータgfp_maskの意味は同じです.ordefと上記alloc_pages()のパラメータorderの意味は同じです.
    2-3.リリースページ:
void free_page(unsigned long addr);
void free_pages(unsigned long addr, unsigned long order);

第1の関数は1ページを解放し、第2のパラメータはいくつかのページを解放し、相応のページ申請関数と組み合わせて使用する必要がある.パラメータaddrが申請ページのときのメモリヘッダアドレスである.orderと上記alloc_pages()パラメータorderと同じです.
 
3.例:以下の点在コードはLDD 3から来ている.
ページ向けメモリの割り当てに基づく:
/* Here's the allocation of a single quantum */
if (!dptr->data[s_pos])
{
        dptr->data[s_pos] =
                (void *)__get_free_pages(GFP_KERNEL, dptr->order);
        if (!dptr->data[s_pos])
                goto nomem;
        memset(dptr->data[s_pos], 0, PAGE_SIZE << dptr->order);
}


ページ・ベースのメモリの解放:
/* This code frees a whole quantum-set */
for (i = 0; i < qset; i++)
        if (dptr->data[i])
                free_pages((unsigned long)(dptr->data[i]), dptr->order);