[インデックス 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.gosrc/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.gosrc/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システムコールの動作に関する一般的な知識