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

[インデックス 13272] ファイルの概要

このコミットは、Go言語のsyscallパッケージにおけるNetBSD向けのパイプ作成処理を改善するものです。具体的には、pipe2システムコールからpipeシステムコールへの変更を行い、NetBSD 5との互換性を向上させています。

コミット

commit 677cdb800d85025b01173e44925189c822869168
Author: Benny Siegert <bsiegert@gmail.com>
Date:   Tue Jun 5 01:29:34 2012 +1000

    syscall: use pipe instead of pipe2 on NetBSD
    
    pipe2 is equivalent to pipe with flags set to 0.
    However, pipe2 was only added recently. Using pipe
    instead improves compatibility with NetBSD 5.
    
    R=jsing
    CC=golang-dev
    https://golang.org/cl/6268045

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/677cdb800d85025b01173e44925189c822869168

元コミット内容

syscall: use pipe instead of pipe2 on NetBSD

このコミットは、NetBSD上でパイプを作成する際にpipe2システムコールではなくpipeシステムコールを使用するように変更します。pipe2はフラグを0に設定した場合にpipeと同等ですが、pipe2は比較的新しく追加されたシステムコールであるため、pipeを使用することでNetBSD 5との互換性が向上します。

変更の背景

Go言語は、様々なオペレーティングシステム(OS)上で動作するように設計されています。そのため、各OSのシステムコールを適切に利用し、互換性を維持することが重要です。このコミットの背景には、NetBSDという特定のOSバージョン(NetBSD 5)におけるシステムコールの可用性の問題がありました。

pipe2システムコールは、従来のpipeシステムコールに加えて、パイプの作成時に追加のフラグ(例えば、O_NONBLOCKO_CLOEXECなど)を指定できる機能を提供します。これにより、パイプの動作をより細かく制御できるようになります。しかし、このpipe2は比較的新しいシステムコールであり、古いバージョンのOSでは利用できない場合があります。

NetBSD 5は、このpipe2システムコールがまだ導入されていなかった、あるいは安定していなかった時期のバージョンであると考えられます。Goのsyscallパッケージがpipe2を使用するように実装されていた場合、NetBSD 5上でGoプログラムがパイプを作成しようとすると、pipe2システムコールが見つからない、または正しく動作しないためにエラーが発生する可能性がありました。

この互換性の問題を解決するため、開発者はpipe2の使用を避け、より広く利用可能なpipeシステムコールに切り替えることを決定しました。コミットメッセージにある「pipe2 is equivalent to pipe with flags set to 0」という記述は、pipe2がフラグなしで呼び出された場合、その機能がpipeと全く同じであることを示しており、機能的な損失がないことを強調しています。

前提知識の解説

1. システムコール (System Call)

システムコールは、オペレーティングシステム(OS)のカーネルが提供するサービスを、ユーザー空間のプログラムが利用するためのインターフェースです。プログラムがファイルを開いたり、メモリを割り当てたり、ネットワーク通信を行ったりする際には、直接ハードウェアを操作するのではなく、OSのシステムコールを呼び出します。これにより、OSはシステムリソースを管理し、複数のプログラムが安全かつ効率的に動作できるようにします。

Go言語では、syscallパッケージがOSのシステムコールへの低レベルなアクセスを提供します。これにより、GoプログラムはOS固有の機能を利用したり、パフォーマンスが重要な処理を行ったりすることができます。

2. パイプ (Pipe)

パイプは、プロセス間通信(IPC: Inter-Process Communication)の一種で、一方のプロセスが書き込んだデータを、もう一方のプロセスが読み取ることができる単方向のデータストリームです。UNIX系OSでは、シェルコマンドの|(パイプ)演算子でおなじみです。

プログラム内でパイプを作成するには、通常、pipe()またはpipe2()といったシステムコールを使用します。これらのシステムコールは、2つのファイルディスクリプタ(通常は整数値)を返します。1つはパイプへの書き込み用、もう1つはパイプからの読み取り用です。

