Linuxカーネルからのユーザースペースメモリへのアクセス


カーネルAPI
次に,ユーザがユーザメモリを操作するカーネルAPIについて検討する.これはカーネルとユーザ空間インタフェースに関し、次のセクションでは他のメモリAPIについて検討することに注意してください.ユーザ空間メモリアクセス関数を表1に示す.
表1.ユーザ空間メモリアクセスAPI
関数#カンスウ#
説明
access_ok
ユーザースペースメモリポインタの有効性を確認
get_user
ユーザースペースから単純な変数を取得
put_user
ユーザースペースへの単純な変数の入力
clear_user
ユーザースペースのブロックを消去するか、ゼロにします.
copy_to_user
カーネルからユーザースペースへのデータ・ブロックのコピー
copy_from_user
ユーザースペースからカーネルへのデータ・ブロックのコピー
strnlen_user
メモリ領域の文字列バッファのサイズを取得
strncpy_from_user
ユーザースペースからカーネルに文字列をコピー
期待通り、これらの関数の実装アーキテクチャは独立しています.たとえば、x 86アーキテクチャでは./linux/arch/x86/lib/usercopy_32.cとusercopy_64.cのソースコードは、これらの関数と./linux/arch/x86/include/asm/uaccess.hで定義された文字列.
図4に示すように、データ移動関数のルールがコピー呼び出しのタイプに関連する場合(単純VS.集約)、これらの関数の役割を示す.
図4.User Space Memory Access APIによるデータ移動
  access_OK関数
アクセスを使用できますOK関数は、アクセスしたいユーザースペースでポインタの有効性をチェックします.呼び出し関数は、データ・ブロックの開始を指すポインタ、ブロック・サイズ、およびアクセス・タイプ(この領域が読み取りまたは書き込みに使用されるかどうかにかかわらず)を提供します.関数プロトタイプは次のように定義されます.
access_ok( type, addr, size ); 

typeパラメータはVERIFY_として指定できますREADまたはVERIFY_WRITE.VERIFY_WRITEはまた、メモリ領域が読み取り可能であるか、書き込み可能であるかを識別することもできる(アクセスは依然としてEFAULTを生成するが).この関数は、カーネルではなくユーザ空間でアドレスを簡単にチェックします.
  get_user関数
ユーザースペースから単純な変数を読み込むにはget_を使用します.user関数.charやintなどの単純なデータ型に適していますが、構造体のような大きなデータ型ではcopy_を使用する必要があります.from_user関数.このプロトタイプは、Read操作のために変数(データの格納)とユーザ空間アドレスを受け取る.
get_user( x, ptr ); 

  get_user関数は、2つの内部関数のうちの1つにマッピングされます.システム内部では、この関数は、与えられた変数に基づいて結果を格納するアクセス変数のサイズを決定し、_get_user_xは内部呼び出しを形成する.成功した場合、この関数は0を返します.一般的にget_userとput_user関数は、それらのブロックコピーよりも速く、小さなタイプが移動されている場合は、それらを使用する必要があります.
  put_user関数
put_を使用できますuser関数は、カーネルからユーザ空間に単純な変数を書き込むために使用されます.とget_userは、書き込み対象の値を含む変数と、書き込み対象としてユーザー空間アドレスを受け入れます.
put_user( x, ptr ); 

とget_user同様put_user関数はput_に内部マッピングされるuser_x関数、成功時、0を返し、エラー時、EFAULTを返します.
  clear_user関数
  clear_user関数は、ユーザ空間のメモリブロックをゼロにするために使用される.この関数は、1つのポインタ(ユーザースペース)と1つのモデルを使用してゼロにします.これはバイトで定義されています.
clear_user( ptr, n ); 

内部、clear_user関数は、まず、ユーザ空間ポインタが書き込み可能かどうかを確認し(access_okを介して)、内部関数を呼び出し(インライン組立方式で符号化)、Clear操作を実行する.repeat接頭辞付き文字列命令を使用して、この関数を非常に緊密なループに最適化します.クリアできないバイト数が返され、操作が成功した場合は0が返されます.
  copy_to_user関数
  copy_to_user関数は、カーネルからユーザ空間にデータブロックをコピーします.この関数は、ユーザ空間バッファへのポインタ、メモリバッファへのポインタ、バイトで定義された長さを受け入れます.この関数は、成功した場合に0を返します.そうしないと、送信できないバイト数を示すゼロ以外の数を返します.
