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 引数には、追加で モードフラグ を含めることもできる。 サポートされている モードフラグ は以下の通りである。

MPOL_F_STATIC_NODES (Linux-2.6.26 以降)
    空でない nodemask は、物理ノード ID である。 Linux では、そのスレッドが異なる CPU 集合コンテキスト (cpuset context) に移動した場合でも、そのスレッドの現在の CPU 集合コンテキストで 許可されているノード集合が変化した場合でも、 nodemask をマッピングし直すことはない。

MPOL_F_RELATIVE_NODES (Linux-2.6.26 以降)
    空でない nodemask は、そのスレッドの現在の CPU 集合で許可されているノード ID 集合 における相対的なノード ID である。

nodemask は、最大で maxnode ビットから構成されるノードのビットマスクを指す。 ビットマスクの大きさは、直近の sizeof(unsigned long) の倍数に切り上げられるが、カーネルが使用するのは maxnode 個までのビットだけである。 NULL 値の nodemask もしくは値が 0 の maxnode はノードの空集合を表す。 maxnode の値が 0 の場合、 nodemask 引数は無視される。 nodemask が必須の場面では、 nodemask に、オンラインで、そのスレッドの現在の CPU 集合コンテキストで 許可されており (MPOL_F_STATIC_NODES モードフラグが指定されていない場合)、メモリーがあるノードが 少なくとも一つ入っていなければならない。

mode 引数には、以下の値のいずれかひとつを含めなければならない。

MPOL_DEFAULT
    このモードはデフォルトではないメモリーポリシーを削除し、 デフォルトの動作に戻すことを指定するものである。 mbind() 経由で、あるメモリー領域に対して MPOL_DEFAULT が適用された場合、スレッドのメモリポリシーを使用することを意味する。 スレッドのメモリポリシーは、 set_mempolicy(2) で変更されているかもしれない。 スレッドのメモリポリシーのモードも MPOL_DEFAULT の場合、システム全体のデフォルトポリシーが使用される。 システム全体のデフォルトポリシーでは、割り当てのきっかけとなった CPU のノードからページの割り当てを行う。 MPOL_DEFAULT では、引数 nodemask と maxnode にノードの空集合を指定しなければならない。

MPOL_BIND
    This mode specifies a strict policy that restricts memory allocation to the nodes specified in nodemask. If nodemask specifies more than one node, page allocations will come from the node with sufficient free memory that is closest to the node where the allocation takes place. Pages will not be allocated from any node not specified in the IR nodemask . (Before Linux 2.6.26, page allocations came from the node with the lowest numeric node ID first, until that node contained no free memory. Allocations then came from the node with the next highest node ID specified in nodemask and so forth, until none of the specified nodes contained free memory.)

MPOL_INTERLEAVE
    このモードは、メモリー割り当てが nodemask に指定されたノード間で交互に行われることを指定するものである。 このポリシーでは、複数のノードにページを広げて配置し、これらのページへの メモリーアクセスを分散することで、遅延ではなく、帯域を最適化する。 効果を得るには、メモリー領域をある程度大きくすべきであり、 メモリーアクセスのパターンがかなり均一な場合でも 少なくとも 1 MB 以上にすべきである。 このモードでも、一つのページへのアクセスに関しては 一つのノードのメモリー帯域が上限となることは変わりない。

MPOL_PREFERRED
    このモードは、割り当て時に優先されるノードを設定する。 カーネルはまず優先ノードにページ割り当てを行おうとし、 優先ノードに空きメモリーが少ない場合に他のノードに割り当てを行う。 nodemask に複数のノード ID が指定された場合は、 nodemask 内の最初のノードが優先ノードとして選択される。 引数 nodemask, maxnode で空集合が指定された場合は、割り当てのきっかけとなった CPU のノードに メモリー割り当てが行われる。

MPOL_LOCAL (Linux 3.8 以降)
    This mode specifies "local allocation"; the memory is allocated on the node of the CPU that triggered the allocation (the "local node"). The nodemask and maxnode arguments must specify the empty set. If the "local node" is low on free memory, the kernel will try to allocate memory from other nodes. The kernel will allocate memory from the "local node" whenever memory for this node is available. If the "local node" is not allowed by the thread's current cpuset context, the kernel will try to allocate memory from other nodes. The kernel will allocate memory from the "local node" whenever it becomes allowed by the thread's current cpuset context. By contrast, MPOL_DEFAULT reverts to the memory policy of the thread (which may be set via set_mempolicy(2)); that policy may be something other than "local allocation".

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 にエラーを示す値を設定する。

エラー

EFAULT
    nodemask と maxnode で指定されたメモリー領域の一部または全部が、 呼び出し元がアクセス可能なアドレス空間外を指している。 もしくは addr と len で指定されたメモリー領域にマップされていない部分 (unmapped hole) があった、

EINVAL
    flags や mode に不正な値が指定された。 addr + len が addr より小さい。 addr がシステムのページサイズの倍数になっていない。 または mode が MPOL_DEFAULT で nodemask に空でない集合が指定された。 mode が MPOL_BIND か MPOL_INTERLEAVE で nodemask が空であった。 maxnode がカーネルに適用された上限を超えている。 nodemask に、サポートされている最大ノード ID より大きいノードが指定された。 nodemask に、オンラインで、かつそのスレッドの現在の CPU 集合コンテキストで 許可されているノードが一つも含まれていないか、 メモリーを含むノードが一つも指定されていない。 mode 引数に MPOL_F_STATIC_NODES と MPOL_F_RELATIVE_NODES の両方が指定された。

EIO MPOL_MF_STRICT が指定されたが、このポリシーに従っていないノードに すでにページが存在していた。 もしくは MPOL_MF_MOVE か MPOL_MF_MOVE_ALL が指定されたが、カーネルが指定された領域内の既存の全てのページを 移動することができなかった。

ENOMEM
    利用可能なカーネルメモリーが十分でなかった。

EPERM
    flags 引数に MPOL_MF_MOVE_ALL フラグが含まれているが、呼び出し元が CAP_SYS_NICE 特権を持たない。

バージョン
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/ に書かれている。