[インデックス 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"