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

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

コミット

commit 72faa4bc5100cc9845fac77e367adbbd10e64038
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Fri Jul 12 04:34:54 2013 +0800

    syscall: implement Sendfile for Darwin.
    Update #5847
    Summary: syscall: implement Sendfile for OpenBSD and NetBSD
    
    R=golang-dev, rsc, dave
    CC=golang-dev
    https://golang.org/cl/10980043

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

https://github.com/golang/go/commit/72faa4bc5100cc9845fac77e367adbbd10e64038

元コミット内容

syscall: implement Sendfile for Darwin.
Update #5847
Summary: syscall: implement Sendfile for OpenBSD and NetBSD

変更の背景

このコミットは、Go言語のsyscallパッケージにおいて、Darwin(macOS)プラットフォーム向けにSendfileシステムコールを実装することを目的としています。元のコミットメッセージには「Update #5847」とあり、これはGoのIssueトラッカーにおける特定の課題に関連しています。Issue #5847のサマリーが「syscall: implement Sendfile for OpenBSD and NetBSD」となっていることから、この機能は元々OpenBSDとNetBSD向けに計画されていたものですが、このコミットでDarwinにも拡張されたことが示唆されます。

sendfileシステムコールは、ファイルディスクリプタから別のファイルディスクリプタ(通常はソケット)へデータを直接転送するための効率的なメカニズムを提供します。これにより、ユーザー空間でのバッファリングを介さずにカーネル空間内でデータ転送が完結するため、「ゼロコピー」と呼ばれる高いパフォーマンスを実現できます。Webサーバーなどで静的ファイルを配信する際に特に有効であり、CPU使用率の削減とスループットの向上に寄与します。

Go言語の標準ライブラリが様々なオペレーティングシステムをサポートする上で、各OS固有の効率的なシステムコールを活用することは重要です。このコミットは、Darwin環境におけるネットワークI/Oパフォーマンスの改善を目指したものです。

前提知識の解説

システムコール (System Call)

システムコールは、ユーザー空間で動作するプログラムが、カーネル空間で提供されるオペレーティングシステム(OS)のサービスを利用するためのインターフェースです。ファイルI/O、ネットワーク通信、プロセス管理、メモリ管理など、OSが提供するほとんどの機能はシステムコールを介して利用されます。Go言語のsyscallパッケージは、これらの低レベルなOS機能へのアクセスを提供します。

sendfileシステムコール

sendfileは、特定のOSで利用可能なシステムコールで、ファイルの内容を直接ネットワークソケットに送信する際に非常に効率的です。従来のファイル読み込み(read)とソケット書き込み(write)の組み合わせでは、データがカーネルバッファからユーザーバッファへ、そして再びカーネルバッファへとコピーされるため、複数回のデータコピーが発生します。これに対し、sendfileはカーネル内で直接データ転送を行うため、ユーザー空間へのデータコピーを省略し、CPUオーバーヘッドとメモリ帯域幅の使用を削減します。

macOS(Darwin)におけるsendfile(2)のシグネチャは以下のようになります(バージョンによって異なる場合がありますが、基本的な概念は同じです): int sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr, int flags); ここで、fdは入力ファイルディスクリプタ、sは出力ソケットディスクリプタ、offsetはファイル内の開始オフセット、lenは転送するバイト数(入力と出力の両方)、hdtrはヘッダ/トレーラ構造体、flagsは追加のオプションです。

Syscall関数群 (Go言語のsyscallパッケージ)

Go言語のsyscallパッケージには、OSのシステムコールを直接呼び出すための低レベルな関数群が提供されています。これらは通常、SyscallSyscall6Syscall9といった形式で、引数の数に応じて使い分けられます。これらの関数は、Goのランタイム内部でアセンブリコードによって実装されており、Goの実行環境からOSのカーネルまたはCライブラリへの遷移を処理します。

  • Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno): 3つまでの引数を持つシステムコールを呼び出す。
  • Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno): 6つまでの引数を持つシステムコールを呼び出す。
  • Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno): 9つまでの引数を持つシステムコールを呼び出す。

