shmget - System V
共有メモリーセグメントを割り当てる
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int
shmflg );
shmget() returns the identifier of the System V shared memory
segment associated with the value of the argument
key. It may be used
either to obtain the identifier of a previously created shared memory segment
(when
shmflg is zero and
key does not have the value
IPC_PRIVATE), or to create a new set.
key の値が
IPC_PRIVATE
の場合、もしくは
key
に対応する共有メモリーセグメントが存在せず、
shmflg に
IPC_CREAT
が指定されていた場合、
新しい共有メモリーセグメントを作成する。
作成される共有メモリーセグメントは、
size 引数の値を
PAGE_SIZE
の倍数へと切り上げた
(round up) 大きさとなる。
shmflg に
IPC_CREAT と
IPC_EXCL
の両方が指定された場合、
key
に対応する共有メモリーセグメントが既に存在すると、
shmget() は失敗し、
errno に
EEXIST が設定される
(これは
open(2) に
O_CREAT | O_EXCL
を指定した場合の動作と同じである)。
shmflg
は以下の内容から構成される:
- IPC_CREAT
- 新しいセグメントを作成する。このフラグが指定されなかった場合、
shmget() は key
に対応するセグメントを探し、
ユーザーがそのセグメントにアクセスする許可があるかどうかをチェックする。
- IPC_EXCL
- このフラグは
IPC_CREAT
とともに使用し、
この呼び出しで確実にセグメントが作成されるようにする。
セグメントが既に存在した場合には、
呼び出しは失敗する。
-
SHM_HUGETLB (Linux 2.6 以降)
- "ヒュージページ
(huge page)"
を使うセグメントを割り当てる。詳細な情報は、Linux
カーネルソースのファイル
Documentation/admin-guide/vm/hugetlbpage.rst
を参照。
-
SHM_HUGE_2MB, SHM_HUGE_1GB (Linux 3.8
以降)
- Used in conjunction with SHM_HUGETLB to select
alternative hugetlb page sizes (respectively, 2 MB and 1 GB)
on systems that support multiple hugetlb page sizes.
- More generally, the desired huge page size can be
configured by encoding the base-2 logarithm of the desired page size in
the six bits at the offset SHM_HUGE_SHIFT. Thus, the above two
constants are defined as:
-
#define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT)
#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
- For some additional details, see the discussion of the
similarly named constants in mmap(2).
-
SHM_NORESERVE (Linux 2.6.15 以降)
- このフラグは、
mmap(2) の MAP_NORESERVE
フラグと同じ役割を果たす。
このセグメントに対するスワップ空間の予約を行わない。
スワップ空間を予約した場合は、そのセグメントの変更が必ず成功することが
保証される。スワップ空間の予約を行わなかった場合は、物理メモリーに空きが
ないと書き込み時に
SIGSEGV
を受け取る可能性がある。
proc(5) にある
/proc/sys/vm/overcommit_memory
ファイルに関する議論も参照のこと。
上記のフラグに加えて、
shmflg の下位 9
ビットは、所有者、グループ、その他への許可を指定する。
これらのビットは
open(2) の
mode
引数と同じ形式で同じ意味を持つ。
今のところ、システムは実行
(execute)
許可を参照しない。
共有メモリーセグメントが新たに作成される際、
共有メモリーセグメントの内容は
0 で初期化され、
関連情報を保持するデータ構造体
shmid_ds
は以下のように初期化される。
- •
-
shm_perm.cuid と shm_perm.uid
に呼び出し元プロセスの実効
(effective) ユーザーID
を設定する。
- •
-
shm_perm.cgid と shm_perm.gid
に呼び出し元プロセスの実効グループID
を設定する。
- •
-
shm_perm.mode の下位 9
ビットに shmflg の下位 9
ビットを設定する。
- •
-
shm_segsz に size
の値を設定する。
- •
-
shm_lpid, shm_nattch, shm_atime,
shm_dtime に 0
を設定する。
- •
-
shm_ctime
に現在の時刻を設定する。
共有メモリーセグメントが既に存在する場合、アクセス許可の検査と、
破壊 (destruction)
マークがつけられていないかのチェックが行われる。
成功の場合、有効な共有メモリーセグメントの識別子が返される。
エラーの場合、 -1
が返り、
errno
にエラーを示す値が設定される。
失敗した場合は
errno
が以下のどれかに設定される:
- EACCES
- The user does not have permission to access the shared
memory segment, and does not have the CAP_IPC_OWNER capability in
the user namespace that governs its IPC namespace.
- EEXIST
-
IPC_CREAT と IPC_EXCL が
shmflg
に指定されたが、
key
に対応する共有メモリーセグメントはすでに存在する。
- EINVAL
- 新しいセグメントを作成しようとしたが、
size が SHMMIN
より小さいか SHMMAX
よりも大きかった。
- EINVAL
- 指定された key
に対応するセグメントが既に存在するが、
size
がそのセグメントのサイズよりも大きかった。
- ENFILE
- システム全体でオープンされているファイルの総数が上限に達した。
- ENOENT
- 指定された key
に対応するセグメントが存在せず、
IPC_CREAT
も指定されていなかった。
- ENOMEM
- セグメントの管理情報
(overhead)
に割り当てるメモリーがなかった。
- ENOSPC
- システム全体の共有メモリーセグメント数の制限
( SHMMNI)
に達した、または要求された
size
のセグメントの割り当てが
システム全体の共有メモリーサイズの制限
( SHMALL) を超過した。
- EPERM
-
SHM_HUGETLB
フラグが指定されたが、呼び出し元には権限がなかった
( CAP_IPC_LOCK
ケーパビリティを持っていなかった)。
POSIX.1-2001, POSIX.1-2008, SVr4.
SHM_HUGETLB と
SHM_NORESERVE は Linux
での拡張である。
Linux や POSIX
の全てのバージョンでは、
<sys/types.h> と
<sys/ipc.h>
のインクルードは必要ない。しかしながら、いくつかの古い実装ではこれらのヘッダーファイルのインクルードが必要であり、
SVID
でもこれらのインクルードをするように記載されている。このような古いシステムへの移植性を意図したアプリケーションではこれらのファイルをインクルードする必要があるかもしれない。
IPC_PRIVATE
はフラグではなく
key_t
型である。
この特別な値が
key
に使用された場合は、
shmget() は
shmflg の下位 9
ビットを除いた全てを無視し、
新しい共有メモリーセグメントを作成する。
shmget()
コールに影響する共有メモリーセグメント資源の制限は以下の通りである:
- SHMALL
- 共有メモリーの全使用量のシステム全体での上限値。
システムページサイズが単位である。
- Linux
では、この上限値は
/proc/sys/kernel/shmall
経由で参照したり、変更したりできる。
Linux 3.16 以降では、
この上限値のデフォルト値は以下のとおりである。
-
ULONG_MAX - 2^24
- この値は割り当てに関する上限としては適用されない
(なお、この値は 32
ビットシステムにも
64
ビットシステムにも適したものになっている)。
ULONG_MAX
ではなく、この値が選ばれたのは、
古いアプリケーションが最初に現在の値を確認せずに既存の上限をそのまま増やしてしまっても問題が起こらないようなデフォルト値を選んだからである。
このようなアプリケーションでは、
上限を ULONG_MAX
に設定すると値がオーバーフローしてしまうことになる。
- Linux 2.4 から Linux 3.15
では、この上限のデフォルト値は以下であった。
-
SHMMAX / PAGE_SIZE * (SHMMNI / 16)
-
SHMMAX と SHMMNI
が変更されないとすると、
この式の結果に
(バイト単位の値を得るために)
ページサイズを掛け算すると、
全ての共有メモリーセグメントで使用される全メモリーの上限として、
8 GB
という値が得られる。
- SHMMAX
- 1
つの共有メモリーセグメントの最大サイズ
(バイト数)。
- Linux
では、この上限値は
/proc/sys/kernel/shmmax
経由で参照したり、変更したりできる。
Linux 3.16 以降では、
この上限値のデフォルト値は以下のとおりである。
-
ULONG_MAX - 2^24
- この値は割り当てに関する上限としては適用されない
(なお、この値は 32
ビットシステムにも
64
ビットシステムにも適したものになっている)。
( ULONG_MAX ではなく)
このデフォルト値が使われている理由については
SHMALL
の説明を参照。
- Linux 2.2 から Linux 3.15
までは、この上限値のデフォルト値は
0x2000000 (32 MB) であった。
- 共有メモリーセグメントの一部分だけをマッピングすることはできないので、
使用可能なセグメントの最大サイズには仮想メモリーの総量という別の上限が適用される。
例えば、i386
ではマッピング可能な最大セグメントの大きさはおおよそ
2.8 GB で、 x86-64
では上限はおおよそ
127TB である。
- SHMMIN
- 共有メモリーセグメントのバイト単位の大きさの下限:
実装依存 (現在は 1
バイトだが、実質的な最小サイズは
PAGE_SIZE である)。
- SHMMNI
- システム全体の共有メモリーセグメント数の上限値。
この上限値のデフォルトは、
Linux 2.2 以降では 128、 Linux 2.4
以降で 4096 である。
- Linux
では、この上限値は
/proc/sys/kernel/shmmni
経由で参照したり、変更したりできる。
プロセス当りの共有メモリーセグメントの個数の最大値
(
SHMSEG)
に関する実装上の制限はない。
バージョン 2.3.30
までは、Linux は
削除が予定されている共有メモリーセグメントに対して
shmget() が行われると
EIDRM
を返していた。
IPC_PRIVATE
という名前を選んだのはおそらく失敗であろう。
IPC_NEW
の方がより明確にその機能を表しているだろう。
shmop(2) を参照。
memfd_create(2),
shmat(2),
shmctl(2),
shmdt(2),
ftok(3),
capabilities(7),
shm_overview(7),
sysvipc(7)
この man ページは Linux
man-pages
プロジェクトのリリース
5.10
の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/
に書かれている。