Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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.gozerrors_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のメモリマッピング関連のシステムコール定数を正しく認識し、利用できるようにすることです。

  1. 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>ヘッダーファイルが解析対象に含まれるようになります。このヘッダーファイルには、mmapmadvisemsyncmlockallといったシステムコールで使用される様々な定数(例: MAP_SHARED, PROT_READ, MADV_DONTNEEDなど)が定義されています。

  2. zerrors_openbsd_*.goファイルの自動生成: mkerrors.sh<sys/mman.h>を解析するようになった結果、その中に定義されている定数がGoのsyscallパッケージのOpenBSD固有の定数ファイルに自動的に追加されます。コミットの差分を見ると、src/pkg/syscall/zerrors_openbsd_386.gosrc/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つのファイルです。

  1. 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>
    
  2. 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
    	// ...
    )
    
  3. 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のシステムコール定数を生成する際に、mmapmadvisemsyncmlockallといったメモリ管理関連のシステムコールで使用される定数も自動的に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アプリケーション開発の幅が広がりました。

関連リンク

参考にした情報源リンク