[インデックス 18636] ファイルの概要
このコミットは、Go言語の syscall
パッケージにSolaris OS (GOOS=solaris) および AMD64アーキテクチャ (GOARCH=amd64) 向けのシステムコール関連の定数、エラー、シグナル、およびシステムコール関数を自動生成されたファイルとして追加するものです。これにより、GoプログラムがSolaris上で低レベルのシステム機能と対話できるようになります。
コミット
commit e5b5f9b39d743893732ed0dca2e697d6de64a775
Author: Aram Hăvărneanu <aram@mgk.ro>
Date: Tue Feb 25 17:12:19 2014 +0900
syscall: generate zfiles for GOOS=solaris
LGTM=minux.ma, mikioh.mikioh
R=golang-codereviews, minux.ma, gobot, jsing, mikioh.mikioh, dave
CC=golang-codereviews
https://golang.org/cl/36010043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e5b5f9b39d743893732ed0dca2e697d6de64a775
元コミット内容
syscall: generate zfiles for GOOS=solaris
このコミットメッセージは簡潔ですが、その内容はGo言語のクロスプラットフォーム対応において非常に重要です。具体的には、Solarisオペレーティングシステム向けのシステムコール関連のファイルを生成し、Goのsyscall
パッケージに組み込むことを意味しています。
変更の背景
Go言語は、その設計当初からクロスプラットフォーム対応を重視しており、様々なオペレーティングシステムやアーキテクチャで動作するように開発されています。syscall
パッケージは、GoプログラムがOSのカーネルと直接対話するための低レベルなインターフェースを提供します。これには、ファイル操作、ネットワーク通信、プロセス管理など、OSが提供する基本的な機能へのアクセスが含まれます。
しかし、各OSは独自のシステムコールインターフェースと定数を持っています。例えば、Linux、macOS、Windows、そしてSolarisでは、同じ機能を提供するシステムコールであっても、その名前、引数、返り値、そして関連する定数(エラーコード、フラグなど)が異なります。
このコミットが行われた2014年2月時点では、Go言語のSolarisサポートが強化されている段階でした。Solaris上でGoプログラムがネイティブに動作し、OSの機能を効率的に利用するためには、Solaris固有のシステムコール定義が必要不可欠でした。この「zfiles」と呼ばれる自動生成されたファイル群は、Goのビルドプロセスにおいて、特定のOS/アーキテクチャの組み合わせ(この場合はSolaris/amd64)に対応するシステムコールインターフェースを自動的に生成するために用いられます。これにより、手動でこれらの定義を記述する手間を省き、正確性と保守性を高めることができます。
前提知識の解説
1. Go言語のsyscall
パッケージ
syscall
パッケージは、Goプログラムがオペレーティングシステムの低レベルな機能にアクセスするためのインターフェースを提供します。これは、C言語の標準ライブラリ(libc)が提供するシステムコールに相当する機能を提供しますが、Goの型システムとエラーハンドリングに統合されています。
2. システムコール (System Call)
システムコールは、ユーザー空間で動作するプログラムが、カーネル空間で動作するオペレーティングシステムのサービスを要求するためのメカニズムです。ファイルI/O、メモリ管理、プロセス制御、ネットワーク通信など、OSのほとんどの機能はシステムコールを通じて提供されます。
3. クロスプラットフォーム開発とOS/アーキテクチャ固有のコード
Go言語は、GOOS
(ターゲットOS)とGOARCH
(ターゲットアーキテクチャ)という環境変数を用いて、異なるプラットフォーム向けのビルドをサポートしています。特定のOSやアーキテクチャに依存するコードは、ファイル名に_GOOS.go
や_GOOS_GOARCH.go
といったサフィックスを付けることで、Goのビルドシステムによって自動的に選択的にコンパイルされます。
4. zfiles
(自動生成ファイル)
Goのsyscall
パッケージでは、多くのOS固有の定数やシステムコール関数が手動で記述されるのではなく、スクリプトによって自動生成されます。これらのファイルは慣習的にz
で始まる名前(例: zerrors_solaris_amd64.go
)が付けられることが多く、MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
といったコメントが含まれています。これは、開発者が直接編集するのではなく、生成スクリプトを修正すべきであることを示しています。
5. cgo
とgodefs
cgo
はGoプログラムからC言語のコードを呼び出すためのツールです。godefs
はcgo
の一部として提供されるツールで、C言語のヘッダーファイルからGoの構造体定義や定数を自動生成するために使用されます。このコミットのzerrors_solaris_amd64.go
ファイルの冒頭にある// Created by cgo -godefs - DO NOT EDIT
というコメントは、このファイルがgodefs
によって生成されたことを示しています。
6. Solaris OS
Solarisは、Sun Microsystems(現在はOracleが所有)によって開発されたUNIXベースのオペレーティングシステムです。特にエンタープライズ環境やサーバー分野で利用されてきました。Go言語がSolarisをサポートすることは、Goがより幅広いシステムで利用可能になることを意味します。
技術的詳細
このコミットは、Solaris/AMD64環境におけるGoのsyscall
パッケージの基盤を確立するものです。具体的には、以下の4つの新しいファイルが追加されています。
-
src/pkg/syscall/zerrors_solaris_amd64.go
:- このファイルは、Solarisシステムにおける様々な定数(例:
AF_INET
,SOCK_STREAM
などのソケット関連定数、O_RDONLY
などのファイルオープンフラグ、SIGINT
などのシグナル定数)を定義しています。 - また、Solaris固有のエラーコード(例:
EACCES
,ENOENT
など)とその文字列表現も含まれています。これらの定数やエラーは、GoプログラムがSolarisのシステムコールを呼び出す際に必要となるものです。 - ファイルのヘッダーには
// mkerrors.sh -m64
と// Created by cgo -godefs - DO NOT EDIT
とあり、mkerrors.sh
スクリプトがcgo -godefs
を使ってこれらの定数をC言語のヘッダーファイルから自動生成したことを示しています。-m64
は64ビットアーキテクチャ向けであることを意味します。
- このファイルは、Solarisシステムにおける様々な定数(例:
-
src/pkg/syscall/zsyscall_solaris_amd64.go
:- このファイルは、Solaris/AMD64環境で利用可能なシステムコール関数をGoの関数として定義しています。
- 例えば、
Access
,Chdir
,Chmod
,Open
,Read
,Write
,Socket
,Accept
,Connect
など、基本的なファイル操作、プロセス管理、ネットワーク操作に関するシステムコールが含まれています。 - これらのGo関数は、内部的に
sysvicall6
やrawSysvicall6
といった低レベルな関数を呼び出しています。これらは、Goのランタイムが直接OSのシステムコールを呼び出すためのアセンブリコードやCgoのラッパーを介したメカニズムです。 modlibc
とmodlibsocket
というnewLazySO
で初期化される変数が定義されており、それぞれlibc.so
とlibsocket.so
という共有ライブラリからシステムコール関数を動的にロードすることを示しています。これは、Solarisにおけるシステムコールの提供方法に合わせた実装です。
-
src/pkg/syscall/zsysnum_solaris_amd64.go
:- このファイルは、Solaris/AMD64環境におけるシステムコール番号を定義しています。
- 各システムコールには一意の番号が割り当てられており、カーネルはこれらの番号に基づいてどのシステムコールが呼び出されたかを識別します。このファイルは、Goのシステムコールラッパーが正しいシステムコールを呼び出すために必要です。
-
src/pkg/syscall/ztypes_solaris_amd64.go
:- このファイルは、Solarisシステムコールで使用されるC言語の構造体や型のGo言語での表現を定義しています。
- 例えば、
Stat_t
(ファイルの状態情報)、Timeval
(時間値)、Rlimit
(リソース制限)、Msghdr
(メッセージヘッダー)などの構造体が含まれています。 - これらの型定義は、Goプログラムがシステムコールに引数を渡したり、システムコールから返される値を受け取ったりする際に、メモリレイアウトがOSの期待するものと一致するようにするために重要です。
これらのファイルは、GoのビルドシステムがSolaris上でGoプログラムをコンパイルする際に、適切なシステムコール定義と定数を自動的に含めることを可能にします。これにより、GoプログラムはSolarisのネイティブAPIを効率的かつ安全に利用できるようになります。
コアとなるコードの変更箇所
このコミットは、以下の4つの新しいファイルをsrc/pkg/syscall/
ディレクトリに追加しています。
src/pkg/syscall/zerrors_solaris_amd64.go
src/pkg/syscall/zsyscall_solaris_amd64.go
src/pkg/syscall/zsysnum_solaris_amd64.go
src/pkg/syscall/ztypes_solaris_amd64.go
これらのファイルはすべて新規追加であり、既存のコードの変更はありません。各ファイルは数千行に及ぶ大量の定数定義、システムコール関数ラッパー、および型定義を含んでいます。
コアとなるコードの解説
zerrors_solaris_amd64.go
このファイルは、Solaris/AMD64環境におけるOS固有の定数とエラー定義の集まりです。
// mkerrors.sh -m64
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs -- -m64 _const.go
package syscall
const (
AF_802 = 0x12
AF_APPLETALK = 0x10
// ... 多数の定数定義 ...
WUNTRACED = 0x4
)
// Errors
const (
E2BIG = Errno(0x7)
EACCES = Errno(0xd)
// ... 多数のエラーコード定義 ...
EXFULL = Errno(0x34)
)
// Signals
const (
SIGABRT = Signal(0x6)
SIGALRM = Signal(0xe)
// ... 多数のシグナル定義 ...
SIGXRES = Signal(0x26)
)
// Error table
var errors = [...]string{
1: "not owner",
2: "no such file or directory",
// ... エラーコードと文字列のマッピング ...
}
// Signal table
var signals = [...]string{
1: "hangup",
2: "interrupt",
// ... シグナルと文字列のマッピング ...
}
- 定数:
AF_INET
(IPv4ソケットファミリー)、SOCK_STREAM
(TCPソケットタイプ)、O_RDONLY
(読み取り専用オープンフラグ)、MAP_SHARED
(共有メモリマップフラグ) など、システムプログラミングで頻繁に利用される数値定数が定義されています。これらはC言語のヘッダーファイルで定義されているマクロや列挙型に対応します。 - エラー:
EACCES
(アクセス拒否)、ENOENT
(ファイルまたはディレクトリが存在しない)、EINVAL
(無効な引数) など、システムコールが失敗した際に返されるエラーコードが定義されています。Goのsyscall.Errno
型にキャストされており、Goのエラーインターフェースと互換性があります。 - シグナル:
SIGINT
(割り込みシグナル)、SIGKILL
(強制終了シグナル)、SIGSEGV
(セグメンテーション違反) など、プロセス間通信やイベント通知に使用されるシグナルが定義されています。Goのsyscall.Signal
型にキャストされています。 - エラー/シグナルテーブル: 数値のエラーコードやシグナル番号に対応する人間が読める文字列が定義されており、デバッグやエラーメッセージの生成に役立ちます。
zsyscall_solaris_amd64.go
このファイルは、Solaris/AMD64のシステムコールをGoから呼び出すためのラッパー関数を定義しています。
// mksyscall_solaris.pl syscall_solaris.go syscall_solaris_amd64.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package syscall
import "unsafe"
var (
modlibc = newLazySO("libc.so")
modlibsocket = newLazySO("libsocket.so")
procgetgroups = modlibc.NewProc("getgroups")
procsetgroups = modlibc.NewProc("setgroups")
procfcntl = modlibc.NewProc("fcntl")
// ... 多数のシステムコールプロシージャ定義 ...
procrecvmsg = modlibsocket.NewProc("recvmsg")
)
func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
r0, _, e1 := rawSysvicall6(procgetgroups.Addr(), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0)
n = int(r0)
if e1 != 0 {
err = e1
}
return
}
func Access(path string, mode uint32) (err error) {
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := sysvicall6(procAccess.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0, 0, 0, 0)
if e1 != 0 {
err = e1
}
return
}
// ... 多数のシステムコールラッパー関数 ...
- 共有ライブラリのロード:
modlibc
とmodlibsocket
は、それぞれSolarisの標準Cライブラリ(libc.so
)とソケットライブラリ(libsocket.so
)を動的にロードするためのnewLazySO
インスタンスです。これにより、Goプログラムは実行時にこれらのライブラリからシステムコール関数を解決します。 - プロシージャ定義:
procgetgroups
,procsetgroups
,procfcntl
などの変数は、ロードされた共有ライブラリ内の特定のシステムコール関数のエントリポイント(アドレス)を保持します。NewProc
メソッドは、指定された関数名に対応するプロシージャを検索します。 - システムコールラッパー関数:
getgroups
,Access
,Chdir
などのGo関数は、対応するOSのシステムコールを呼び出すための薄いラッパーです。- これらの関数は、Goの引数を
uintptr
に変換し、rawSysvicall6
またはsysvicall6
を呼び出します。 rawSysvicall6
とsysvicall6
は、Goのランタイムが提供する低レベルな関数で、レジスタを介して引数を渡し、OSのシステムコールを実行します。rawSysvicall6
はエラーを直接返しますが、sysvicall6
はGoのエラー型に変換します。- システムコールが成功した場合は戻り値をGoの型に変換し、失敗した場合はOSのエラーコードをGoの
error
インターフェースにラップして返します。 - 文字列引数(例:
path
)は、C言語の文字列(ヌル終端バイト配列)に変換するためにBytePtrFromString
が使用されます。
- これらの関数は、Goの引数を
zsysnum_solaris_amd64.go
このファイルは、Solaris/AMD64のシステムコール番号を定義しています。
// mksyscall_solaris.pl syscall_solaris.go syscall_solaris_amd64.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package syscall
const (
SYS_ACCEPT4 = 0x150
SYS_ACCESS = 0x21
SYS_ACL = 0x12c
// ... 多数のシステムコール番号定義 ...
SYS_WRITEV = 0x7a
)
SYS_ACCEPT4
,SYS_ACCESS
,SYS_WRITEV
などの定数は、それぞれのシステムコールに対応する数値の識別子です。Goのランタイムがシステムコールをディスパッチする際に、これらの番号を使用して正しいカーネル関数を呼び出します。
ztypes_solaris_amd64.go
このファイルは、Solaris/AMD64のシステムコールで使用されるC言語の構造体や型のGo言語での表現を定義しています。
// mkerrors.sh -m64
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs -- -m64 _const.go
package syscall
type _Gid_t uint32
type _Socklen uint32
type _C_short int16
type _C_int int32
type _C_long int64
type _C_long_long int64
type Timespec struct {
Sec int64
Nsec int64
}
type Timeval struct {
Sec int64
Usec int64
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int64
Ixrss int64
Idrss int64
Isrss int64
Minflt int64
Majflt int64
Nswap int64
Inblock int64
Oublock int64
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64
Nivcsw int64
}
// ... 多数の構造体定義 ...
- 基本型エイリアス:
_Gid_t
,_Socklen
,_C_short
などは、C言語の基本型(gid_t
,socklen_t
,short
など)に対応するGoの型エイリアスです。これにより、GoのコードがCのAPIとやり取りする際に、正しいサイズと表現が保証されます。 - 構造体定義:
Timespec
,Timeval
,Rusage
,Stat_t
などの構造体は、C言語の対応する構造体と同じメモリレイアウトを持つように定義されています。これは、システムコールがこれらの構造体を引数として受け取ったり、結果として返したりする場合に、GoとCの間でデータが正しく交換されるために不可欠です。例えば、Stat_t
はファイルのメタデータ(サイズ、パーミッション、タイムスタンプなど)を保持し、Rusage
はプロセスや子プロセスのリソース使用状況(CPU時間、メモリ使用量など)を保持します。
これらの自動生成されたファイルは、Go言語がSolarisプラットフォームで動作するための低レベルなインターフェースを提供し、GoプログラムがOSの機能を活用できるようにする上で極めて重要な役割を果たしています。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall - Go言語のクロスコンパイルに関するドキュメント: https://go.dev/doc/install/source#environment
- Go言語の
cgo
に関するドキュメント: https://go.dev/blog/cgo
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- Solarisシステムプログラミングガイド (Oracle): https://docs.oracle.com/cd/E19253-01/817-0503/index.html (一般的なSolarisシステムコールに関する情報)
- UNIX系OSにおけるシステムコールとライブラリ関数の違いに関する一般的な情報源
- Go言語のビルドシステムとクロスコンパイルに関する一般的な情報源
mkerrors.sh
やmksyscall_solaris.pl
のようなスクリプトの役割に関するGoコミュニティ内の議論やドキュメント (具体的なURLは特定しにくいが、Goのソースコードリポジトリ内で関連するスクリプトやMakefileを参照)