3. pipe() システムコール

pipe()システムコールは、最も基本的なパイプ作成関数です。通常、以下のようなシグネチャを持ちます(C言語の場合):

int pipe(int pipefd[2]);

この関数は、pipefdという2要素の整数配列を受け取ります。成功すると、pipefd[0]には読み取り用のファイルディスクリプタが、pipefd[1]には書き込み用のファイルディスクリプタが格納されます。エラーが発生した場合は-1を返します。

pipe()で作成されたパイプは、デフォルトでブロッキングI/Oモードで動作し、O_CLOEXECexec系システムコールで子プロセスにファイルディスクリプタが継承されないようにするフラグ)は設定されません。これらの挙動を変更するには、別途fcntl()システムコールなどを使用する必要があります。

4. pipe2() システムコール

pipe2()システムコールは、pipe()の拡張版です。以下のようなシグネチャを持ちます(C言語の場合):

int pipe2(int pipefd[2], int flags);

pipe2()pipefd配列に加えて、flags引数を受け取ります。このflags引数を使用することで、パイプの作成時にO_NONBLOCK(非ブロッキングI/O)やO_CLOEXECなどのフラグを原子的に設定できます。これにより、pipe()でパイプを作成した後にfcntl()を呼び出す必要がなくなり、競合状態のリスクを減らすことができます。

コミットメッセージにある「pipe2 is equivalent to pipe with flags set to 0」とは、pipe2(pipefd, 0)と呼び出すことが、pipe(pipefd)と呼び出すことと機能的に同じであることを意味します。

5. NetBSD

NetBSDは、BSD系UNIXオペレーティングシステムの一つで、高い移植性を特徴としています。様々なハードウェアアーキテクチャ上で動作するように設計されており、組み込みシステムからサーバーまで幅広い用途で利用されています。Go言語は、このような多様なOS環境をサポートしており、NetBSDもその対象の一つです。

このコミットは、NetBSDの特定のバージョン(NetBSD 5)におけるシステムコールの実装状況を考慮したものであり、Go言語が異なるOSバージョン間での互換性をどのように維持しているかを示す良い例です。

技術的詳細

このコミットの技術的な核心は、Go言語のsyscallパッケージがNetBSD上でパイプを作成する際に、どのシステムコールを使用するかという点にあります。

元の実装では、GoのsyscallパッケージはNetBSD向けにpipe2システムコールを利用していました。これは、pipe2pipeよりも新しい機能を提供し、パイプ作成時にフラグを原子的に設定できるという利点があるため、より現代的なアプローチと見なされていた可能性があります。

しかし、NetBSD 5のような古いバージョンのOSでは、pipe2システムコールが利用できないか、あるいはその挙動が期待通りではないという問題がありました。GoプログラムがNetBSD 5上で動作し、パイプを作成しようとすると、pipe2の呼び出しが失敗し、プログラムのクラッシュや予期せぬエラーにつながる可能性がありました。

この問題を解決するため、コミットではpipe2の使用を中止し、代わりにpipeシステムコールを使用するように変更されました。

  • pipe2からpipeへの切り替え: pipe2flags引数を取りますが、このコミットではpipe2を呼び出す際にflags0に設定していました。これは、機能的にはpipeシステムコールと全く同じ挙動を意味します。したがって、pipe2pipeに置き換えても、機能的な影響は全くありません。
  • 互換性の向上: pipeシステムコールはpipe2よりも古くから存在し、より多くのOSバージョンでサポートされています。特にNetBSD 5のような古い環境では、pipeが確実に利用できるため、この変更によってGoプログラムのNetBSD 5における互換性が大幅に向上します。
  • Goのsyscallパッケージの抽象化: Goのsyscallパッケージは、OS固有のシステムコールをGoの関数として抽象化しています。このコミットでは、GoのPipe関数が内部的にpipe2を呼び出す代わりにpipeを呼び出すように変更されました。これにより、GoのユーザーはPipe関数を呼び出すだけで、OSのバージョンに関わらず適切なパイプ作成メカニズムが利用されるようになります。