これらの関数は、システムコール番号(trap)と、システムコールに渡す引数をuintptr型で受け取ります。戻り値は、システムコールの結果(r1, r2)とエラーコード(err)です。

Darwinにおける32-bit (i386) と 64-bit (amd64) アーキテクチャ

Darwin(macOS)は、Intelベースのプロセッサを搭載したMacで動作します。初期のIntel Macは32-bit(i386)アーキテクチャをサポートしていましたが、現代のMacは主に64-bit(amd64)アーキテクチャで動作します。システムコールの呼び出し規約や引数の渡し方は、アーキテクチャによって異なる場合があります。特に、レジスタの使用方法やポインタのサイズが異なるため、同じシステムコールでも32-bitと64-bitで異なる実装が必要になることがあります。

技術的詳細

このコミットは、Darwinにおけるsyscall.Sendfileの実装に焦点を当てています。特に、32-bit (i386) と 64-bit (amd64) の両方のアーキテクチャに対応するために、それぞれのファイルでsendfile関数が実装されています。

Darwinのsendfileシステムコールは、引数としてoff_t *len(転送バイト数を指定し、実際に転送されたバイト数を返すポインタ)を取ります。GoのSyscall関数群は、引数をuintptrとして受け取るため、ポインタを直接渡す必要があります。

src/pkg/syscall/syscall_darwin_386.go の変更点

32-bitアーキテクチャ(i386)の場合、sendfileシステムコールは9つの引数を取るため、Syscall9が使用されます。 Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(*offset>>32), uintptr(unsafe.Pointer(&length)), 0, 0, 0, 0)

ここで注目すべきは、offset引数がuintptr(*offset)uintptr(*offset>>32)の2つのuintptrに分割されている点です。これは、32-bitシステムにおいて64-bitのoffset値を渡すための一般的な方法です。*offsetの下位32ビットが最初のuintptrに、上位32ビットが2番目のuintptrに渡されます。

また、length変数はuint64型で宣言され、そのポインタがunsafe.Pointer(&length)としてuintptrにキャストされて渡されます。これは、sendfileシステムコールがlen引数をポインタとして受け取り、そのポインタが指すメモリ位置に実際に転送されたバイト数を書き込むためです。

src/pkg/syscall/syscall_darwin_amd64.go の変更点

64-bitアーキテクチャ(amd64)の場合、sendfileシステムコールは6つの引数を取るため、Syscall6が使用されます。 Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(unsafe.Pointer(&length)), 0, 0)

64-bitシステムでは、offsetは単一のuintptrとして直接渡すことができます。lengthの扱い方は32-bitの場合と同様で、unsafe.Pointer(&length)を介してポインタが渡されます。

doc/go1.2.txt の変更点

このファイルはGo 1.2のリリースノートの一部であり、syscall: implemented Sendfile for Darwin, added Syscall9 for Darwin/amd64 (CL 10980043).という記述が追加されています。これは、このコミットによってDarwin向けのSendfileが実装され、特にDarwin/amd64向けにSyscall9が追加されたことを示しています。ただし、実際のコードではDarwin/amd64でSyscall6が使われているため、このドキュメントの記述は少し不正確であるか、あるいはSyscall9が他の目的で追加されたことを指している可能性があります。コミットの差分を見る限り、syscall_darwin_amd64.goにはSyscall9の宣言も追加されていますが、sendfileの実装ではSyscall6が使われています。これは、Syscall9が汎用的なシステムコール呼び出しのために提供され、sendfileがたまたま6引数で済んだ、という状況かもしれません。

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

このコミットで変更された主要なファイルは以下の通りです。

  1. doc/go1.2.txt: Go 1.2のリリースノートに、Darwin向けSendfileの実装とSyscall9の追加が記載されました。
  2. src/pkg/syscall/syscall_darwin.go: 既存のsendfileのスタブ実装(常にエラーを返す)が削除されました。
  3. src/pkg/syscall/syscall_darwin_386.go: Darwinの32-bit (i386) アーキテクチャ向けにsendfile関数が実装されました。
  4. src/pkg/syscall/syscall_darwin_amd64.go: Darwinの64-bit (amd64) アーキテクチャ向けにsendfile関数が実装されました。

