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

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

cgoはGoプログラムからC言語のコードを呼び出すためのツールです。godefscgoの一部として提供されるツールで、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つの新しいファイルが追加されています。

  1. 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ビットアーキテクチャ向けであることを意味します。
  2. src/pkg/syscall/zsyscall_solaris_amd64.go:

    • このファイルは、Solaris/AMD64環境で利用可能なシステムコール関数をGoの関数として定義しています。
    • 例えば、Access, Chdir, Chmod, Open, Read, Write, Socket, Accept, Connectなど、基本的なファイル操作、プロセス管理、ネットワーク操作に関するシステムコールが含まれています。
    • これらのGo関数は、内部的にsysvicall6rawSysvicall6といった低レベルな関数を呼び出しています。これらは、Goのランタイムが直接OSのシステムコールを呼び出すためのアセンブリコードやCgoのラッパーを介したメカニズムです。
    • modlibcmodlibsocketというnewLazySOで初期化される変数が定義されており、それぞれlibc.solibsocket.soという共有ライブラリからシステムコール関数を動的にロードすることを示しています。これは、Solarisにおけるシステムコールの提供方法に合わせた実装です。
  3. src/pkg/syscall/zsysnum_solaris_amd64.go:

    • このファイルは、Solaris/AMD64環境におけるシステムコール番号を定義しています。
    • 各システムコールには一意の番号が割り当てられており、カーネルはこれらの番号に基づいてどのシステムコールが呼び出されたかを識別します。このファイルは、Goのシステムコールラッパーが正しいシステムコールを呼び出すために必要です。
  4. 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
}

// ... 多数のシステムコールラッパー関数 ...
  • 共有ライブラリのロード: modlibcmodlibsocketは、それぞれSolarisの標準Cライブラリ(libc.so)とソケットライブラリ(libsocket.so)を動的にロードするためのnewLazySOインスタンスです。これにより、Goプログラムは実行時にこれらのライブラリからシステムコール関数を解決します。
  • プロシージャ定義: procgetgroups, procsetgroups, procfcntlなどの変数は、ロードされた共有ライブラリ内の特定のシステムコール関数のエントリポイント(アドレス)を保持します。NewProcメソッドは、指定された関数名に対応するプロシージャを検索します。
  • システムコールラッパー関数: getgroups, Access, ChdirなどのGo関数は、対応するOSのシステムコールを呼び出すための薄いラッパーです。
    • これらの関数は、Goの引数をuintptrに変換し、rawSysvicall6またはsysvicall6を呼び出します。
    • rawSysvicall6sysvicall6は、Goのランタイムが提供する低レベルな関数で、レジスタを介して引数を渡し、OSのシステムコールを実行します。rawSysvicall6はエラーを直接返しますが、sysvicall6はGoのエラー型に変換します。
    • システムコールが成功した場合は戻り値をGoの型に変換し、失敗した場合はOSのエラーコードをGoのerrorインターフェースにラップして返します。
    • 文字列引数(例: path)は、C言語の文字列(ヌル終端バイト配列)に変換するためにBytePtrFromStringが使用されます。

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言語のソースコード (GitHub): https://github.com/golang/go
  • Solarisシステムプログラミングガイド (Oracle): https://docs.oracle.com/cd/E19253-01/817-0503/index.html (一般的なSolarisシステムコールに関する情報)
  • UNIX系OSにおけるシステムコールとライブラリ関数の違いに関する一般的な情報源
  • Go言語のビルドシステムとクロスコンパイルに関する一般的な情報源
  • mkerrors.shmksyscall_solaris.plのようなスクリプトの役割に関するGoコミュニティ内の議論やドキュメント (具体的なURLは特定しにくいが、Goのソースコードリポジトリ内で関連するスクリプトやMakefileを参照)