この変更は、Go言語が多様なOS環境で安定して動作するための、地道ながらも重要な互換性維持の取り組みの一環と言えます。

コアとなるコードの変更箇所

このコミットでは、以下の3つのファイルが変更されています。

  1. src/pkg/syscall/syscall_netbsd.go
  2. src/pkg/syscall/zsyscall_netbsd_386.go
  3. src/pkg/syscall/zsyscall_netbsd_amd64.go

src/pkg/syscall/syscall_netbsd.go

このファイルは、NetBSD固有のシステムコールに関するGo言語のラッパー関数を定義しています。

--- a/src/pkg/syscall/syscall_netbsd.go
+++ b/src/pkg/syscall/syscall_netbsd.go
@@ -118,15 +118,12 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,\
 	return origlen - len(buf), count, names
 }
 
-//sysnb pipe2(p *[2]_C_int, flags _C_int) (err error)
+//sysnb pipe() (fd1 int, fd2 int, err error)
 func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
-	var pp [2]_C_int
-	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	p[0], p[1], err = pipe()
 	return
 }
  • //sysnb pipe2(p *[2]_C_int, flags _C_int) (err error) が削除され、//sysnb pipe() (fd1 int, fd2 int, err error) が追加されました。これは、Goのビルドシステムがシステムコールを生成する際に使用するディレクティブです。pipe2システムコールへのバインディングを削除し、pipeシステムコールへの新しいバインディングを指示しています。
  • Pipe Go関数内で、pipe2を呼び出していた部分が削除され、代わりに新しく定義されたpipe()関数(Goの内部的なシステムコールラッパー)を呼び出すように変更されました。
    • var pp [2]_C_interr = pipe2(&pp, 0) の行が削除されました。
    • p[0] = int(pp[0])p[1] = int(pp[1]) の行が削除されました。
    • p[0], p[1], err = pipe() の行が追加されました。これにより、pipe()システムコールが返す2つのファイルディスクリプタとエラーを直接Goのpスライスに代入しています。

src/pkg/syscall/zsyscall_netbsd_386.go および src/pkg/syscall/zsyscall_netbsd_amd64.go

これらのファイルは、Goのビルドプロセスによって自動生成される、NetBSDの386およびAMD64アーキテクチャ向けのシステムコールラッパーです。

