MBIND(2) | Linux Programmer's Manual | MBIND(2) |
mbind - メモリー領域に対してメモリーポリシーを設定する
#include <numaif.h>
long mbind(void *addr, unsigned long len, int mode, const unsigned long *nodemask, unsigned long maxnode, unsigned flags);
-lnuma でリンクする。
mbind() は、 addr から始まる長さ len バイトの範囲のメモリーに NUMA メモリーポリシーを設定する。 NUMA ポリシーはポリシーモードと 0 個以上のノードから構成される。 メモリーポリシーはどのノードからメモリーを割り当てるかを決定する。
addr と len で指定されたメモリー範囲に、 メモリーの「無名」領域 — MAP_ANONYMOUS 付きの mmap(2) システムコールを使って作成されたメモリー領域 — や MAP_PRIVATE 付きの mmap(2) を使ってマップされたメモリーマップファイルが含まれている場合、アプリケーションがそのページへの書き込み (データの格納) を行った時には指定されたポリシーのみに基づいてページが割り当てられる。無名領域の場合、最初の読み出しアクセスの際には カーネル内の全データが 0 である共有ページが使用される。 MAP_PRIVATE でマップされたファイルの場合、最初の読み出しアクセスがあると、 ページ割り当てが発生するきっかけとなったスレッドのメモリポリシーにしたがってページの割り当てが行われる。 ページ割り当てのきっかけとなったスレッドは、 mbind() を呼び出したスレッドと同じとは限らない。
指定されたメモリー範囲内にある MAP_SHARED のマッピングでは指定されたポリシーは無視され、 ページ割り当てが発生するきっかけとなったスレッドのメモリポリシーに したがってページの割り当てが行われることになる。 繰り返しになるが、ページ割り当てのきっかけとなったスレッドは、 mbind() を呼び出したスレッドと同じとは限らない。
指定されたメモリー範囲に、 shmget(2) システムコールを使って作成されたり、 shmat(2) システムコールを使って付加 (attach) されたりした共有メモリー領域が 含まれる場合、無名メモリー領域や共有メモリー領域に対するページ割り当ては、 共有メモリーセグメントへポリシーの設定を行ったプロセスがページ割り当て のきっかけとなったかに関わらず、指定されたポリシーにしたがって割り当て が行われる。 しかしながら、共有メモリー領域が SHM_HUGETLB フラグを指定して作成された場合には、ヒュージページ (huge page) の割り当てが 指定されたポリシーにしたがって行われるのは、その領域に対して mbind() を呼び出したプロセスがページ割り当てのきっかけとなった場合のみである。
デフォルトでは、 mbind() は新規のメモリー割り当てに対してのみ効果を持つ。 ポリシーが設定される前にすでに使用されている範囲内のページに対しては、 ポリシーは影響しない。 このデフォルトの動作は、以下で説明するフラグ MPOL_MF_MOVE や MPOL_MF_MOVE_ALL により上書きされる可能性がある。
mode 引数には、 MPOL_DEFAULT, MPOL_BIND, MPOL_INTERLEAVE, MPOL_PREFERRED, MPOL_LOCAL (詳細は下記参照) のいずれか一つを指定しなければならない。 MPOL_DEFAULT 以外のポリシーモードの場合、呼び出し元は nodemask 引数でそのポリシーモードを適用するノードを指定する必要がある。
mode 引数には、追加で モードフラグ を含めることもできる。 サポートされている モードフラグ は以下の通りである。
nodemask は、最大で maxnode ビットから構成されるノードのビットマスクを指す。 ビットマスクの大きさは、直近の sizeof(unsigned long) の倍数に切り上げられるが、カーネルが使用するのは maxnode 個までのビットだけである。 NULL 値の nodemask もしくは値が 0 の maxnode はノードの空集合を表す。 maxnode の値が 0 の場合、 nodemask 引数は無視される。 nodemask が必須の場面では、 nodemask に、オンラインで、そのスレッドの現在の CPU 集合コンテキストで 許可されており (MPOL_F_STATIC_NODES モードフラグが指定されていない場合)、メモリーがあるノードが 少なくとも一つ入っていなければならない。
mode 引数には、以下の値のいずれかひとつを含めなければならない。
flags に MPOL_MF_STRICT が 指定され、 mode が MPOL_DEFAULT でない場合、 指定されたポリシーに従っていないメモリー領域にページが存在すると、 mbind() はエラー EIO で失敗する。
flags に MPOL_MF_MOVE が指定されると、カーネルはそのメモリー領域内の既存の全てのページを移動し、 指定されたポリシーに従うようにしようとする。 他のプロセスと共有されているページは移動されない。 MPOL_MF_STRICT も指定された場合、移動できなかったページがあると、 mbind() はエラー EIO で失敗する。
flags に MPOL_MF_MOVE_ALL が指定されると、カーネルはそのメモリー領域内の既存の全てのページを、 他のプロセスがページを使用しているかどうかに関わらず移動する。 このフラグを使用するには、呼び出し元のスレッドは特権 (CAP_SYS_NICE) を持っていなければならない。 MPOL_MF_STRICT も指定された場合、移動できなかったページがあると、 mbind() はエラー EIO で失敗する。
成功すると、 mbind() は 0 を返す。エラーの場合、-1 を返し、 errno にエラーを示す値を設定する。
mbind() システムコールはバージョン 2.6.7 で Linux カーネルに追加された。
このシステムコールは Linux 固有である。
ライブラリによるサポートについては numa(7) を参照。
NUMA ポリシーは、 MAP_SHARED フラグが指定されてマップされたメモリーマップファイルの領域では サポートされていない。
MPOL_DEFAULT モードは、 mbind() と set_mempolicy(2) で異なる効果を持つことができる。 set_mempolicy(2) で MPOL_DEFAULT が指定された場合、そのスレッドのメモリポリシーはシステムの デフォルトポリシー、すなわちローカルからの割り当て、に戻る。 mbind() を使ってメモリーのある領域に MPOL_DEFAULT が指定された場合、その範囲に対してそれ以降に行われるページの割り当てでは、 set_mempolicy(2) で設定したのと同じように、そのスレッドのメモリポリシーが適用される。 これにより、特定のメモリー領域についてだけ明示的なポリシーを削除し、 デフォルトのポリシーに「戻す」ことができる。 あるメモリー領域に対して「ローカルからの割り当て」を明示的に設定するには、 mode に MPOL_LOCAL か MPOL_PREFERRED を指定し、 nodemask に空集合のノードを指定すればよい。 この方法は set_mempolicy(2) でも通用する。
2.6.16 でヒュージページポリシーへの対応が追加された。 インターリーブポリシーがヒュージページのマッピングで効果を持つには、 ポリシーが適用されるメモリーが数十メガバイト以上である必要がある。
Linux 5.7 より前では、 MPOL_MF_STRICT はヒュージページのマッピングでは無視されていた。
MPOL_MF_MOVE と MPOL_MF_MOVE_ALL は Linux 2.6.16 以降でのみ利用可能である。
get_mempolicy(2), getcpu(2), mmap(2), set_mempolicy(2), shmat(2), shmget(2), numa(3), cpuset(7), numa(7), numactl(8)
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。
2020-06-09 | Linux |