共有メモリ設定パラメータのshmallとshmmax

PostgreSQLなどをはじめ、DBMSを動かすサーバでは一般的にカーネルパラメータshmmax、shmallのパラメータの変更が行われる。この設定変更に関する情報はWebの色んなサイトにあるが、一部のサイトでは誤った記載が間々あるように思う。というのも、「shmallとshmmaxの設定値を同じ値に設定するんだ」、という説明は正しくない。一部のサイトでは、shmallの値をバイト数で指定しようとしているように見受けられる。
Linuxカーネルのソース(linux-2.6.18/include/linux/shm.hの17行目〜)を読むと、こんなコメントが。shmallについては、バイト数ではなくページ数を設定する。


#define SHMMAX 0x2000000 /* max shared seg size (bytes) */
#define SHMMIN 1 /* min shared seg size (bytes) */
#define SHMMNI 4096 /* max num of segs system wide */
#ifdef __KERNEL__
#define SHMALL (SHMMAX/PAGE_SIZE*(SHMMNI/16)) /* max shm system wide (pages) */
#else
#define SHMALL (SHMMAX/getpagesize()*(SHMMNI/16))
#endif
#define SHMSEG SHMMNI /* max shared segs per process */

マニュアル(http://www.linux.or.jp/JM/html/LDP_man-pages/man2/shmget.2.html)を見ると、以下のように記載されている。やはりshmallは「バイト数ではなくページ数」を設定するもののようだ。

SHMALL システム全体の共有メモリ・ページの最大数 (Linux では、この上限値は /proc/sys/kernel/shmall 経由で参照したり、変更したりできる)。
SHMMAX 共有メモリ・セグメントのバイト単位の大きさの上限: 方針依存 (Linux では、この上限値は /proc/sys/kernel/shmmax 経由で参照したり、変更したりできる)。
SHMMIN 共有メモリ・セグメントのバイト単位の大きさの下限: 実装依存 (現在は 1 バイトだが、実質的な最小サイズは PAGE_SIZE である)。

OS導入後デフォルト設定のままとなっている手元のサーバ(kernel:2.6.18)で、kernel.shm*の値を確認した結果は以下の通り。


# sysctl -a | grep kernel.shm
kernel.shmmni = 4096
kernel.shmall = 4294967296
kernel.shmmax = 68719476736
次にこの値がカーネルソースのコメントの関係式に照らして正しいかを確認してみる。先のマニュアルの説明によれば、shmmniが4096バイトになっているということは、PAGE_SIZEが4KBであることを表すはずなので、

shmmax shmmin 68719476736(Byte) 4096(Byte)
shmall = ------------ * ---------- = -------------------- * ------------ = 4294967296
page_size 16 4096(Byte) 16
ふむ、確かにその通り。shmallを大きく取ったからといってシステムクラッシュが起こるわけではないが、是非気をつけたいポイントである。

おまけ:なお、PAGESIZEの設定値を確認する方法は「# getconf PAGESIZE」を実行すれば確認できる。そもそもPAGESIZEってどこでセットされてるんだろ?というのも少しだけ調べてみたが、搭載するCPUのアーキテクチャごとに適合したpage.hが読み込まれ、自動的にセットされているように思えた。PAGESIZEについては手動で明示的に値を変更するようなことはないんだろうなぁと想像(詳しい方、教えてください><;)