copy_to_user( to, from, n ); 

ユーザバッファへの書き込み機能を確認した後(access_ok経由)、内部関数_copy_to_userが呼び出され、逆に__が呼び出されます.copy_from_user_inatomic(./linux/arch/x 86/include/asm/uaccess_XX.h).ここで、XXは32または64であり、アーキテクチャに依存します.この関数は、1、2、または4バイトのコピーを実行するかどうかを決定した後に、__を呼び出す.copy_to_user_ll、これが実際の仕事が行われている場所です.破損したハードウェア(i 486以前、WPビットは管理モードで使用できなかった)では、ページテーブルをいつでも置き換えることができ、処理時に交換されないように、所望のページをメモリに固定する必要があります.i 486以降、このプロセスは最適化されたコピーにすぎない.
  copy_from_user関数
  copy_from_user関数は、データブロックをユーザ空間からカーネルバッファにコピーします.カーネル空間では、目的のバッファ(カーネル空間)、ソースバッファ(ユーザ空間から)、バイトで定義された長さを受け入れます.とcopy_to_userと同様に、この関数は成功した場合、0を返します.そうしないと、コピーできないバイト数を示すゼロ以外の数を返します.
copy_from_user( to, from, n ); 

この関数は、まずユーザ空間ソースバッファから読み出される能力(access_okを介して)をチェックし、次に__を呼び出す.copy_from_user,最終呼び出し_copy_from_user_ll.これからは、フレームワークに基づいて、ユーザバッファからカーネルバッファへのゼロコピー(バイト不可)を実行するために呼び出されます.最適化組立関数には、管理機能が含まれます.
  strnlen_user関数
  strnlen_user関数はstrnlenのようにも使用できますが、バッファがユーザ空間で利用できることを前提としています.strnlen_user関数には、ユーザー空間バッファアドレスとチェックする最大長の2つのパラメータがあります.
strnlen_user( src, n ); 

  strnlen_user関数はまずaccess_を呼び出すOKユーザーバッファが読み取り可能かどうかを確認します.strlen関数が呼び出されるとmax lengthパラメータは無視されます.
  strncpy_from_user関数
  strncpy_from_user関数は、ユーザー空間からカーネルバッファに文字列をコピーし、ユーザー空間のソースアドレスと最大長を指定します.
strncpy_from_user( dest, src, n ); 

この関数は、ユーザ空間からコピーされるため、まずaccess_を使用する.OKバッファが読めるかどうかを確認します.とcopy_from_userと同様に、この関数は最適化組立関数(./linux/arch/x 86/lib/usercopy_XX.c)として実現される.
メモリマッピングの他のモード
上記のセクションでは,カーネルとユーザ空間の間でデータを移動する方法(カーネル初期化操作を用いる)について検討した.Linuxはまた、カーネルとユーザ空間でデータを移動するための他の方法を提供します.これらの方法は、必ずしもユーザ空間メモリアクセス関数と同じ機能を提供できるとは限らないが、アドレス空間間でメモリをマッピングする機能は似ている.
ユーザ空間では、ユーザプロセスが個別のアドレス空間に現れるため、それらの間でデータを移動するには、あるプロセス間通信メカニズムを経なければならないことに注意されたい.Linuxは様々なモード(例えば、メッセージキュー)を提供するが、最も有名なのはPOSIX共有メモリ(shmem)である.このメカニズムでは、プロセスがメモリ領域を作成し、同じプロセスまたは複数のプロセスで領域を共有できます.各プロセスは、共有メモリ領域をそれぞれのアドレス空間に異なるアドレスにマッピングすることができることに注意してください.したがって、相対的なアドレスオフセット(offset addressing)が必要である.
mmap関数を使用すると、仮想アドレス空間にマッピングを作成するユーザー空間アプリケーションが使用できます.この機能は、あるデバイスドライバクラスで一般的であり、物理デバイスメモリをプロセスの仮想アドレス空間にマッピングできます.1つのドライバでは、mmap関数はremap_を通過します.pfn_rangeカーネル関数は、デバイスメモリからユーザアドレス空間への線形マッピングを提供する.
終わりの言葉
Linuxでのメモリ管理のトピックについて議論し,これらの概念を用いたユーザ空間メモリアクセス関数について議論した.ユーザースペースとカーネルスペースの間でデータを移動するのは表面的には簡単ではありませんが、Linuxにはプラットフォームをまたいで複雑なタスクを管理する簡単なAPIセットが含まれています.