[インデックス 18226] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるOpenBSD向けのシステムコール定数に関するものです。具体的には、src/pkg/syscall/mkerrors.sh
スクリプトと、それによって生成されるsrc/pkg/syscall/zerrors_openbsd_386.go
およびsrc/pkg/syscall/zerrors_openbsd_amd64.go
ファイルが変更されています。これらの変更は、mmap(2)
、madvise(2)
、msync(2)
、mlockall(2)
といったメモリマッピング関連のシステムコールで使用される定数をGoのsyscall
パッケージに適切に含めることを目的としています。
コミット
このコミットは、OpenBSD環境においてmmap
関連のシステムコール定数がGoのsyscall
パッケージに不足していた問題を解決します。mkerrors.sh
スクリプトに<sys/mman.h>
ヘッダーのインクルードを追加することで、これらの定数が自動生成されるzerrors_openbsd_*.go
ファイルに取り込まれるようになります。これにより、GoプログラムからOpenBSDのメモリマッピング関連のシステムコールを正しく利用できるようになります。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f40dd8f1d9a1c2ed2e7160702b7466df5d9ccb5b
元コミット内容
commit f40dd8f1d9a1c2ed2e7160702b7466df5d9ccb5b
Author: Joel Sing <jsing@google.com>
Date: Mon Jan 13 11:25:48 2014 +1100
syscall: include mmap constants in openbsd zerror* files
Include the <sys/mman.h> header for OpenBSD mkerrors.sh. This brings
in constants used with madvise(2), mmap(2), msync(2) and mlockall(2).
Fixes #4929
R=golang-codereviews, minux.ma
CC=golang-codereviews
https://golang.org/cl/50930043
変更の背景
この変更の背景には、Go言語のsyscall
パッケージがOpenBSD環境でmmap
関連のシステムコールを完全にサポートしていなかったという問題があります。具体的には、madvise(2)
、mmap(2)
、msync(2)
、mlockall(2)
といったシステムコールで使用される定数(例: MAP_SHARED
, PROT_READ
, MADV_DONTNEED
など)がGoのsyscall
パッケージのOpenBSD固有の定数ファイル(zerrors_openbsd_386.go
、zerrors_openbsd_amd64.go
)に定義されていませんでした。
Goのsyscall
パッケージは、各OSやアーキテクチャ固有のシステムコール定数を自動生成するスクリプト(mkerrors.sh
など)を使用しています。これらのスクリプトは、C言語のヘッダーファイルを解析し、対応するGoの定数定義を生成します。しかし、OpenBSD向けのmkerrors.sh
は、メモリマッピング関連の定数が定義されている<sys/mman.h>
ヘッダーをインクルードしていなかったため、これらの定数がGoのコードに反映されていませんでした。
この不足は、GoプログラムがOpenBSD上でメモリマッピングを操作しようとした際に、必要な定数が未定義であるためにコンパイルエラーや実行時エラーを引き起こす可能性がありました。この問題はGoのIssue #4929として報告されており、このコミットはその問題を解決するために行われました。
前提知識の解説
Go言語のsyscall
パッケージ
Go言語のsyscall
パッケージは、オペレーティングシステムが提供する低レベルなプリミティブ(システムコール)へのインターフェースを提供します。これにより、Goプログラムはファイル操作、ネットワーク通信、プロセス管理、メモリ管理など、OSカーネルが提供する機能に直接アクセスできます。
syscall
パッケージは、OSやアーキテクチャごとに異なるシステムコール番号や定数を扱うため、プラットフォーム固有のコードを含んでいます。これらの定数の一部は、C言語のヘッダーファイルから自動生成されることが多く、そのためにmkerrors.sh
のようなスクリプトが利用されます。
mkerrors.sh
スクリプトとzerrors_*.go
ファイル
Goのsyscall
パッケージには、mkerrors.sh
のようなスクリプトが存在します。これらのスクリプトは、特定のOS(この場合はOpenBSD)のC言語ヘッダーファイルを読み込み、その中に定義されているエラーコード、フラグ、定数などをGo言語のコードとして自動生成します。生成されたファイルは通常zerrors_os_arch.go
のような命名規則に従います(例: zerrors_openbsd_386.go
, zerrors_openbsd_amd64.go
)。
この自動生成プロセスにより、Go開発者はOS固有の定数を手動でGoのコードに移植する手間を省き、OSのヘッダーファイルが更新された際にも容易に追従できるようになります。
メモリマッピング関連のシステムコール
mmap(2)
(memory map): ファイルやデバイス、または匿名メモリ領域をプロセスの仮想アドレス空間にマッピングするためのシステムコールです。これにより、ファイルの内容をメモリのように直接アクセスしたり、プロセス間でメモリを共有したりすることが可能になります。MAP_SHARED
: マッピングされたメモリへの変更が、そのメモリをマッピングしている他のプロセスや、元のファイルに反映されることを示します。MAP_PRIVATE
: マッピングされたメモリへの変更が、呼び出し元プロセスにのみ可視であり、元のファイルや他のプロセスには影響しないことを示します(コピーオンライト)。PROT_READ
: マッピングされたメモリ領域が読み取り可能であることを示します。PROT_WRITE
: マッピングされたメモリ領域が書き込み可能であることを示します。PROT_EXEC
: マッピングされたメモリ領域が実行可能であることを示します。MAP_ANON
: ファイルではなく、匿名メモリ領域をマッピングすることを示します。
madvise(2)
(memory advise): カーネルに対して、特定のメモリ領域の利用パターンに関するヒントを与えるシステムコールです。これにより、カーネルはメモリ管理の最適化を行うことができます。MADV_NORMAL
: 通常のアクセスパターン。MADV_RANDOM
: ランダムなアクセスパターン。MADV_SEQUENTIAL
: 順次アクセスパターン。MADV_WILLNEED
: 将来的にアクセスされる可能性が高いことを示し、プリフェッチを促します。MADV_DONTNEED
: 今後アクセスされない可能性が高いことを示し、メモリの解放を促します。
msync(2)
(memory sync):mmap
によってマッピングされたメモリ領域の内容を、対応するファイルに同期させるシステムコールです。MS_ASYNC
: 非同期で同期を行います。MS_SYNC
: 同期が完了するまでブロックします。MS_INVALIDATE
: キャッシュされたデータを無効化し、ファイルから再読み込みします。
mlockall(2)
(memory lock all): プロセスの仮想アドレス空間全体、または指定された部分を物理メモリにロックし、スワップアウトされないようにするシステムコールです。リアルタイムアプリケーションなどでパフォーマンスを保証するために使用されます。
これらのシステムコールは、Unix系OSにおけるメモリ管理の重要な要素であり、Goプログラムが低レベルなメモリ操作を行う際に必要となります。
技術的詳細
このコミットの技術的な核心は、Goのsyscall
パッケージがOpenBSDのメモリマッピング関連のシステムコール定数を正しく認識し、利用できるようにすることです。
-
mkerrors.sh
の変更:src/pkg/syscall/mkerrors.sh
スクリプトは、OpenBSD向けのGoのsyscall
定数を生成する際に、C言語のヘッダーファイルを読み込みます。このスクリプトのincludes_OpenBSD
変数に、新たに<sys/mman.h>
が追加されました。--- a/src/pkg/syscall/mkerrors.sh +++ b/src/pkg/syscall/mkerrors.sh @@ -143,6 +143,7 @@ includes_OpenBSD='\ #include <sys/types.h> #include <sys/param.h> #include <sys/event.h> +#include <sys/mman.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/sysctl.h>
この変更により、
mkerrors.sh
が実行される際に、OpenBSDのシステムに存在する<sys/mman.h>
ヘッダーファイルが解析対象に含まれるようになります。このヘッダーファイルには、mmap
、madvise
、msync
、mlockall
といったシステムコールで使用される様々な定数(例:MAP_SHARED
,PROT_READ
,MADV_DONTNEED
など)が定義されています。 -
zerrors_openbsd_*.go
ファイルの自動生成:mkerrors.sh
が<sys/mman.h>
を解析するようになった結果、その中に定義されている定数がGoのsyscall
パッケージのOpenBSD固有の定数ファイルに自動的に追加されます。コミットの差分を見ると、src/pkg/syscall/zerrors_openbsd_386.go
とsrc/pkg/syscall/zerrors_openbsd_amd64.go
の両方に、MADV_*
、MAP_*
、MS_*
、PROT_*
といった定数が大量に追加されていることが確認できます。これらの定数は、C言語のヘッダーファイルで定義されているシンボリック定数(通常はプリプロセッサマクロや
enum
)に対応しており、Goのコードではconst
キーワードを用いて定義されます。例えば、C言語の#define MAP_SHARED 0x0001
は、GoではMAP_SHARED = 0x1
のように変換されます。この自動生成の仕組みにより、GoプログラムはOpenBSD環境でこれらの定数を直接参照し、
mmap
などのシステムコールを呼び出す際に正しいフラグやオプションを指定できるようになります。これにより、Goのsyscall
パッケージのOpenBSDサポートがより完全なものとなり、メモリマッピングを必要とするGoアプリケーションの開発が容易になります。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下の3つのファイルです。
-
src/pkg/syscall/mkerrors.sh
: このシェルスクリプトは、Goのsyscall
パッケージの定数を生成するために使用されます。変更点としては、OpenBSD向けのインクルードリストに<sys/mman.h>
が追加されています。--- a/src/pkg/syscall/mkerrors.sh +++ b/src/pkg/syscall/mkerrors.sh @@ -143,6 +143,7 @@ includes_OpenBSD='\ #include <sys/types.h> #include <sys/param.h> #include <sys/event.h> +#include <sys/mman.h> #include <sys/socket.h> #include <sys/sockio.h> #include <sys/sysctl.h>
-
src/pkg/syscall/zerrors_openbsd_386.go
: OpenBSDの32ビット(i386)アーキテクチャ向けのシステムコール定数が定義されているGoファイルです。mkerrors.sh
の変更により、mmap
関連の定数が追加されています。// 抜粋 const ( // ... 既存の定数 ... MADV_DONTNEED = 0x4 MADV_FREE = 0x6 MADV_NORMAL = 0x0 MADV_RANDOM = 0x1 MADV_SEQUENTIAL = 0x2 MADV_SPACEAVAIL = 0x5 MADV_WILLNEED = 0x3 MAP_ANON = 0x1000 MAP_COPY = 0x4 MAP_FILE = 0x0 MAP_FIXED = 0x10 MAP_FLAGMASK = 0x1ff7 MAP_HASSEMAPHORE = 0x200 MAP_INHERIT = 0x80 MAP_INHERIT_COPY = 0x1 MAP_INHERIT_DONATE_COPY = 0x3 MAP_INHERIT_NONE = 0x2 MAP_INHERIT_SHARE = 0x0 MAP_NOEXTEND = 0x100 MAP_NORESERVE = 0x40 MAP_PRIVATE = 0x2 MAP_RENAME = 0x20 MAP_SHARED = 0x1 MAP_TRYFIXED = 0x400 MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 // ... MS_ASYNC = 0x1 MS_INVALIDATE = 0x4 MS_SYNC = 0x2 // ... PROT_EXEC = 0x4 PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 // ... )
-
src/pkg/syscall/zerrors_openbsd_amd64.go
: OpenBSDの64ビット(amd64)アーキテクチャ向けのシステムコール定数が定義されているGoファイルです。こちらも同様に、mmap
関連の定数が追加されています。追加された定数の内容はzerrors_openbsd_386.go
と同一です。// 抜粋 (zerrors_openbsd_386.go と同様の定数が追加されている) const ( // ... 既存の定数 ... MADV_DONTNEED = 0x4 MADV_FREE = 0x6 MADV_NORMAL = 0x0 MADV_RANDOM = 0x1 MADV_SEQUENTIAL = 0x2 MADV_SPACEAVAIL = 0x5 MADV_WILLNEED = 0x3 MAP_ANON = 0x1000 MAP_COPY = 0x4 MAP_FILE = 0x0 MAP_FIXED = 0x10 MAP_FLAGMASK = 0x1ff7 MAP_HASSEMAPHORE = 0x200 MAP_INHERIT = 0x80 MAP_INHERIT_COPY = 0x1 MAP_INHERIT_DONATE_COPY = 0x3 MAP_INHERIT_NONE = 0x2 MAP_INHERIT_SHARE = 0x0 MAP_NOEXTEND = 0x100 MAP_NORESERVE = 0x40 MAP_PRIVATE = 0x2 MAP_RENAME = 0x20 MAP_SHARED = 0x1 MAP_TRYFIXED = 0x400 MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 // ... MS_ASYNC = 0x1 MS_INVALIDATE = 0x4 MS_SYNC = 0x2 // ... PROT_EXEC = 0x4 PROT_NONE = 0x0 PROT_READ = 0x1 PROT_WRITE = 0x2 // ... )
コアとなるコードの解説
このコミットの主要な変更は、mkerrors.sh
スクリプトに<sys/mman.h>
ヘッダーのインクルードを追加したことです。これにより、OpenBSD環境でGoのsyscall
パッケージがメモリマッピング関連のシステムコール定数を正しく利用できるようになりました。
-
mkerrors.sh
の変更:includes_OpenBSD
変数に#include <sys/mman.h>
が追加されたことで、mkerrors.sh
がOpenBSDのシステムコール定数を生成する際に、mmap
、madvise
、msync
、mlockall
といったメモリ管理関連のシステムコールで使用される定数も自動的にGoのコードに変換されるようになりました。これは、GoがC言語のヘッダーファイルを解析してGoの定数を生成する一般的なパターンに従っています。 -
zerrors_openbsd_386.go
およびzerrors_openbsd_amd64.go
への定数追加: これらのファイルはmkerrors.sh
によって自動生成されるため、手動で編集されることはありません。mkerrors.sh
の変更がトリガーとなり、以下の主要な定数群がGoのconst
として追加されました。MADV_*
定数:madvise(2)
システムコールで使用されるアドバイスフラグです。MADV_DONTNEED
: 指定されたメモリ領域の内容はもう必要ないことをカーネルに伝えます。これにより、カーネルはそのメモリを解放したり、スワップアウトしたりする可能性があります。MADV_FREE
: メモリ領域を解放し、後で再利用できるようにします。MADV_NORMAL
: 通常のアクセスパターンを示します。MADV_RANDOM
: ランダムなアクセスパターンを示します。MADV_SEQUENTIAL
: 順次アクセスパターンを示します。MADV_SPACEAVAIL
: 将来的にメモリが必要になることを示します。MADV_WILLNEED
: 将来的にアクセスされる可能性が高いことを示し、プリフェッチを促します。
MAP_*
定数:mmap(2)
システムコールで使用されるマッピングタイプやフラグです。MAP_ANON
: ファイルではなく、匿名メモリ領域をマッピングします。MAP_COPY
: コピーオンライトマッピングを作成します。MAP_FILE
: ファイルをマッピングします。MAP_FIXED
: 指定されたアドレスにマッピングを固定しようとします。MAP_FLAGMASK
: マッピングフラグのマスク。MAP_HASSEMAPHORE
: セマフォを持つマッピング。MAP_INHERIT*
: 子プロセスへの継承に関するフラグ。MAP_NOEXTEND
: ファイルを拡張しない。MAP_NORESERVE
: スワップ領域を予約しない。MAP_PRIVATE
: プライベートなコピーオンライトマッピング。MAP_RENAME
: マッピングをリネーム。MAP_SHARED
: 共有マッピング。MAP_TRYFIXED
:MAP_FIXED
を試みるが、失敗してもエラーにしない。
MCL_*
定数:mlockall(2)
システムコールで使用されるフラグです。MCL_CURRENT
: 現在のメモリマッピングをロックします。MCL_FUTURE
: 将来のマッピングもロックします。
MS_*
定数:msync(2)
システムコールで使用される同期フラグです。MS_ASYNC
: 非同期で同期を行います。MS_INVALIDATE
: キャッシュされたデータを無効化し、ファイルから再読み込みします。MS_SYNC
: 同期が完了するまでブロックします。
PROT_*
定数:mmap(2)
システムコールで使用されるメモリ保護フラグです。PROT_EXEC
: 実行可能。PROT_NONE
: アクセス不可。PROT_READ
: 読み取り可能。PROT_WRITE
: 書き込み可能。
これらの定数がGoのsyscall
パッケージに組み込まれたことで、OpenBSD上で動作するGoプログラムは、C言語で書かれたプログラムと同様に、これらの低レベルなメモリ管理機能を直接、かつ型安全に利用できるようになりました。これにより、Goのクロスプラットフォーム互換性が向上し、OpenBSD環境でのGoアプリケーション開発の幅が広がりました。
関連リンク
- Go Issue #4929: https://github.com/golang/go/issues/4929
- Go CL 50930043: https://golang.org/cl/50930043
参考にした情報源リンク
mmap(2)
man page (OpenBSD): https://man.openbsd.org/mmap.2madvise(2)
man page (OpenBSD): https://man.openbsd.org/madvise.2msync(2)
man page (OpenBSD): https://man.openbsd.org/msync.2mlockall(2)
man page (OpenBSD): https://man.openbsd.org/mlockall.2- Go
syscall
package documentation: https://pkg.go.dev/syscall - Go
mkerrors.sh
script (source code): https://github.com/golang/go/blob/master/src/syscall/mkerrors.sh (コミット当時のバージョンとは異なる可能性がありますが、一般的な動作を理解するために参照) - Go
zerrors_openbsd_amd64.go
(source code): https://github.com/golang/go/blob/master/src/syscall/zerrors_openbsd_amd64.go (コミット当時のバージョンとは異なる可能性がありますが、一般的な構造を理解するために参照)