[インデックス 15128] ファイルの概要
このコミットは、Go言語の net
パッケージにおけるWindows環境でのソケット作成処理を改善するものです。具体的には、ソケット作成に syscall.Socket
を直接使用する代わりに、内部ヘルパー関数である sysSocket
を一貫して利用するように変更しています。これにより、Windows固有のソケット操作の複雑性を sysSocket
に集約し、コードの整合性と保守性を向上させています。
コミット
Author: Alex Brainman alex.brainman@gmail.com Date: Mon Feb 4 16:03:41 2013 +1100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/94064548c66b76ae111c68e67729c3bd11ad3faf
元コミット内容
net: use windows sysSocket everywhere
R=golang-dev, bradfitz, dave
CC=golang-dev
https://golang.org/cl/7273046
変更の背景
Go言語の net
パッケージは、ネットワーク通信の基盤を提供します。異なるオペレーティングシステム(OS)に対応するため、OS固有のシステムコールを抽象化して利用しています。Windows環境では、ソケットの作成や管理に特有の考慮事項があります。
このコミットの背景には、Windowsにおけるソケット作成処理の一貫性と堅牢性の向上が挙げられます。以前のコードでは、ソケット作成に直接 syscall.Socket
を使用している箇所と、sysSocket
というヘルパー関数を使用している箇所が混在していました。sysSocket
は、Windows環境でのソケット作成時に必要な追加の初期化や設定(例えば、I/O完了ポート (IOCP) との関連付けなど)をカプセル化している可能性があります。
syscall.ForkLock
の削除は、Windowsにおける fork
の概念の欠如と関連しています。Unix系OSでは fork
システムコールがプロセス複製に使用され、ソケットディスクリプタの継承に関する問題を防ぐために ForkLock
が必要となる場合があります。しかし、Windowsでは fork
が存在しないため、このロックは不要であり、むしろオーバーヘッドや潜在的な誤解を招く可能性があります。同様に、syscall.CloseOnExec
もUnix系OSの概念であり、Windowsでは異なるメカニズムでソケットの継承が制御されるため、直接的な使用は適切ではありません。
したがって、この変更は、Windows固有のソケット操作を sysSocket
に集約し、不要なUnix系OSの概念(ForkLock
, CloseOnExec
)を排除することで、Windows版 net
パッケージのコードをよりクリーンで、Windowsのネイティブな動作に即したものにすることを目的としています。
前提知識の解説
- ソケット (Socket): ネットワーク通信のエンドポイント。アプリケーションがネットワーク経由でデータを送受信するために使用する抽象化されたインターフェース。
syscall.Socket
: OSのネイティブなsocket()
システムコールをGo言語から呼び出すための関数。ソケットを作成し、そのファイルディスクリプタ(Unix系)またはハンドル(Windows)を返します。sysSocket
(Go言語の内部ヘルパー関数): このコミットで言及されているsysSocket
は、Go言語のnet
パッケージ内部で定義されているWindows固有のソケット作成ヘルパー関数であると推測されます。これは、単にsyscall.Socket
を呼び出すだけでなく、WindowsのWinsock APIにおける追加の初期化や設定(例:WSASocket
の使用、I/O完了ポート (IOCP) との関連付け、非同期I/Oの設定など)を内部的に処理している可能性があります。これにより、Windows環境でのソケットの適切な動作を保証します。syscall.ForkLock
: Unix系OSにおいて、fork
システムコールが実行される際に、ファイルディスクリプタやその他のリソースの状態を保護するためのロック機構。fork
は親プロセスのメモリ空間を複製するため、ソケットなどの共有リソースが競合状態に陥るのを防ぐ必要があります。Windowsにはfork
の概念がないため、このロックは無関係です。syscall.CloseOnExec
: Unix系OSにおいて、exec
システムコール(新しいプログラムを実行する)が呼び出された際に、特定のファイルディスクリプタを自動的にクローズするように設定するフラグ。これにより、子プロセスに不要なファイルディスクリプタが継承されるのを防ぎます。Windowsでは、ソケットの継承は異なる方法で制御されます(例:WSADuplicateSocket
やSetHandleInformation
のHANDLE_FLAG_INHERIT
フラグ)。- Winsock (Windows Sockets API): Windowsオペレーティングシステムにおけるネットワークプログラミングインターフェース。Unix系OSのBerkeley Sockets APIに似ていますが、Windows固有の機能(例: I/O完了ポート、オーバーラップI/O)をサポートしています。
- I/O完了ポート (IOCP): Windowsにおける高性能な非同期I/Oモデル。複数のソケットからのI/Oイベントを効率的に処理するために使用されます。Goの
net
パッケージは、Windows上で高性能なネットワークI/Oを実現するためにIOCPを利用しています。
技術的詳細
このコミットの主要な技術的変更は、Windows環境におけるソケット作成の抽象化レイヤーを統一することです。
-
sysSocket
の一貫した利用:- 以前は
syscall.Socket
が直接呼び出されていた箇所が、sysSocket
に置き換えられました。これは、sysSocket
がWindows固有のソケット初期化ロジック(例えば、Winsockのバージョン交渉、IOCPとの関連付け、非同期I/O設定など)をカプセル化しているためです。 - これにより、ソケット作成に関するすべてのWindows固有の複雑性が
sysSocket
に集約され、コードの重複が排除され、将来的な変更やバグ修正が容易になります。 netFD.accept
メソッド内で新しいソケットを作成する際、およびgetInterfaceList
関数内でUDPソケットを作成する際に、この変更が適用されています。
- 以前は
-
syscall.ForkLock
の削除:netFD.accept
メソッドからsyscall.ForkLock.RLock()
とsyscall.ForkLock.RUnlock()
の呼び出しが削除されました。- これは、Windows OSにはUnix系OSの
fork
システムコールが存在しないため、ForkLock
が不要であるという事実に基づいています。このロックはWindows環境では意味がなく、コードの複雑性を増すだけでした。
-
syscall.CloseOnExec
の削除:netFD.accept
メソッドからsyscall.CloseOnExec(s)
の呼び出しが削除されました。- これも
ForkLock
と同様に、CloseOnExec
がUnix系OSのexec
システムコールに関連する概念であり、Windowsのソケット継承メカニズムとは異なるためです。Windowsでは、ソケットの継承はハンドルプロパティによって制御され、CloseOnExec
のような直接的なシステムコールは存在しません。sysSocket
が内部的に適切なハンドルプロパティを設定しているか、またはGoランタイムがWindowsのソケット継承を適切に管理しているため、この明示的な呼び出しは不要となります。
これらの変更により、Goの net
パッケージのWindows実装は、よりWindowsのネイティブなAPIと動作モデルに適合し、不要なクロスプラットフォームの抽象化によるオーバーヘッドや混乱が排除されます。結果として、コードはよりクリーンで、理解しやすく、Windows環境でのパフォーマンスと安定性が向上する可能性があります。
コアとなるコードの変更箇所
このコミットでは、以下の2つのファイルが変更されています。
src/pkg/net/fd_windows.go
src/pkg/net/interface_windows.go
具体的な変更内容は以下の通りです。
src/pkg/net/fd_windows.go
の変更点:
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -619,15 +619,10 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
defer fd.decref()
// Get new socket.
- // See ../syscall/exec_unix.go for description of ForkLock.
- syscall.ForkLock.RLock()
- s, err := syscall.Socket(fd.family, fd.sotype, 0)
+ s, err := sysSocket(fd.family, fd.sotype, 0)
if err != nil {
- syscall.ForkLock.RUnlock()
return nil, &OpError{"socket", fd.net, fd.laddr, err}
}
- syscall.CloseOnExec(s)
- syscall.ForkLock.RUnlock()
// Associate our new socket with IOCP.
onceStartServer.Do(startServer)
src/pkg/net/interface_windows.go
の変更点:
--- a/src/pkg/net/interface_windows.go
+++ b/src/pkg/net/interface_windows.go
@@ -38,7 +38,7 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
}
func getInterfaceList() ([]syscall.InterfaceInfo, error) {
- s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
+ s, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
if err != nil {
return nil, os.NewSyscallError("Socket", err)
}
コアとなるコードの解説
src/pkg/net/fd_windows.go
の変更
netFD.accept
メソッドは、新しい接続を受け入れる際に新しいソケットを作成します。
-
変更前:
// See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err := syscall.Socket(fd.family, fd.sotype, 0) if err != nil { syscall.ForkLock.RUnlock() return nil, &OpError{"socket", fd.net, fd.laddr, err} } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock()
ここでは、ソケット作成の前後で
syscall.ForkLock
を取得・解放し、作成したソケットにCloseOnExec
フラグを設定していました。これはUnix系OSのセマンティクスに合わせたものでしたが、Windowsでは不要かつ不適切です。 -
変更後:
s, err := sysSocket(fd.family, fd.sotype, 0) if err != nil { return nil, &OpError{"socket", fd.net, fd.laddr, err} }
syscall.Socket
の呼び出しがsysSocket
に置き換えられ、それに伴いsyscall.ForkLock
とsyscall.CloseOnExec
の呼び出しが完全に削除されました。これにより、Windows環境でのソケット作成がsysSocket
に一元化され、Windowsのネイティブな動作に即した形になりました。sysSocket
が内部でWindowsソケットの適切な初期化(例えば、IOCPとの関連付けなど)を処理するため、これらの明示的なUnix系OSの概念は不要になります。
src/pkg/net/interface_windows.go
の変更
getInterfaceList
関数は、ネットワークインターフェースのリストを取得するためにUDPソケットを作成します。
-
変更前:
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
ここでも直接
syscall.Socket
を使用していました。 -
変更後:
s, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
同様に、
syscall.Socket
の呼び出しがsysSocket
に置き換えられました。これにより、インターフェースリスト取得のためのソケット作成もsysSocket
を通じて行われるようになり、Windowsソケット操作の一貫性が保たれます。
これらの変更は、Goの net
パッケージがWindows上でより効率的かつ正確に動作するための重要なステップであり、Windows固有のソケットプログラミングのベストプラクティスに準拠するものです。
関連リンク
- Go CL 7273046: https://golang.org/cl/7273046 (このコミットに対応するGoのコードレビューシステム上のチェンジリスト)
参考にした情報源リンク
- Go言語のソースコード (特に
src/pkg/net
およびsrc/pkg/syscall
のWindows関連ファイル) - Windows Sockets (Winsock) API ドキュメント (Microsoft Learn)
- I/O Completion Ports (IOCP) の概念に関する資料
- Go言語の
syscall
パッケージに関するドキュメントや議論 - Go言語の
net
パッケージの設計に関する議論 (Go issue tracker, mailing lists) - Unix系OSにおける
fork
およびexec
システムコールの動作に関する一般的な知識# [インデックス 15128] ファイルの概要
このコミットは、Go言語の net
パッケージにおけるWindows環境でのソケット作成処理を改善するものです。具体的には、ソケット作成に syscall.Socket
を直接使用する代わりに、内部ヘルパー関数である sysSocket
を一貫して利用するように変更しています。これにより、Windows固有のソケット操作の複雑性を sysSocket
に集約し、コードの整合性と保守性を向上させています。
コミット
Author: Alex Brainman alex.brainman@gmail.com Date: Mon Feb 4 16:03:41 2013 +1100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/94064548c66b76ae111c68e67729c3bd11ad3faf
元コミット内容
net: use windows sysSocket everywhere
R=golang-dev, bradfitz, dave
CC=golang-dev
https://golang.org/cl/7273046
変更の背景
Go言語の net
パッケージは、ネットワーク通信の基盤を提供します。異なるオペレーティングシステム(OS)に対応するため、OS固有のシステムコールを抽象化して利用しています。Windows環境では、ソケットの作成や管理に特有の考慮事項があります。
このコミットの背景には、Windowsにおけるソケット作成処理の一貫性と堅牢性の向上が挙げられます。以前のコードでは、ソケット作成に直接 syscall.Socket
を使用している箇所と、sysSocket
というヘルパー関数を使用している箇所が混在していました。sysSocket
は、Windows環境でのソケット作成時に必要な追加の初期化や設定(例えば、I/O完了ポート (IOCP) との関連付けなど)をカプセル化している可能性があります。
syscall.ForkLock
の削除は、Windowsにおける fork
の概念の欠如と関連しています。Unix系OSでは fork
システムコールがプロセス複製に使用され、ソケットディスクリプタの継承に関する問題を防ぐために ForkLock
が必要となる場合があります。しかし、Windowsでは fork
が存在しないため、このロックは不要であり、むしろオーバーヘッドや潜在的な誤解を招く可能性があります。同様に、syscall.CloseOnExec
もUnix系OSの概念であり、Windowsでは異なるメカニズムでソケットの継承が制御されるため、直接的な使用は適切ではありません。
したがって、この変更は、Windows固有のソケット操作を sysSocket
に集約し、不要なUnix系OSの概念(ForkLock
, CloseOnExec
)を排除することで、Windows版 net
パッケージのコードをよりクリーンで、Windowsのネイティブな動作に即したものにすることを目的としています。
前提知識の解説
- ソケット (Socket): ネットワーク通信のエンドポイント。アプリケーションがネットワーク経由でデータを送受信するために使用する抽象化されたインターフェース。
syscall.Socket
: OSのネイティブなsocket()
システムコールをGo言語から呼び出すための関数。ソケットを作成し、そのファイルディスクリプタ(Unix系)またはハンドル(Windows)を返します。sysSocket
(Go言語の内部ヘルパー関数): このコミットで言及されているsysSocket
は、Go言語のnet
パッケージ内部で定義されているWindows固有のソケット作成ヘルパー関数であると推測されます。これは、単にsyscall.Socket
を呼び出すだけでなく、WindowsのWinsock APIにおける追加の初期化や設定(例:WSASocket
の使用、I/O完了ポート (IOCP) との関連付け、非同期I/Oの設定など)を内部的に処理している可能性があります。これにより、Windows環境でのソケットの適切な動作を保証します。syscall.ForkLock
: Unix系OSにおいて、fork
システムコールが実行される際に、ファイルディスクリプタやその他のリソースの状態を保護するためのロック機構。fork
は親プロセスのメモリ空間を複製するため、ソケットなどの共有リソースが競合状態に陥るのを防ぐ必要があります。Windowsにはfork
の概念がないため、このロックは無関係です。syscall.CloseOnExec
: Unix系OSにおいて、exec
システムコール(新しいプログラムを実行する)が呼び出された際に、特定のファイルディスクリプタを自動的にクローズするように設定するフラグ。これにより、子プロセスに不要なファイルディスクリプタが継承されるのを防ぎます。Windowsでは、ソケットの継承は異なる方法で制御されます(例:WSADuplicateSocket
やSetHandleInformation
のHANDLE_FLAG_INHERIT
フラグ)。- Winsock (Windows Sockets API): Windowsオペレーティングシステムにおけるネットワークプログラミングインターフェース。Unix系OSのBerkeley Sockets APIに似ていますが、Windows固有の機能(例: I/O完了ポート、オーバーラップI/O)をサポートしています。
- I/O完了ポート (IOCP): Windowsにおける高性能な非同期I/Oモデル。複数のソケットからのI/Oイベントを効率的に処理するために使用されます。Goの
net
パッケージは、Windows上で高性能なネットワークI/Oを実現するためにIOCPを利用しています。
技術的詳細
このコミットの主要な技術的変更は、Windows環境におけるソケット作成の抽象化レイヤーを統一することです。
-
sysSocket
の一貫した利用:- 以前は
syscall.Socket
が直接呼び出されていた箇所が、sysSocket
に置き換えられました。これは、sysSocket
がWindows固有のソケット初期化ロジック(例えば、Winsockのバージョン交渉、IOCPとの関連付け、非同期I/O設定など)をカプセル化しているためです。 - これにより、ソケット作成に関するすべてのWindows固有の複雑性が
sysSocket
に集約され、コードの重複が排除され、将来的な変更やバグ修正が容易になります。 netFD.accept
メソッド内で新しいソケットを作成する際、およびgetInterfaceList
関数内でUDPソケットを作成する際に、この変更が適用されています。
- 以前は
-
syscall.ForkLock
の削除:netFD.accept
メソッドからsyscall.ForkLock.RLock()
とsyscall.ForkLock.RUnlock()
の呼び出しが削除されました。- これは、Windows OSにはUnix系OSの
fork
システムコールが存在しないため、ForkLock
が不要であるという事実に基づいています。このロックはWindows環境では意味がなく、コードの複雑性を増すだけでした。
-
syscall.CloseOnExec
の削除:netFD.accept
メソッドからsyscall.CloseOnExec(s)
の呼び出しが削除されました。- これも
ForkLock
と同様に、CloseOnExec
がUnix系OSのexec
システムコールに関連する概念であり、Windowsのソケット継承メカニズムとは異なるためです。Windowsでは、ソケットの継承は異なる方法で制御されます(例:WSADuplicateSocket
やSetHandleInformation
のHANDLE_FLAG_INHERIT
フラグ)。sysSocket
が内部的に適切なハンドルプロパティを設定しているか、またはGoランタイムがWindowsのソケット継承を適切に管理しているため、この明示的な呼び出しは不要となります。
これらの変更により、Goの net
パッケージのWindows実装は、よりWindowsのネイティブなAPIと動作モデルに適合し、不要なクロスプラットフォームの抽象化によるオーバーヘッドや混乱が排除されます。結果として、コードはよりクリーンで、理解しやすく、Windows環境でのパフォーマンスと安定性が向上する可能性があります。
コアとなるコードの変更箇所
このコミットでは、以下の2つのファイルが変更されています。
src/pkg/net/fd_windows.go
src/pkg/net/interface_windows.go
具体的な変更内容は以下の通りです。
src/pkg/net/fd_windows.go
の変更点:
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -619,15 +619,10 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
defer fd.decref()
// Get new socket.
- // See ../syscall/exec_unix.go for description of ForkLock.
- syscall.ForkLock.RLock()
- s, err := syscall.Socket(fd.family, fd.sotype, 0)
+ s, err := sysSocket(fd.family, fd.sotype, 0)
if err != nil {
- syscall.ForkLock.RUnlock()
return nil, &OpError{"socket", fd.net, fd.laddr, err}
}
- syscall.CloseOnExec(s)
- syscall.ForkLock.RUnlock()
// Associate our new socket with IOCP.
onceStartServer.Do(startServer)
src/pkg/net/interface_windows.go
の変更点:
--- a/src/pkg/net/interface_windows.go
+++ b/src/pkg/net/interface_windows.go
@@ -38,7 +38,7 @@ func getAdapterList() (*syscall.IpAdapterInfo, error) {
}
func getInterfaceList() ([]syscall.InterfaceInfo, error) {
- s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
+ s, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
if err != nil {
return nil, os.NewSyscallError("Socket", err)
}
コアとなるコードの解説
src/pkg/net/fd_windows.go
の変更
netFD.accept
メソッドは、新しい接続を受け入れる際に新しいソケットを作成します。
-
変更前:
// See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err := syscall.Socket(fd.family, fd.sotype, 0) if err != nil { syscall.ForkLock.RUnlock() return nil, &OpError{"socket", fd.net, fd.laddr, err} } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock()
ここでは、ソケット作成の前後で
syscall.ForkLock
を取得・解放し、作成したソケットにCloseOnExec
フラグを設定していました。これはUnix系OSのセマンティクスに合わせたものでしたが、Windowsでは不要かつ不適切です。 -
変更後:
s, err := sysSocket(fd.family, fd.sotype, 0) if err != nil { return nil, &OpError{"socket", fd.net, fd.laddr, err} }
syscall.Socket
の呼び出しがsysSocket
に置き換えられ、それに伴いsyscall.ForkLock
とsyscall.CloseOnExec
の呼び出しが完全に削除されました。これにより、Windows環境でのソケット作成がsysSocket
に一元化され、Windowsのネイティブな動作に即した形になりました。sysSocket
が内部でWindowsソケットの適切な初期化(例えば、IOCPとの関連付けなど)を処理するため、これらの明示的なUnix系OSの概念は不要になります。
src/pkg/net/interface_windows.go
の変更
getInterfaceList
関数は、ネットワークインターフェースのリストを取得するためにUDPソケットを作成します。
-
変更前:
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
ここでも直接
syscall.Socket
を使用していました。 -
変更後:
s, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
同様に、
syscall.Socket
の呼び出しがsysSocket
に置き換えられました。これにより、インターフェースリスト取得のためのソケット作成もsysSocket
を通じて行われるようになり、Windowsソケット操作の一貫性が保たれます。
これらの変更は、Goの net
パッケージがWindows上でより効率的かつ正確に動作するための重要なステップであり、Windows固有のソケットプログラミングのベストプラクティスに準拠するものです。
関連リンク
- Go CL 7273046: https://golang.org/cl/7273046 (このコミットに対応するGoのコードレビューシステム上のチェンジリスト)
参考にした情報源リンク
- Go言語のソースコード (特に
src/pkg/net
およびsrc/pkg/syscall
のWindows関連ファイル) - Windows Sockets (Winsock) API ドキュメント (Microsoft Learn)
- I/O Completion Ports (IOCP) の概念に関する資料
- Go言語の
syscall
パッケージに関するドキュメントや議論 - Go言語の
net
パッケージの設計に関する議論 (Go issue tracker, mailing lists) - Unix系OSにおける
fork
およびexec
システムコールの動作に関する一般的な知識