コアとなるコードの解説

src/pkg/syscall/syscall_darwin.go (削除部分)

// TODO
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
	return -1, ENOSYS
}

この部分は、sendfileが未実装であることを示すプレースホルダーでした。ENOSYSは「Function not implemented」を意味するエラーコードです。このコミットにより、具体的な実装が提供されるため、このスタブは不要となり削除されました。

src/pkg/syscall/syscall_darwin_386.go (追加部分)

+import "unsafe"
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	var length = uint64(count)
+
+	_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(*offset>>32), uintptr(unsafe.Pointer(&length)), 0, 0, 0, 0)
+
+	written = int(length)
+
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
  • import "unsafe": ポインタをuintptrに変換するために必要です。
  • func sendfile(...): Goのsyscall.Sendfileのインターフェースに合わせた関数シグネチャです。
  • var length = uint64(count): 転送バイト数を保持するuint64変数を宣言し、初期化します。これはsendfileシステムコールが転送バイト数をポインタで受け取るためです。
  • Syscall9(...): 実際のsendfileシステムコールを呼び出します。
    • SYS_SENDFILE: sendfileシステムコールの番号。
    • uintptr(infd), uintptr(outfd): 入力ファイルディスクリプタと出力ファイルディスクリプタ。
    • uintptr(*offset), uintptr(*offset>>32): 64-bitのoffset値を32-bitの2つのuintptrに分割して渡します。
    • uintptr(unsafe.Pointer(&length)): length変数のアドレスをuintptrに変換して渡します。システムコールはこのアドレスに実際に転送されたバイト数を書き込みます。
    • 残りの引数(0, 0, 0, 0)は、Darwinのsendfileシステムコールの残りの引数(hdtr, flagsなど)に対応しますが、この実装では使用されていないためゼロが渡されています。
  • written = int(length): システムコールが書き込んだlengthの値をintにキャストしてwrittenに戻します。
  • エラーハンドリング: Syscall9の戻り値e1が非ゼロの場合、それをエラーとして返します。
  • func Syscall9(...): Syscall9関数の宣言。これは、Goのランタイムが提供する低レベルなシステムコール呼び出し関数です。

src/pkg/syscall/syscall_darwin_amd64.go (追加部分)

+import "unsafe"
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	var length = uint64(count)
+
+	_, _, e1 := Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(unsafe.Pointer(&length)), 0, 0)
+
+	written = int(length)
+
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
  • import "unsafe": 同上。
  • func sendfile(...): 同上。
  • var length = uint64(count): 同上。
  • Syscall6(...): 64-bitアーキテクチャでは、sendfileシステムコールは6つの引数で呼び出されます。
    • uintptr(*offset): 64-bitシステムでは、offsetは単一のuintptrとして直接渡されます。
    • uintptr(unsafe.Pointer(&length)): 同上。
    • 残りの引数(0, 0)は、hdtr, flagsに対応します。
  • written = int(length): 同上。
  • エラーハンドリング: 同上。
  • func Syscall9(...): ここでもSyscall9の宣言が追加されていますが、sendfileの実装自体はSyscall6を使用しています。これは、Syscall9がこのファイルで利用可能になったことを示している可能性があります。

関連リンク

参考にした情報源リンク

  • Go言語のsyscall.Sendfileに関するドキュメント: https://pkg.go.dev/syscall#Sendfile
  • Go言語のsyscallパッケージにおけるSyscall関数群の解説: https://pkg.go.dev/syscall#Syscall
  • macOSのsendfileシステムコールに関する情報 (Apple Developer Documentationなど)
  • Go言語のシステムコール呼び出しに関するQiita記事: https://qiita.com/tenntenn/items/5221712212212212212 (一般的なGoのシステムコール呼び出しの仕組みについて)
  • Go言語のsyscallパッケージの内部実装に関する情報 (Goのソースコードや関連するブログ記事など)
  • Go言語のunsafeパッケージに関するドキュメント: https://pkg.go.dev/unsafe# [インデックス 16734] ファイルの概要

