[インデックス 17373] ファイルの概要
このコミットは、Go言語のsyscallパッケージにDragonFly BSDオペレーティングシステムとAMD64アーキテクチャのサポートを追加するものです。具体的には、DragonFly/AMD64環境でGoプログラムがシステムコールを直接呼び出せるようにするための低レベルなアセンブリコード、Go言語のラッパー、および関連する型定義が追加されています。また、システムコール関連のファイルを自動生成するためのスクリプトもDragonFly BSDに対応するように更新されています。
コミット
コミットハッシュ: 8f3f4c96a3d13be7cd9e4a82e2df51d840cda756
作者: Joel Sing jsing@google.com
コミット日時: 2013年8月24日 土曜日 01:51:25 +1000
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/8f3f4c96a3d13be7cd9e4a82e2df51d840cda756
元コミット内容
syscall: dragonfly/amd64 support
Add syscall support for dragonfly/amd64.
Also add support for generating syscall z* files for dragonfly.
R=bradfitz
CC=golang-dev
https://golang.org/cl/13188043
変更の背景
Go言語は、様々なオペレーティングシステムとアーキテクチャをサポートすることを目標としています。このコミットが行われた2013年当時、Goは主要なOS(Linux, macOS, Windowsなど)とアーキテクチャ(AMD64, ARMなど)をサポートしていましたが、より多くのプラットフォームへの対応を継続的に進めていました。
DragonFly BSDは、FreeBSD 4.8からフォークしたオープンソースのUnix系オペレーティングシステムであり、独自の設計思想と技術(例: HAMMERファイルシステム、LWKTなど)を持っています。GoプログラムがDragonFly BSD上でネイティブに動作し、そのシステムリソースを効率的に利用するためには、GoランタイムがDragonFly BSDのシステムコールインターフェースを理解し、適切に呼び出すメカニズムが必要でした。
このコミットは、Go言語がDragonFly BSD/AMD64環境で動作するための基盤を構築し、GoプログラムがこのOS上でシステムレベルの操作(ファイルI/O、ネットワーク通信、プロセス管理など)を実行できるようにすることを目的としています。これにより、Go開発者はDragonFly BSDをターゲットとしたアプリケーションを開発できるようになり、Go言語のエコシステムがさらに拡大します。
前提知識の解説
1. システムコール (System Call)
システムコールは、オペレーティングシステム(OS)のカーネルが提供するサービスを、ユーザー空間のプログラムが利用するためのインターフェースです。ファイル操作(読み書き)、ネットワーク通信、メモリ管理、プロセス生成など、OSが管理するリソースへのアクセスはすべてシステムコールを通じて行われます。Go言語のような高レベル言語で書かれたプログラムも、最終的にはこれらのシステムコールを呼び出すことでOSと対話します。
2. Go言語の syscall パッケージ
Go言語の標準ライブラリにはsyscallパッケージが含まれており、これはOS固有のシステムコールへの低レベルなアクセスを提供します。このパッケージは、OSやアーキテクチャごとに異なるシステムコールの呼び出し規約(レジスタの使用方法、引数の渡し方、戻り値の処理など)を抽象化し、Goプログラムから統一されたインターフェースでシステムコールを呼び出せるようにします。
3. GOOS と GOARCH
Go言語のビルドシステムでは、環境変数GOOSとGOARCHを使用して、ターゲットとなるオペレーティングシステムとアーキテクチャを指定します。
GOOS: ターゲットOS (例:linux,darwin,windows,freebsd,dragonfly)GOARCH: ターゲットアーキテクチャ (例:amd64,arm,386)
これらの変数は、Goコンパイラが特定のOS/アーキテクチャ向けにコードを生成する際に使用され、また、Goソースコード内のビルドタグ(例: // +build dragonfly amd64)と組み合わせて、特定のファイルが特定の環境でのみコンパイルされるように制御します。
4. ビルドタグ (Build Tags)
Goのソースファイルには、ファイルの先頭に// +build tag形式のコメントを記述することで、ビルドタグを設定できます。これにより、特定のタグが有効な場合にのみそのファイルがコンパイルされるようになります。例えば、// +build dragonfly amd64と書かれたファイルは、GOOS=dragonflyかつGOARCH=amd64の場合にのみビルドに含まれます。
5. mksyscall.pl, mkerrors.sh, mksysnum_*.pl スクリプト
Goのsyscallパッケージでは、OS固有のシステムコール定数や構造体、システムコールラッパーなどを自動生成するためにPerlスクリプトが使用されます。
mksyscall.pl: GoのsyscallパッケージのGo言語ラッパーコードを生成します。//sysコメントでマークされた関数定義を解析し、対応するシステムコール呼び出しコードを生成します。mkerrors.sh: OS固有のエラーコード定数(EINVALなど)をGoの定数として生成します。C言語のヘッダファイルから情報を抽出します。mksysnum_*.pl: OS固有のシステムコール番号(例:SYS_READ)をGoの定数として生成します。通常、OSのカーネルソースツリーにあるシステムコール定義ファイル(例:syscalls.master)から情報を抽出します。
これらのスクリプトは、Goのsyscallパッケージが様々なOS/アーキテクチャに対応するための重要な自動化ツールです。
6. z* ファイル
Goのsyscallパッケージには、zerrors_*.go, zsyscall_*.go, zsysnum_*.goといった命名規則のファイルが存在します。これらは上記のmkerrors.sh, mksyscall.pl, mksysnum_*.plスクリプトによって自動生成されるファイルであり、OS/アーキテクチャ固有のエラー定数、システムコールラッパー、システムコール番号などが定義されています。これらのファイルは手動で編集されることはなく、Goのビルドプロセスの一部として必要に応じて再生成されます。
7. DragonFly BSD
DragonFly BSDは、2003年にFreeBSD 4.8からフォークして開発が始まったオープンソースのUnix系OSです。FreeBSDとは異なるカーネル設計思想を持ち、特にスケーラビリティとパフォーマンスの向上を目指しています。特徴的な技術として、トランザクションセマンティクスを持つファイルシステム「HAMMER」や、軽量カーネルスレッド(LWKT)などが挙げられます。GoがこのOSをサポートすることで、DragonFly BSD上で動作する高性能なGoアプリケーションの開発が可能になります。
技術的詳細
このコミットは、Go言語がDragonFly BSD/AMD64環境でシステムコールを効率的かつ安全に実行できるようにするための包括的な変更を導入しています。
Goのsyscallパッケージは、OS固有のシステムコールを抽象化し、Goプログラムから利用できるようにする役割を担っています。新しいOS/アーキテクチャのサポートを追加する際には、以下の主要なコンポーネントが必要となります。
- アセンブリ言語によるシステムコールラッパー: 実際のシステムコール呼び出しは、OSのABI(Application Binary Interface)に従って、アセンブリ言語で記述される必要があります。これは、GoのランタイムとOSカーネル間の低レベルなインターフェースを提供します。
- Go言語によるシステムコールラッパー: アセンブリ言語で定義された低レベルなシステムコールを、Go言語の関数としてラップし、より使いやすいインターフェースを提供します。
- OS固有の型定義と定数: システムコールで使用される構造体、定数、エラーコードなどをGo言語で定義します。これらはC言語のヘッダファイルに対応するものです。
- ビルドスクリプトの更新: 新しいOS/アーキテクチャ向けに、システムコール関連のファイルを自動生成するためのスクリプト(
mksyscall.pl、mkerrors.sh、mksysnum_*.pl)を更新し、DragonFly BSDの情報を正しく処理できるようにします。 - ビルドタグの追加: 既存のGoソースファイルにDragonFly BSD向けのビルドタグを追加し、特定のOSに依存するコードが正しくコンパイルされるようにします。
このコミットでは、これらの要素がすべて導入されています。
asm_dragonfly_amd64.s: DragonFly/AMD64環境でのシステムコール呼び出しを行うためのアセンブリコードが記述されています。Syscall,Syscall6,Syscall9,RawSyscall,RawSyscall6といったGoのsyscallパッケージの主要な関数が、OSのABIに従ってレジスタに引数をセットし、SYSCALL命令を実行するロジックを含んでいます。エラー処理や戻り値のレジスタからの取得もここで行われます。syscall_dragonfly.go: DragonFly BSD固有のシステムコールラッパー関数や、ParseDirentのようなOS固有のヘルパー関数がGo言語で実装されています。このファイルには、//sysコメントでマークされた多くのシステムコール定義が含まれており、これらはmksyscall.plによってzsyscall_dragonfly_amd64.goのような自動生成ファイルに変換されます。syscall_dragonfly_amd64.go: DragonFly/AMD64に特化したGo言語のヘルパー関数(例:Getpagesize,TimespecToNsec)や、sendfileのような特定のシステムコールに対するGoラッパーが定義されています。types_dragonfly.go: DragonFly BSDのC言語ヘッダファイルに対応するGo言語の型定義(構造体、定数など)が含まれています。これらはcgo -godefsツールによって生成されるための入力ファイルとして機能します。SockaddrDatalink,Stat_t,Direntなど、OS固有のデータ構造が定義されています。mkall.sh,mkerrors.sh,mksyscall.pl,mksysnum_dragonfly.pl: これらのスクリプトが更新され、DragonFly BSD向けのz*ファイルの生成をサポートするようになりました。特にmksysnum_dragonfly.plは新規追加され、DragonFly BSDのシステムコール番号を自動的に取得・生成する役割を担います。mkerrors.shにはDragonFly BSD固有のCヘッダファイルのインクルードパスが追加されています。- 既存ファイルのビルドタグ更新:
bpf_bsd.go,consistency_unix_test.go,env_unix.goなど、多くの既存のsyscallパッケージのGoソースファイルにdragonflyビルドタグが追加されています。これにより、これらのファイルがDragonFly BSD環境でもコンパイルされるようになり、OS間の共通コードが再利用されます。
この変更により、GoコンパイラはDragonFly BSD/AMD64をターゲットとしてGoプログラムをビルドできるようになり、GoプログラムはDragonFly BSDのカーネルと直接対話できるようになります。
コアとなるコードの変更箇所
このコミットで追加または大幅に変更された主要なファイルは以下の通りです。
-
src/pkg/syscall/asm_dragonfly_amd64.s(新規追加):- DragonFly/AMD64環境におけるGoの
Syscall,Syscall6,Syscall9,RawSyscall,RawSyscall6関数のアセンブリ実装。 - システムコール番号と引数をレジスタに配置し、
SYSCALL命令を実行する。 - システムコールからの戻り値とエラー(
errno)を処理するロジックを含む。
- DragonFly/AMD64環境におけるGoの
-
src/pkg/syscall/mksysnum_dragonfly.pl(新規追加):- DragonFly BSDのシステムコール番号を自動生成するためのPerlスクリプト。
- DragonFly BSDのカーネルソースからシステムコール定義を読み込み、Goの定数として出力する。
-
src/pkg/syscall/route_dragonfly.go(新規追加):- DragonFly BSDのルーティングソケットとメッセージに関するGo言語の型定義とヘルパー関数。
anyMessageからRoutingMessageへの変換ロジックや、InterfaceAnnounceMessage,InterfaceMulticastAddrMessageなどの構造体が含まれる。
-
src/pkg/syscall/syscall_dragonfly.go(新規追加):- DragonFly BSD固有のシステムコールラッパー関数と、OS固有のヘルパー関数(例:
nametomib,ParseDirent)のGo言語実装。 //sysコメントでマークされた多数のシステムコール定義が含まれており、これらはmksyscall.plによって自動生成されるコードの元となる。Pipe,Pread,PwriteなどのGoラッパー関数も定義されている。
- DragonFly BSD固有のシステムコールラッパー関数と、OS固有のヘルパー関数(例:
-
src/pkg/syscall/syscall_dragonfly_amd64.go(新規追加):- DragonFly/AMD64に特化したGo言語のヘルパー関数(例:
Getpagesize,TimespecToNsec,NsecToTimespec,TimevalToNsec,NsecToTimeval)。 SetKevent,SetLen,SetControllenなどの構造体フィールド設定ヘルパー。sendfileシステムコールのGoラッパー。
- DragonFly/AMD64に特化したGo言語のヘルパー関数(例:
-
src/pkg/syscall/types_dragonfly.go(新規追加):- DragonFly BSDのC言語ヘッダファイルに対応するGo言語の型定義と定数。
Timespec,Timeval,Rusage,Rlimit,Stat_t,Dirent,SockaddrDatalinkなど、OS固有のデータ構造が定義されている。cgo -godefsツールによってGoの型定義が生成されるための入力ファイル。
-
src/pkg/syscall/mkall.sh(変更):dragonfly_amd64ケースが追加され、mksyscall.pl,mksysnum_dragonfly.pl,go tool cgo -godefsがDragonFly向けに実行されるように設定された。syscall_goos変数の設定で、dragonflyがsyscall_bsd.goを使用するOSリストに追加された。
-
src/pkg/syscall/mkerrors.sh(変更):includes_DragonFly変数が追加され、DragonFly BSDのエラーコード生成に必要なCヘッダファイルがリストアップされた。
-
src/pkg/syscall/mksyscall.pl(変更):-dragonflyオプションが追加され、DragonFly BSD固有のシステムコール引数処理ロジック(特にint64型の引数処理)が実装された。
-
既存のGoソースファイル (
bpf_bsd.go,consistency_unix_test.go,env_unix.go,exec_bsd.go,exec_unix.go,passfd_test.go,route_bsd.go,sockcmsg_unix.go,syscall_bsd.go,syscall_no_getwd.go,syscall_unix.go) (変更):- ファイルの先頭にあるビルドタグに
dragonflyが追加され、これらのファイルがDragonFly BSD環境でもコンパイルされるようになった。 syscall_bsd.goでは、Getsockname関数内のコメントでDragonFly BSDもOpenBSDと同様の挙動を示す可能性が指摘され、条件分岐にruntime.GOOS == "dragonfly"が追加された。passfd_test.goでは、DragonFly BSDでのsendmsgの問題によりテストがスキップされるようにt.Skipが追加された。
- ファイルの先頭にあるビルドタグに
コアとなるコードの解説
src/pkg/syscall/asm_dragonfly_amd64.s
このアセンブリファイルは、GoプログラムがDragonFly BSDのカーネルと直接対話するための最も低レベルな部分です。Goのsyscallパッケージが提供するSyscall, Syscall6, Syscall9(それぞれ引数の数が異なるシステムコール呼び出し関数)およびRawSyscall, RawSyscall6(Goランタイムのスケジューラをブロックしない生システムコール呼び出し)の実装を含みます。
TEXT ·Syscall(SB),NOSPLIT,$0-64:Syscall関数の定義。NOSPLITはスタックフレームを分割しないことを意味し、$0-64はスタックフレームサイズと引数・戻り値の合計サイズを示します。CALL runtime·entersyscall(SB)/CALL runtime·exitsyscall(SB): これらの呼び出しは、Goランタイムのスケジューラに対して、システムコールに入ろうとしていること、またはシステムコールから戻ったことを通知します。これにより、GoのスケジューラはGoroutineのスケジューリングを適切に調整できます。RawSyscall系にはこれらの呼び出しはありません。MOVQ 16(SP), DIなど: Goの関数呼び出し規約に従ってスタックに積まれた引数(a1,a2,a3など)を、DragonFly BSDのシステムコール呼び出し規約に従ってレジスタ(DI,SI,DX,R10,R8,R9)に移動させます。MOVQ 8(SP), AX: システムコール番号をAXレジスタにロードします。SYSCALL: 実際のシステムコールを実行する命令です。この命令が実行されると、CPUは特権モードに切り替わり、カーネル内の対応するシステムコールハンドラが実行されます。JCC ok:SYSCALL命令の実行後、キャリーフラグ(CF)がセットされているかどうかをチェックします。Unix系システムでは、システムコールがエラーを返した場合にCFがセットされることが一般的です。- エラー処理:
JCC okのジャンプが失敗した場合(エラーが発生した場合)、AXレジスタに格納されているエラーコード(errno)をGoの戻り値として設定します。成功した場合はerrnoを0に設定します。 - 戻り値: システムコールからの戻り値(
r1,r2)はAXとDXレジスタから取得され、Goの戻り値としてスタックに格納されます。
このアセンブリコードは、GoのランタイムとDragonFly BSDカーネル間の重要な橋渡し役を担っています。
src/pkg/syscall/syscall_dragonfly.go
このファイルは、DragonFly BSD固有のシステムコールをGo言語でラップし、Goプログラムから利用しやすくするためのものです。
//sysnb pipe() (r int, w int, err error)://sysnbは、この行がシステムコール定義であり、mksyscall.plによって自動生成されることを示します。nbは"non-blocking"ではなく"no-blocking"、つまりGoランタイムのスケジューラをブロックしないRawSyscallを使用することを示唆します。func Pipe(p []int) (err error): 上記のpipe()システムコールをGoの慣用的なPipe関数としてラップしています。引数pは2つの要素を持つスライスで、読み込み側と書き込み側のファイルディスクリプタが格納されます。//sys extpread(fd int, p []byte, flags int, offset int64) (n int, err error):preadシステムコールの定義。extpは拡張されたpreadであることを示唆します。func Pread(fd int, p []byte, offset int64) (n int, err error):extpreadをラップしたPread関数。func nametomib(name string) (mib []_C_int, err error):sysctlシステムコールを使用して、文字列形式のカーネルパラメータ名(例: "kern.hostname")を、sysctlが内部で使用する整数配列(MIB: Management Information Base)に変換するヘルパー関数です。これはOS固有のsysctlインターフェースを扱うために必要です。func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string): ディレクトリの内容を読み込む際に使用されるDirent構造体のバイト列を解析し、ファイル名を抽出する関数です。OSによってDirent構造体のレイアウトが異なるため、OS固有の実装が必要です。
このファイルは、GoのsyscallパッケージがDragonFly BSDのシステムコールをGoのセマンティクスに適合させるための主要なロジックを含んでいます。
src/pkg/syscall/types_dragonfly.go
このファイルは、DragonFly BSDのC言語ヘッダファイルで定義されている様々な構造体や定数をGo言語の型として再定義しています。これは、GoプログラムがC言語のシステムコールインターフェースと互換性のあるデータ構造を扱えるようにするために不可欠です。
// +godefs map struct_in_addr [4]byte /* in_addr */:cgo -godefsツールに対する指示で、C言語のstruct in_addrをGoの[4]byteにマッピングすることを示します。package syscall:syscallパッケージの一部であることを示します。const ( sizeofPtr = C.sizeofPtr ... ): C言語のsizeof演算子を使って、ポインタや基本的な型のサイズをGoの定数として定義しています。これは、メモリレイアウトの計算やポインタ演算に必要です。type Timespec C.struct_timespec: C言語のstruct timespecをGoのTimespec型として定義しています。他の多くの構造体も同様に定義されています(例:Timeval,Rusage,Stat_t,Dirent,RawSockaddrInet4など)。const ( S_IFMT = C.S_IFMT ... ): ファイルモードやソケット関連の定数など、C言語のヘッダファイルで定義されている定数をGoの定数として定義しています。
このファイルは、GoのsyscallパッケージがDragonFly BSDのシステムコールインターフェースと型レベルで互換性を持つための基盤を提供します。
関連リンク
- Go言語公式ドキュメント: https://golang.org/
- DragonFly BSD公式ウェブサイト: https://www.dragonflybsd.org/
- Go
syscallパッケージのソースコード (GitHub): https://github.com/golang/go/tree/master/src/syscall - Go Change-Id 13188043 (Gerrit): https://golang.org/cl/13188043
参考にした情報源リンク
- Go言語の
syscallパッケージの内部構造に関する一般的な知識 - Unix系OSにおけるシステムコール呼び出し規約(ABI)に関する一般的な知識
- DragonFly BSDの概要に関する情報
- Go言語のビルドタグに関する情報
- Go言語の
mksyscall.plなどのスクリプトの役割に関する情報 - Go言語の
z*ファイルに関する情報 git diffコマンドで表示されたコミット内容read_fileツールで取得したコミットデータ (./commit_data/17373.txt)- Google Web Search (上記「変更の背景」および「前提知識の解説」の情報を補完するため)
- "DragonFly BSD operating system"
- "Go syscall package internals"
- "Go build tags GOOS GOARCH"
- "Go mksyscall.pl mkerrors.sh mksysnum.pl"
- "Go z* files syscall"