--- a/src/pkg/syscall/zsyscall_netbsd_386.go
+++ b/src/pkg/syscall/zsyscall_netbsd_386.go
@@ -253,8 +253,10 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe2(p *[2]_C_int, flags _C_int) (err error) {
-	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+func pipe() (fd1 int, fd2 int, err error) {
+	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+	fd1 = int(r0)
+	fd2 = int(r1)
 	if e1 != 0 {
 		err = e1
 	}

src/pkg/syscall/zsyscall_netbsd_amd64.goも同様の変更です。

  • func pipe2(...) の定義が削除され、func pipe(...) の定義が追加されました。
  • RawSyscallの呼び出しがSYS_PIPE2からSYS_PIPEに変更されました。
  • pipe2はポインタとフラグを引数に取っていましたが、pipeは引数を取らず、戻り値として2つのファイルディスクリプタとエラーを返します。これに合わせて、RawSyscallの戻り値の処理も変更されています。r0r1がそれぞれfd1fd2にマッピングされています。

これらの変更により、GoのsyscallパッケージはNetBSD上でパイプを作成する際に、古いpipeシステムコールを呼び出すように完全に切り替わりました。

コアとなるコードの解説

このコミットの核心は、Go言語のsyscallパッケージがNetBSD上でパイプを作成する際のシステムコール呼び出しの変更にあります。

syscall_netbsd.go の変更

このファイルは、GoのsyscallパッケージがNetBSD固有のシステムコールをどのようにラップしているかを示しています。

元のコードでは、GoのPipe関数は内部的にpipe2システムコールを呼び出していました。

//sysnb pipe2(p *[2]_C_int, flags _C_int) (err error)
func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe2(&pp, 0) // pipe2システムコールを呼び出し
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

ここで注目すべきは、pipe2(&pp, 0)という呼び出しです。pipe2は通常、パイプの動作を制御するためのフラグを第2引数に取りますが、ここでは0が渡されています。これは、pipe2をフラグなしで呼び出すことで、従来のpipeシステムコールと同じ挙動を期待していることを意味します。

変更後のコードでは、pipe2の代わりにpipeシステムコールを直接呼び出すように変更されています。

//sysnb pipe() (fd1 int, fd2 int, err error)
func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	p[0], p[1], err = pipe() // pipeシステムコールを呼び出し
	return
}

//sysnb pipe() (fd1 int, fd2 int, err error)というコメントは、Goのビルドツール(mksyscallなど)に対する指示で、引数なしでpipeシステムコールを呼び出し、2つの整数(ファイルディスクリプタ)とエラーを返すGo関数を生成するように伝えています。

この変更により、GoのPipe関数は、NetBSD 5のような古い環境でも確実に利用できるpipeシステムコールを使用するようになり、互換性が向上しました。機能的にはpipe2をフラグなしで呼び出すのと同等であるため、Goプログラムの動作に影響はありません。

zsyscall_netbsd_386.go および zsyscall_netbsd_amd64.go の変更

これらのファイルは、Goのsyscallパッケージが実際にOSのシステムコールを呼び出すための低レベルなラッパー関数を含んでいます。これらは通常、mksyscallなどのツールによって自動生成されます。

元のコードでは、pipe2というGo関数が定義されており、これがSYS_PIPE2というシステムコール番号を使ってRawSyscallを呼び出していました。

func pipe2(p *[2]_C_int, flags _C_int) (err error) {
	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
	// ... エラー処理 ...
}

変更後、pipe2関数は削除され、代わりにpipe関数が定義されました。このpipe関数はSYS_PIPEシステムコールを呼び出します。

func pipe() (fd1 int, fd2 int, err error) {
	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
	fd1 = int(r0)
	fd2 = int(r1)
	// ... エラー処理 ...
}

RawSyscallは、GoがOSのシステムコールを直接呼び出すための最も低レベルな関数です。SYS_PIPE2SYS_PIPEは、それぞれのシステムコールに対応するOS固有の番号です。

pipe2は引数としてポインタとフラグを受け取っていましたが、pipeは引数を取らず、戻り値として2つのファイルディスクリプタ(r0, r1)を返します。この変更は、GoのsyscallパッケージがOSのpipeシステムコールのシグネチャに合わせて、低レベルな呼び出しを調整したことを示しています。

これらの自動生成されるファイルの変更は、syscall_netbsd.goで指定された//sysnbディレクティブの変更の結果として発生します。つまり、Goのビルドツールが、新しいディレクティブに基づいて適切なシステムコールラッパーを再生成したということです。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (GitHub): https://github.com/golang/go
  • UNIX系OSにおけるpipe()pipe2()システムコールのmanページ (例: Linuxのmanページ):
  • NetBSDの公式ウェブサイト: https://www.netbsd.org/
  • Go言語のシステムコール生成に関する情報 (Goの内部ドキュメントやソースコードコメント): src/cmd/go/mksyscall.go など
  • プロセス間通信 (IPC) に関する一般的な情報源 (オペレーティングシステム概論など)
  • Go言語のクロスプラットフォーム開発に関する情報I have retrieved the commit information and have a good understanding of the changes. I will now generate the detailed technical explanation in Markdown format, following all the specified sections and requirements. I will not save it to a file, only print to standard output.
# [インデックス 13272] ファイルの概要

このコミットは、Go言語の`syscall`パッケージにおけるNetBSD向けのパイプ作成処理を改善するものです。具体的には、`pipe2`システムコールから`pipe`システムコールへの変更を行い、NetBSD 5との互換性を向上させています。

## コミット

commit 677cdb800d85025b01173e44925189c822869168 Author: Benny Siegert bsiegert@gmail.com Date: Tue Jun 5 01:29:34 2012 +1000

syscall: use pipe instead of pipe2 on NetBSD

pipe2 is equivalent to pipe with flags set to 0.
However, pipe2 was only added recently. Using pipe
instead improves compatibility with NetBSD 5.

R=jsing
CC=golang-dev
https://golang.org/cl/6268045

## GitHub上でのコミットページへのリンク

[https://github.com/golang/go/commit/677cdb800d85025b01173e44925189c822869168](https://github.com/golang/go/commit/677cdb800d85025b01173e44925189c822869168)

## 元コミット内容

`syscall: use pipe instead of pipe2 on NetBSD`

このコミットは、NetBSD上でパイプを作成する際に`pipe2`システムコールではなく`pipe`システムコールを使用するように変更します。`pipe2`はフラグを0に設定した場合に`pipe`と同等ですが、`pipe2`は比較的新しく追加されたシステムコールであるため、`pipe`を使用することでNetBSD 5との互換性が向上します。

## 変更の背景

Go言語は、様々なオペレーティングシステム(OS)上で動作するように設計されています。そのため、各OSのシステムコールを適切に利用し、互換性を維持することが重要です。このコミットの背景には、NetBSDという特定のOSバージョン(NetBSD 5)におけるシステムコールの可用性の問題がありました。

`pipe2`システムコールは、従来の`pipe`システムコールに加えて、パイプの作成時に追加のフラグ(例えば、`O_NONBLOCK`や`O_CLOEXEC`など)を指定できる機能を提供します。これにより、パイプの動作をより細かく制御できるようになります。しかし、この`pipe2`は比較的新しいシステムコールであり、古いバージョンのOSでは利用できない場合があります。

NetBSD 5は、この`pipe2`システムコールがまだ導入されていなかった、あるいは安定していなかった時期のバージョンであると考えられます。Goの`syscall`パッケージが`pipe2`を使用するように実装されていた場合、NetBSD 5上でGoプログラムがパイプを作成しようとすると、`pipe2`システムコールが見つからない、または正しく動作しないためにエラーが発生する可能性がありました。

この互換性の問題を解決するため、開発者は`pipe2`の使用を避け、より広く利用可能な`pipe`システムコールに切り替えることを決定しました。コミットメッセージにある「`pipe2` is equivalent to `pipe` with flags set to 0」という記述は、`pipe2`がフラグなしで呼び出された場合、その機能が`pipe`と全く同じであることを示しており、機能的な損失がないことを強調しています。

## 前提知識の解説

### 1. システムコール (System Call)

システムコールは、オペレーティングシステム(OS)のカーネルが提供するサービスを、ユーザー空間のプログラムが利用するためのインターフェースです。プログラムがファイルを開いたり、メモリを割り当てたり、ネットワーク通信を行ったりする際には、直接ハードウェアを操作するのではなく、OSのシステムコールを呼び出します。これにより、OSはシステムリソースを管理し、複数のプログラムが安全かつ効率的に動作できるようにします。

Go言語では、`syscall`パッケージがOSのシステムコールへの低レベルなアクセスを提供します。これにより、GoプログラムはOS固有の機能を利用したり、パフォーマンスが重要な処理を行ったりすることができます。

### 2. パイプ (Pipe)

パイプは、プロセス間通信(IPC: Inter-Process Communication)の一種で、一方のプロセスが書き込んだデータを、もう一方のプロセスが読み取ることができる単方向のデータストリームです。UNIX系OSでは、シェルコマンドの`|`(パイプ)演算子でおなじみです。

プログラム内でパイプを作成するには、通常、`pipe()`または`pipe2()`といったシステムコールを使用します。これらのシステムコールは、2つのファイルディスクリプタ(通常は整数値)を返します。1つはパイプへの書き込み用、もう1つはパイプからの読み取り用です。

### 3. `pipe()` システムコール

`pipe()`システムコールは、最も基本的なパイプ作成関数です。通常、以下のようなシグネチャを持ちます(C言語の場合):

```c
int pipe(int pipefd[2]);

この関数は、pipefdという2要素の整数配列を受け取ります。成功すると、pipefd[0]には読み取り用のファイルディスクリプタが、pipefd[1]には書き込み用のファイルディスクリプタが格納されます。エラーが発生した場合は-1を返します。

pipe()で作成されたパイプは、デフォルトでブロッキングI/Oモードで動作し、O_CLOEXECexec系システムコールで子プロセスにファイルディスクリプタが継承されないようにするフラグ)は設定されません。これらの挙動を変更するには、別途fcntl()システムコールなどを使用する必要があります。

4. pipe2() システムコール

pipe2()システムコールは、pipe()の拡張版です。以下のようなシグネチャを持ちます(C言語の場合):

int pipe2(int pipefd[2], int flags);

pipe2()pipefd配列に加えて、flags引数を受け取ります。このflags引数を使用することで、パイプの作成時にO_NONBLOCK(非ブロッキングI/O)やO_CLOEXECなどのフラグを原子的に設定できます。これにより、pipe()でパイプを作成した後にfcntl()を呼び出す必要がなくなり、競合状態のリスクを減らすことができます。

コミットメッセージにある「pipe2 is equivalent to pipe with flags set to 0」とは、pipe2(pipefd, 0)と呼び出すことが、pipe(pipefd)と呼び出すことと機能的に同じであることを意味します。

5. NetBSD

NetBSDは、BSD系UNIXオペレーティングシステムの一つで、高い移植性を特徴としています。様々なハードウェアアーキテクチャ上で動作するように設計されており、組み込みシステムからサーバーまで幅広い用途で利用されています。Go言語は、このような多様なOS環境をサポートしており、NetBSDもその対象の一つです。

このコミットは、NetBSDの特定のバージョン(NetBSD 5)におけるシステムコールの実装状況を考慮したものであり、Go言語が異なるOSバージョン間での互換性をどのように維持しているかを示す良い例です。

技術的詳細

このコミットの技術的な核心は、Go言語のsyscallパッケージがNetBSD上でパイプを作成する際に、どのシステムコールを使用するかという点にあります。

元の実装では、GoのsyscallパッケージはNetBSD向けにpipe2システムコールを利用していました。これは、pipe2pipeよりも新しい機能を提供し、パイプ作成時にフラグを原子的に設定できるという利点があるため、より現代的なアプローチと見なされていた可能性があります。

しかし、NetBSD 5のような古いバージョンのOSでは、pipe2システムコールが利用できないか、あるいはその挙動が期待通りではないという問題がありました。GoプログラムがNetBSD 5上で動作し、パイプを作成しようとすると、pipe2の呼び出しが失敗し、プログラムのクラッシュや予期せぬエラーにつながる可能性がありました。

この問題を解決するため、コミットではpipe2の使用を中止し、代わりにpipeシステムコールを使用するように変更されました。

  • pipe2からpipeへの切り替え: pipe2flags引数を取りますが、このコミットではpipe2を呼び出す際にflags0に設定していました。これは、機能的にはpipeシステムコールと全く同じ挙動を意味します。したがって、pipe2pipeに置き換えても、機能的な影響は全くありません。
  • 互換性の向上: pipeシステムコールはpipe2よりも古くから存在し、より多くのOSバージョンでサポートされています。特にNetBSD 5のような古い環境では、pipeが確実に利用できるため、この変更によってGoプログラムのNetBSD 5における互換性が大幅に向上します。
  • Goのsyscallパッケージの抽象化: Goのsyscallパッケージは、OS固有のシステムコールをGoの関数として抽象化しています。このコミットでは、GoのPipe関数が内部的にpipe2を呼び出す代わりにpipeを呼び出すように変更されました。これにより、GoのユーザーはPipe関数を呼び出すだけで、OSのバージョンに関わらず適切なパイプ作成メカニズムが利用されるようになります。

この変更は、Go言語が多様なOS環境で安定して動作するための、地道ながらも重要な互換性維持の取り組みの一環と言えます。

コアとなるコードの変更箇所

このコミットでは、以下の3つのファイルが変更されています。

  1. src/pkg/syscall/syscall_netbsd.go
  2. src/pkg/syscall/zsyscall_netbsd_386.go
  3. src/pkg/syscall/zsyscall_netbsd_amd64.go

src/pkg/syscall/syscall_netbsd.go

このファイルは、NetBSD固有のシステムコールに関するGo言語のラッパー関数を定義しています。

--- a/src/pkg/syscall/syscall_netbsd.go
+++ b/src/pkg/syscall/syscall_netbsd.go
@@ -118,15 +118,12 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,\
 	return origlen - len(buf), count, names
 }
 
-//sysnb pipe2(p *[2]_C_int, flags _C_int) (err error)
+//sysnb pipe() (fd1 int, fd2 int, err error)
 func Pipe(p []int) (err error) {
 	if len(p) != 2 {
 		return EINVAL
 	}
-	var pp [2]_C_int
-	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	p[0], p[1], err = pipe()
 	return
 }
  • //sysnb pipe2(p *[2]_C_int, flags _C_int) (err error) が削除され、//sysnb pipe() (fd1 int, fd2 int, err error) が追加されました。これは、Goのビルドシステムがシステムコールを生成する際に使用するディレクティブです。pipe2システムコールへのバインディングを削除し、pipeシステムコールへの新しいバインディングを指示しています。
  • Pipe Go関数内で、pipe2を呼び出していた部分が削除され、代わりに新しく定義されたpipe()関数(Goの内部的なシステムコールラッパー)を呼び出すように変更されました。
    • var pp [2]_C_interr = pipe2(&pp, 0) の行が削除されました。
    • p[0] = int(pp[0])p[1] = int(pp[1]) の行が削除されました。
    • p[0], p[1], err = pipe() の行が追加されました。これにより、pipe()システムコールが返す2つのファイルディスクリプタとエラーを直接Goのpスライスに代入しています。

src/pkg/syscall/zsyscall_netbsd_386.go および src/pkg/syscall/zsyscall_netbsd_amd64.go

これらのファイルは、Goのビルドプロセスによって自動生成される、NetBSDの386およびAMD64アーキテクチャ向けのシステムコールラッパーです。

--- a/src/pkg/syscall/zsyscall_netbsd_386.go
+++ b/src/pkg/syscall/zsyscall_netbsd_386.go
@@ -253,8 +253,10 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func pipe2(p *[2]_C_int, flags _C_int) (err error) {
-	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+func pipe() (fd1 int, fd2 int, err error) {
+	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+	fd1 = int(r0)
+	fd2 = int(r1)
 	if e1 != 0 {
 		err = e1
 	}

src/pkg/syscall/zsyscall_netbsd_amd64.goも同様の変更です。

  • func pipe2(...) の定義が削除され、func pipe(...) の定義が追加されました。
  • RawSyscallの呼び出しがSYS_PIPE2からSYS_PIPEに変更されました。
  • pipe2はポインタとフラグを引数に取っていましたが、pipeは引数を取らず、戻り値として2つのファイルディスクリプタとエラーを返します。これに合わせて、RawSyscallの戻り値の処理も変更されています。r0r1がそれぞれfd1fd2にマッピングされています。

これらの変更により、GoのsyscallパッケージはNetBSD上でパイプを作成する際に、古いpipeシステムコールを呼び出すように完全に切り替わりました。

コアとなるコードの解説

このコミットの核心は、Go言語のsyscallパッケージがNetBSD上でパイプを作成する際のシステムコール呼び出しの変更にあります。

syscall_netbsd.go の変更

このファイルは、GoのsyscallパッケージがNetBSD固有のシステムコールをどのようにラップしているかを示しています。

元のコードでは、GoのPipe関数は内部的にpipe2システムコールを呼び出していました。

//sysnb pipe2(p *[2]_C_int, flags _C_int) (err error)
func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	var pp [2]_C_int
	err = pipe2(&pp, 0) // pipe2システムコールを呼び出し
	p[0] = int(pp[0])
	p[1] = int(pp[1])
	return
}

ここで注目すべきは、pipe2(&pp, 0)という呼び出しです。pipe2は通常、パイプの動作を制御するためのフラグを第2引数に取りますが、ここでは0が渡されています。これは、pipe2をフラグなしで呼び出すことで、従来のpipeシステムコールと同じ挙動を期待していることを意味します。

変更後のコードでは、pipe2の代わりにpipeシステムコールを直接呼び出すように変更されています。

//sysnb pipe() (fd1 int, fd2 int, err error)
func Pipe(p []int) (err error) {
	if len(p) != 2 {
		return EINVAL
	}
	p[0], p[1], err = pipe() // pipeシステムコールを呼び出し
	return
}

//sysnb pipe() (fd1 int, fd2 int, err error)というコメントは、Goのビルドツール(mksyscallなど)に対する指示で、引数なしでpipeシステムコールを呼び出し、2つの整数(ファイルディスクリプタ)とエラーを返すGo関数を生成するように伝えています。

この変更により、GoのPipe関数は、NetBSD 5のような古い環境でも確実に利用できるpipeシステムコールを使用するようになり、互換性が向上しました。機能的にはpipe2をフラグなしで呼び出すのと同等であるため、Goプログラムの動作に影響はありません。

zsyscall_netbsd_386.go および zsyscall_netbsd_amd64.go の変更

これらのファイルは、Goのsyscallパッケージが実際にOSのシステムコールを呼び出すための低レベルなラッパー関数を含んでいます。これらは通常、mksyscallなどのツールによって自動生成されます。

元のコードでは、pipe2というGo関数が定義されており、これがSYS_PIPE2というシステムコール番号を使ってRawSyscallを呼び出していました。

func pipe2(p *[2]_C_int, flags _C_int) (err error) {
	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
	// ... エラー処理 ...
}

変更後、pipe2関数は削除され、代わりにpipe関数が定義されました。このpipe関数はSYS_PIPEシステムコールを呼び出します。

func pipe() (fd1 int, fd2 int, err error) {
	r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
	fd1 = int(r0)
	fd2 = int(r1)
	// ... エラー処理 ...
}

RawSyscallは、GoがOSのシステムコールを直接呼び出すための最も低レベルな関数です。SYS_PIPE2SYS_PIPEは、それぞれのシステムコールに対応するOS固有の番号です。

pipe2は引数としてポインタとフラグを受け取っていましたが、pipeは引数を取らず、戻り値として2つのファイルディスクリプタ(r0, r1)を返します。この変更は、GoのsyscallパッケージがOSのpipeシステムコールのシグネチャに合わせて、低レベルな呼び出しを調整したことを示しています。

これらの自動生成されるファイルの変更は、syscall_netbsd.goで指定された//sysnbディレクティブの変更の結果として発生します。つまり、Goのビルドツールが、新しいディレクティブに基づいて適切なシステムコールラッパーを再生成したということです。

関連リンク

参考にした情報源リンク