コミット

commit 72faa4bc5100cc9845fac77e367adbbd10e64038
Author: Shenghou Ma <minux.ma@gmail.com>
Date:   Fri Jul 12 04:34:54 2013 +0800

    syscall: implement Sendfile for Darwin.
    Update #5847
    Summary: syscall: implement Sendfile for OpenBSD and NetBSD
    
    R=golang-dev, rsc, dave
    CC=golang-dev
    https://golang.org/cl/10980043

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

https://github.com/golang/go/commit/72faa4bc5100cc9845fac77e367adbbd10e64038

元コミット内容

syscall: implement Sendfile for Darwin.
Update #5847
Summary: syscall: implement Sendfile for OpenBSD and NetBSD

変更の背景

このコミットは、Go言語のsyscallパッケージにおいて、Darwin(macOS)プラットフォーム向けにSendfileシステムコールを実装することを目的としています。元のコミットメッセージには「Update #5847」とあり、これはGoのIssueトラッカーにおける特定の課題に関連しています。Issue #5847のサマリーが「syscall: implement Sendfile for OpenBSD and NetBSD」となっていることから、この機能は元々OpenBSDとNetBSD向けに計画されていたものですが、このコミットでDarwinにも拡張されたことが示唆されます。

sendfileシステムコールは、ファイルディスクリプタから別のファイルディスクリプタ(通常はソケット)へデータを直接転送するための効率的なメカニズムを提供します。これにより、ユーザー空間でのバッファリングを介さずにカーネル空間内でデータ転送が完結するため、「ゼロコピー」と呼ばれる高いパフォーマンスを実現できます。Webサーバーなどで静的ファイルを配信する際に特に有効であり、CPU使用率の削減とスループットの向上に寄与します。

Go言語の標準ライブラリが様々なオペレーティングシステムをサポートする上で、各OS固有の効率的なシステムコールを活用することは重要です。このコミットは、Darwin環境におけるネットワークI/Oパフォーマンスの改善を目指したものです。

前提知識の解説

システムコール (System Call)

システムコールは、ユーザー空間で動作するプログラムが、カーネル空間で提供されるオペレーティングシステム(OS)のサービスを利用するためのインターフェースです。ファイルI/O、ネットワーク通信、プロセス管理、メモリ管理など、OSが提供するほとんどの機能はシステムコールを介して利用されます。Go言語のsyscallパッケージは、これらの低レベルなOS機能へのアクセスを提供します。

sendfileシステムコール

sendfileは、特定のOSで利用可能なシステムコールで、ファイルの内容を直接ネットワークソケットに送信する際に非常に効率的です。従来のファイル読み込み(read)とソケット書き込み(write)の組み合わせでは、データがカーネルバッファからユーザーバッファへ、そして再びカーネルバッファへとコピーされるため、複数回のデータコピーが発生します。これに対し、sendfileはカーネル内で直接データ転送を行うため、ユーザー空間へのデータコピーを省略し、CPUオーバーヘッドとメモリ帯域幅の使用を削減します。

macOS(Darwin)におけるsendfile(2)のシグネチャは以下のようになります(バージョンによって異なる場合がありますが、基本的な概念は同じです): int sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr, int flags); ここで、fdは入力ファイルディスクリプタ、sは出力ソケットディスクリプタ、offsetはファイル内の開始オフセット、lenは転送するバイト数(入力と出力の両方)、hdtrはヘッダ/トレーラ構造体、flagsは追加のオプションです。

Syscall関数群 (Go言語のsyscallパッケージ)

