mbind -
メモリ領域に対してメモリポリシーを設定する
#include <numaif.h>
int mbind(void *addr, unsigned long len, int mode,
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_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
モードフラグが指定されていない場合)、メモリがあるノードが
少なくとも一つ入っていなければならない。
モード
MPOL_DEFAULT
はデフォルトではないプロセスのメモリポリシーを削除し、
デフォルトの動作に戻すことを指定するものである。
mbind()
経由で、あるメモリ領域に対して
MPOL_DEFAULT
が適用された場合、プロセスのデフォルトポリシーを使用することを意味する。
プロセスのデフォルトポリシーは、
set_mempolicy(2)
で変更されているかもしれない。
プロセスのポリシーのモードも
MPOL_DEFAULT
の場合、システム全体のデフォルトポリシーが使用される。
システム全体のデフォルトポリシーでは、割り当てのきっかけとなった
CPU
のノードからページの割り当てを行う。
MPOL_DEFAULT では、引き数
nodemask と
maxnode
にノードの空集合を指定しなければならない。
MPOL_BIND
は厳しいポリシーで、メモリ割り当ては
nodemask
に指定されたノードに限定される。
他のノードへの割り当ては行われない。
nodemask に 2
個以上のノードが指定された場合、ページの割り当ては
ノード ID
が数字として最小のノードから開始され、
そのノードに空きメモリがなくなるまでそのノードから
ページ割り当てが行われる。そのノードに空きメモリがなくなったら、
次に小さなノード ID
を持つノードからページ割り当てが行われる。
これを、
nodemask
で指定された全てのノードで空きメモリがなくなるまで繰り返す。
nodemask
で指定された以外のノードからはページの割り当ては行われない。
MPOL_INTERLEAVE
は、メモリ割り当てが
nodemask
に指定されたノード間で交互に行われることを指定するものである。
このポリシーでは、複数のノードにページを広げて配置し、これらのページへの
メモリアクセスを分散することで、遅延ではなく、帯域を最適化する。
効果を得るには、メモリ領域をある程度大きくすべきであり、
メモリアクセスのパターンがかなり均一な場合でも
少なくとも 1MB
以上にすべきである。
このモードでも、一つのページへのアクセスに関しては
一つのノードのメモリ帯域が上限となることは変わりない。
MPOL_PREFERRED
は、割り当て時に優先されるノードを設定する。
カーネルはまず優先ノードにページ割り当てを行おうとし、
優先ノードに空きメモリが少ない場合に他のノードに割り当てを行う。
nodemask に複数のノード ID
が指定された場合は、
nodemask
内の最初のノードが優先ノードとして選択される。
引き数
nodemask,
maxnode
で空集合が指定された場合は、割り当てのきっかけとなった
CPU のノードに
メモリ割り当てが行われる。
mbind(2)
で、あるメモリ領域に対して「ローカルからの割り当て
(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
で指定されたメモリ領域の一部または全部が、
呼び出し元がアクセス可能なアドレス空間外を指している。
もしくは指定されたメモリ領域にマップされていない部分
(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_PREFERRED
を指定し、
nodemask
に空集合のノードを指定すればよい。
この方法は
set_mempolicy(2)
でも通用する。
2.6.16
でヒュージページ・ポリシーへの対応が追加された。
インターリーブ・ポリシーがヒュージページのマッピングで効果を持つには、
ポリシーが適用されるメモリが数十メガバイト以上である必要がある。
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
プロジェクトのリリース
3.65 の一部
である。プロジェクトの説明とバグ報告に関する情報は
http://www.kernel.org/doc/man-pages/
に書かれている。