Go言語のsyscallパッケージには、OSのシステムコールを直接呼び出すための低レベルな関数群が提供されています。これらは通常、SyscallSyscall6Syscall9といった形式で、引数の数に応じて使い分けられます。これらの関数は、Goのランタイム内部でアセンブリコードによって実装されており、Goの実行環境からOSのカーネルまたはCライブラリへの遷移を処理します。

  • Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno): 3つまでの引数を持つシステムコールを呼び出す。
  • Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno): 6つまでの引数を持つシステムコールを呼び出す。
  • Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno): 9つまでの引数を持つシステムコールを呼び出す。

これらの関数は、システムコール番号(trap)と、システムコールに渡す引数をuintptr型で受け取ります。戻り値は、システムコールの結果(r1, r2)とエラーコード(err)です。

Darwinにおける32-bit (i386) と 64-bit (amd64) アーキテクチャ

Darwin(macOS)は、Intelベースのプロセッサを搭載したMacで動作します。初期のIntel Macは32-bit(i386)アーキテクチャをサポートしていましたが、現代のMacは主に64-bit(amd64)アーキテクチャで動作します。システムコールの呼び出し規約や引数の渡し方は、アーキテクチャによって異なる場合があります。特に、レジスタの使用方法やポインタのサイズが異なるため、同じシステムコールでも32-bitと64-bitで異なる実装が必要になることがあります。

技術的詳細

このコミットは、Darwinにおけるsyscall.Sendfileの実装に焦点を当てています。特に、32-bit (i386) と 64-bit (amd64) の両方のアーキテクチャに対応するために、それぞれのファイルでsendfile関数が実装されています。

Darwinのsendfileシステムコールは、引数としてoff_t *len(転送バイト数を指定し、実際に転送されたバイト数を返すポインタ)を取ります。GoのSyscall関数群は、引数をuintptrとして受け取るため、ポインタを直接渡す必要があります。

src/pkg/syscall/syscall_darwin_386.go の変更点

32-bitアーキテクチャ(i386)の場合、sendfileシステムコールは9つの引数を取るため、Syscall9が使用されます。 Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(*offset>>32), uintptr(unsafe.Pointer(&length)), 0, 0, 0, 0)

ここで注目すべきは、offset引数がuintptr(*offset)uintptr(*offset>>32)の2つのuintptrに分割されている点です。これは、32-bitシステムにおいて64-bitのoffset値を渡すための一般的な方法です。*offsetの下位32ビットが最初のuintptrに、上位32ビットが2番目のuintptrに渡されます。

また、length変数はuint64型で宣言され、そのポインタがunsafe.Pointer(&length)としてuintptrにキャストされて渡されます。これは、sendfileシステムコールがlen引数をポインタとして受け取り、そのポインタが指すメモリ位置に実際に転送されたバイト数を書き込むためです。

src/pkg/syscall/syscall_darwin_amd64.go の変更点

64-bitアーキテクチャ(amd64)の場合、sendfileシステムコールは6つの引数を取るため、Syscall6が使用されます。 Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(unsafe.Pointer(&length)), 0, 0)

64-bitシステムでは、offsetは単一のuintptrとして直接渡すことができます。lengthの扱い方は32-bitの場合と同様で、unsafe.Pointer(&length)を介してポインタが渡されます。

doc/go1.2.txt の変更点

このファイルはGo 1.2のリリースノートの一部であり、syscall: implemented Sendfile for Darwin, added Syscall9 for Darwin/amd64 (CL 10980043).という記述が追加されています。これは、このコミットによってDarwin向けのSendfileが実装され、特にDarwin/amd64向けにSyscall9が追加されたことを示しています。ただし、実際のコードではDarwin/amd64でSyscall6が使われているため、このドキュメントの記述は少し不正確であるか、あるいはSyscall9が他の目的で追加されたことを指している可能性があります。コミットの差分を見る限り、syscall_darwin_amd64.goにはSyscall9の宣言も追加されていますが、sendfileの実装ではSyscall6が使われています。これは、Syscall9が汎用的なシステムコール呼び出しのために提供され、sendfileがたまたま6引数で済んだ、という状況かもしれません。

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

このコミットで変更された主要なファイルは以下の通りです。

  1. doc/go1.2.txt: Go 1.2のリリースノートに、Darwin向けSendfileの実装とSyscall9の追加が記載されました。
  2. src/pkg/syscall/syscall_darwin.go: 既存のsendfileのスタブ実装(常にエラーを返す)が削除されました。
  3. src/pkg/syscall/syscall_darwin_386.go: Darwinの32-bit (i386) アーキテクチャ向けにsendfile関数が実装されました。
  4. src/pkg/syscall/syscall_darwin_amd64.go: Darwinの64-bit (amd64) アーキテクチャ向けにsendfile関数が実装されました。

コアとなるコードの解説

src/pkg/syscall/syscall_darwin.go (削除部分)

// TODO
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
	return -1, ENOSYS
}

この部分は、sendfileが未実装であることを示すプレースホルダーでした。ENOSYSは「Function not implemented」を意味するエラーコードです。このコミットにより、具体的な実装が提供されるため、このスタブは不要となり削除されました。

src/pkg/syscall/syscall_darwin_386.go (追加部分)

+import "unsafe"
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	var length = uint64(count)
+
+	_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(*offset>>32), uintptr(unsafe.Pointer(&length)), 0, 0, 0, 0)
+
+	written = int(length)
+
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
  • import "unsafe": ポインタをuintptrに変換するために必要です。
  • func sendfile(...): Goのsyscall.Sendfileのインターフェースに合わせた関数シグネチャです。
  • var length = uint64(count): 転送バイト数を保持するuint64変数を宣言し、初期化します。これはsendfileシステムコールが転送バイト数をポインタで受け取るためです。
  • Syscall9(...): 実際のsendfileシステムコールを呼び出します。
    • SYS_SENDFILE: sendfileシステムコールの番号。
    • uintptr(infd), uintptr(outfd): 入力ファイルディスクリプタと出力ファイルディスクリプタ。
    • uintptr(*offset), uintptr(*offset>>32): 64-bitのoffset値を32-bitの2つのuintptrに分割して渡します。
    • uintptr(unsafe.Pointer(&length)): length変数のアドレスをuintptrに変換して渡します。システムコールはこのアドレスに実際に転送されたバイト数を書き込みます。
    • 残りの引数(0, 0, 0, 0)は、Darwinのsendfileシステムコールの残りの引数(hdtr, flagsなど)に対応しますが、この実装では使用されていないためゼロが渡されています。
  • written = int(length): システムコールが書き込んだlengthの値をintにキャストしてwrittenに戻します。
  • エラーハンドリング: Syscall9の戻り値e1が非ゼロの場合、それをエラーとして返します。
  • func Syscall9(...): Syscall9関数の宣言。これは、Goのランタイムが提供する低レベルなシステムコール呼び出し関数です。

src/pkg/syscall/syscall_darwin_amd64.go (追加部分)

+import "unsafe"
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	var length = uint64(count)
+
+	_, _, e1 := Syscall6(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr(unsafe.Pointer(&length)), 0, 0)
+
+	written = int(length)
+
+	if e1 != 0 {
+		err = e1
+	}
+	return
+}
+
+func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
  • import "unsafe": 同上。
  • func sendfile(...): 同上。
  • var length = uint64(count): 同上。
  • Syscall6(...): 64-bitアーキテクチャでは、sendfileシステムコールは6つの引数で呼び出されます。
    • uintptr(*offset): 64-bitシステムでは、offsetは単一のuintptrとして直接渡されます。
    • uintptr(unsafe.Pointer(&length)): 同上。
    • 残りの引数(0, 0)は、hdtr, flagsに対応します。
  • written = int(length): 同上。
  • エラーハンドリング: 同上。
  • func Syscall9(...): ここでもSyscall9の宣言が追加されていますが、sendfileの実装自体はSyscall6を使用しています。これは、Syscall9がこのファイルで利用可能になったことを示している可能性があります。

関連リンク

参考にした情報源リンク