[インデックス 16342] ファイルの概要
このコミットは、Go言語のランタイムにおけるネットワークポーリング記述子(PollDesc
)のファイルディスクリプタ(fd
)の型をint32
からuintptr
に変更するものです。これは、特にWindows版のネットワークポーリング(netpoll
)の実装に向けた準備として行われました。
コミット
GoランタイムのPollDesc.fd
の型をint32
からuintptr
に変更。この変更は、Windows版のnetpoll
実装の準備として行われました。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/38abb09a2e4c682d0dcbe2d592c32bf0f9c2d1c5
元コミット内容
commit 38abb09a2e4c682d0dcbe2d592c32bf0f9c2d1c5
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Mon May 20 12:55:50 2013 +1000
runtime: change PollDesc.fd from int32 to uintptr
This is in preparation for netpoll windows version.
R=golang-dev, bradfitz
CC=dvyukov, golang-dev, mikioh.mikioh
https://golang.org/cl/9569043
変更の背景
この変更の主な背景は、GoランタイムのネットワークポーリングメカニズムをWindowsオペレーティングシステムに対応させるための準備です。Unix系システム(Linuxのepoll
やBSD/macOSのkqueue
など)では、ファイルディスクリプタ(FD)は通常、整数型(int
やint32
)で表現されます。しかし、Windowsでは、ファイルやソケットなどのI/Oオブジェクトは「ハンドル(HANDLE)」と呼ばれるポインタのような型で扱われることが多く、これはUnix系のFDとは概念が異なります。
int32
は32ビットの符号付き整数であり、その表現可能な値の範囲は限られています。一方、uintptr
はポインタを保持できる十分な大きさの符号なし整数型であり、システムが32ビットか64ビットかによってそのサイズが異なります。Windowsのハンドルは、32ビットシステムでは32ビット、64ビットシステムでは64ビットの値を持ちうるため、int32
では表現しきれない可能性があります。
このコミットは、将来的にWindowsのI/O完了ポート(IOCP: I/O Completion Port)などのメカニズムを利用したnetpoll
の実装を見据え、ファイルディスクリプタを表現する型を、より汎用性が高く、ポインタサイズに依存しないuintptr
に変更することで、クロスプラットフォームな互換性を確保しようとしています。
前提知識の解説
ファイルディスクリプタ (File Descriptor, FD)
ファイルディスクリプタは、Unix系オペレーティングシステムにおいて、ファイルやソケット、パイプなどのI/Oリソースを識別するためにカーネルがプロセスに割り当てる非負の整数です。プログラムは、このFDを通じてI/O操作を行います。
int32
int32
は、32ビットの符号付き整数型です。Go言語では、C言語との相互運用(cgo
)や、特定のビット幅を持つ整数が必要な場合に使用されます。最大値は約20億です。
uintptr
uintptr
は、Go言語における符号なし整数型で、ポインタを保持するのに十分な大きさを持つことが保証されています。そのサイズは、実行されているシステムのポインタサイズ(32ビットシステムでは32ビット、64ビットシステムでは64ビット)に依存します。これは、ポインタを整数として扱う必要がある場合や、C言語のポインタ型とGoの整数型の間で変換を行う際に特に有用です。uintptr
は、メモリのアドレスや、OSが提供するハンドルなどの抽象的な識別子を表現するのに適しています。
PollDesc
PollDesc
は、Goランタイムのネットワークポーリングメカニズムで使用される内部構造体です。これは、特定のファイルディスクリプタ(またはWindowsのハンドル)に関連付けられたポーリング状態を管理するために使用されます。例えば、読み込み可能になったか、書き込み可能になったかなどのイベントを監視します。
netpoll
netpoll
は、Goランタイムが提供する非同期ネットワークI/Oの基盤となるメカニズムです。これは、複数のネットワーク接続からのI/Oイベントを効率的に処理するために、オペレーティングシステムが提供するポーリングAPI(Linuxのepoll
、BSD/macOSのkqueue
、WindowsのIOCPなど)を利用します。netpoll
は、Goのgoroutineスケジューラと連携し、I/Oが準備できるまでgoroutineをブロックし、準備ができたら再開することで、多数の同時接続を効率的に扱うことを可能にします。
epoll
とkqueue
epoll
: Linuxカーネルが提供する高性能なI/Oイベント通知メカニズムです。多数のファイルディスクリプタを効率的に監視し、I/Oイベントが発生したFDのみを通知します。kqueue
: FreeBSD、macOS、NetBSD、OpenBSDなどのBSD系OSで利用可能なイベント通知インターフェースです。epoll
と同様に、多数のファイルディスクリプタやその他のイベントソースからのイベントを効率的に監視します。
WindowsのI/Oモデルとハンドル
Windowsでは、Unix系のファイルディスクリプタとは異なり、「ハンドル(HANDLE)」という概念がI/Oオブジェクトの識別子として使われます。ハンドルは、カーネルオブジェクト(ファイル、ソケット、イベントなど)への参照であり、その実体はポインタのような値です。Windowsの非同期I/Oは、主にI/O完了ポート(IOCP)を介して行われます。IOCPは、複数の非同期I/O操作の完了を効率的に処理するためのメカニズムです。
技術的詳細
このコミットの技術的な核心は、ファイルディスクリプタの型をint32
からuintptr
に変更することによって、Goランタイムのネットワークポーリング層がより広範なプラットフォーム、特にWindowsに対応できるようになる点にあります。
-
型サイズの互換性:
- Unix系システムでは、ファイルディスクリプタは通常、比較的低い整数値で表現され、
int32
で十分な場合が多いです。 - しかし、Windowsのハンドルは、32ビットシステムでは32ビット、64ビットシステムでは64ビットの値を持ちます。
int32
は32ビットの符号付き整数であるため、64ビットシステムで64ビットのハンドル値を扱う場合にはオーバーフローが発生し、正しくハンドルを表現できなくなります。 uintptr
は、実行環境のポインタサイズ(32ビットまたは64ビット)に合わせてサイズが変化するため、32ビットシステムでも64ビットシステムでも、ポインタやハンドルを正確に表現できます。これにより、GoランタイムがWindowsのネイティブなハンドルを直接扱うことが可能になります。
- Unix系システムでは、ファイルディスクリプタは通常、比較的低い整数値で表現され、
-
ポインタとしての扱い:
uintptr
は、その名の通り「ポインタを保持できる整数型」であり、C言語のポインタ型とGoの整数型の間で安全に変換を行うための橋渡しとなります。- Goランタイムの
netpoll
実装は、C言語で書かれた部分(netpoll_epoll.c
,netpoll_kqueue.c
など)とGo言語で書かれた部分(fd_poll_runtime.go
,netpoll.goc
など)が混在しています。C言語側ではファイルディスクリプタやハンドルをポインタまたはポインタサイズの整数として扱うことが一般的であり、uintptr
への変更は、これらのC言語側の実装との整合性を高めます。
-
クロスプラットフォーム対応の柔軟性:
- この変更により、
PollDesc.fd
は、Unix系のFDもWindowsのハンドルも、抽象化されたuintptr
として扱うことができるようになります。 - これにより、
netpoll
のインターフェース自体は変更せずに、プラットフォーム固有の実装(netpoll_windows.c
のようなファイルが将来追加されることを想定)で、それぞれのOSのI/O識別子を適切に処理できるようになります。
- この変更により、
このコミットは、Go言語がより多くのプラットフォームで高性能なネットワークI/Oを提供するための、重要な基盤整備の一環と言えます。
コアとなるコードの変更箇所
このコミットでは、以下の5つのファイルが変更されています。主な変更は、PollDesc
構造体のfd
フィールドの型、およびnetpollopen
やnetpollclose
といった関連関数の引数や内部での型キャストをint32
からuintptr
に変更することです。
src/pkg/net/fd_poll_runtime.go
src/pkg/runtime/netpoll.goc
src/pkg/runtime/netpoll_epoll.c
src/pkg/runtime/netpoll_kqueue.c
src/pkg/runtime/runtime.h
具体的な変更点:
src/pkg/net/fd_poll_runtime.go
:runtime_pollOpen
関数の引数fd
の型がint
からuintptr
に変更。fd.sysfd
をruntime_pollOpen
に渡す際にuintptr(fd.sysfd)
と明示的に型キャスト。
src/pkg/runtime/netpoll.goc
:runtime·netpollopen
関数のプロトタイプ宣言で、fd
の型がint32
からuintptr
に変更。PollDesc
構造体内のfd
フィールドの型がint32
からuintptr
に変更。runtime_pollOpen
関数の引数fd
の型がint
からuintptr
に変更。
src/pkg/runtime/netpoll_epoll.c
:runtime·netpollopen
関数の引数fd
の型がint32
からuintptr
に変更。runtime·epollctl
関数にfd
を渡す際に(int32)fd
と型キャスト。runtime·netpollclose
関数の引数fd
の型がint32
からuintptr
に変更。runtime·epollctl
関数にfd
を渡す際に(int32)fd
と型キャスト。
src/pkg/runtime/netpoll_kqueue.c
:runtime·netpollopen
関数の引数fd
の型がint32
からuintptr
に変更。Kevent
構造体のident
フィールドにfd
を代入する際に(uint32)fd
と型キャスト。ev[0].ident
やev[1].ident
の比較で(uint32)fd
と型キャスト。runtime·netpollclose
関数の引数fd
の型がint32
からuintptr
に変更。
src/pkg/runtime/runtime.h
:runtime·netpollopen
とruntime·netpollclose
関数のプロトタイプ宣言で、fd
の型がint32
からuintptr
に変更。
コアとなるコードの解説
これらの変更は、Goランタイムのネットワークポーリングサブシステム全体にわたる型の一貫性を確保し、特にWindowsプラットフォームへの対応を容易にするためのものです。
PollDesc
構造体のfd
フィールド: このフィールドは、ポーリング対象となるファイルディスクリプタ(またはハンドル)を保持します。int32
からuintptr
への変更により、32ビットおよび64ビットシステムの両方で、Unix系のFDとWindowsのハンドルの両方を適切に格納できるようになります。runtime_pollOpen
関数: Go言語側からランタイムのポーリング機能を開くための関数です。引数の型をuintptr
に変更することで、GoのnetFD.sysfd
(システム固有のファイルディスクリプタ/ハンドル)を直接、型安全にランタイムに渡せるようになります。runtime·netpollopen
およびruntime·netpollclose
関数(C言語側): これらは、epoll
やkqueue
といったOSネイティブのポーリングAPIを呼び出すためのC言語関数です。引数の型をuintptr
に変更することで、Go側から渡されたuintptr
型の値を直接受け取ることができます。- C言語側では、
epoll_ctl
やkevent
といったシステムコールが期待する型(通常はint
やuint32
)に合わせて、受け取ったuintptr
値を明示的に型キャストしています。これは、uintptr
がポインタサイズに依存する汎用的な整数型であるのに対し、システムコールは特定のビット幅の整数を要求するためです。このキャストは、uintptr
が実際にFDやハンドルとして有効な値を保持していることを前提としています。
- C言語側では、
runtime.h
: ランタイムのC言語部分で利用されるヘッダファイルであり、関数のプロトタイプ宣言が含まれています。ここでの型変更は、ランタイム全体のインターフェースの一貫性を保つために必要です。
全体として、この変更は、Goランタイムが異なるOSのI/O識別子を抽象化し、統一されたuintptr
型で扱うことで、クロスプラットフォームなnetpoll
実装の柔軟性と堅牢性を高めるための基盤を築いています。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/38abb09a2e4c682d0dcbe2d592c32bf0f9c2d1c5
参考にした情報源リンク
- Go言語の
uintptr
に関するドキュメントや解説記事 - Go言語の
netpoll
に関する技術ブログやソースコード解説 - Linuxの
epoll
、BSDのkqueue
、WindowsのI/O完了ポート(IOCP)に関するOSドキュメントや解説 - Unix系OSのファイルディスクリプタとWindowsのハンドルの違いに関する情報
- Go言語の
cgo
に関するドキュメント# [インデックス 16342] ファイルの概要
このコミットは、Go言語のランタイムにおけるネットワークポーリング記述子(PollDesc
)のファイルディスクリプタ(fd
)の型をint32
からuintptr
に変更するものです。これは、特にWindows版のネットワークポーリング(netpoll
)の実装に向けた準備として行われました。
コミット
GoランタイムのPollDesc.fd
の型をint32
からuintptr
に変更。この変更は、Windows版のnetpoll
実装の準備として行われました。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/38abb09a2e4c682d0dcbe2d592c32bf0f9c2d1c5
元コミット内容
commit 38abb09a2e4c682d0dcbe2d592c32bf0f9c2d1c5
Author: Alex Brainman <alex.brainman@gmail.com>
Date: Mon May 20 12:55:50 2013 +1000
runtime: change PollDesc.fd from int32 to uintptr
This is in preparation for netpoll windows version.
R=golang-dev, bradfitz
CC=dvyukov, golang-dev, mikioh.mikioh
https://golang.org/cl/9569043
変更の背景
この変更の主な背景は、GoランタイムのネットワークポーリングメカニズムをWindowsオペレーティングシステムに対応させるための準備です。Unix系システム(Linuxのepoll
やBSD/macOSのkqueue
など)では、ファイルディスクリプタ(FD)は通常、整数型(int
やint32
)で表現されます。しかし、Windowsでは、ファイルやソケットなどのI/Oオブジェクトは「ハンドル(HANDLE)」と呼ばれるポインタのような型で扱われることが多く、これはUnix系のFDとは概念が異なります。
int32
は32ビットの符号付き整数であり、その表現可能な値の範囲は限られています。一方、uintptr
はポインタを保持できる十分な大きさの符号なし整数型であり、システムが32ビットか64ビットかによってそのサイズが異なります。Windowsのハンドルは、32ビットシステムでは32ビット、64ビットシステムでは64ビットの値を持ちうるため、int32
では表現しきれない可能性があります。
このコミットは、将来的にWindowsのI/O完了ポート(IOCP: I/O Completion Port)などのメカニズムを利用したnetpoll
の実装を見据え、ファイルディスクリプタを表現する型を、より汎用性が高く、ポインタサイズに依存しないuintptr
に変更することで、クロスプラットフォームな互換性を確保しようとしています。
前提知識の解説
ファイルディスクリプタ (File Descriptor, FD)
ファイルディスクリプタは、Unix系オペレーティングシステムにおいて、ファイルやソケット、パイプなどのI/Oリソースを識別するためにカーネルがプロセスに割り当てる非負の整数です。プログラムは、このFDを通じてI/O操作を行います。
int32
int32
は、32ビットの符号付き整数型です。Go言語では、C言語との相互運用(cgo
)や、特定のビット幅を持つ整数が必要な場合に使用されます。最大値は約20億です。
uintptr
uintptr
は、Go言語における符号なし整数型で、ポインタを保持するのに十分な大きさを持つことが保証されています。そのサイズは、実行されているシステムのポインタサイズ(32ビットシステムでは32ビット、64ビットシステムでは64ビット)に依存します。これは、ポインタを整数として扱う必要がある場合や、C言語のポインタ型とGoの整数型の間で変換を行う際に特に有用です。uintptr
は、メモリのアドレスや、OSが提供するハンドルなどの抽象的な識別子を表現するのに適しています。
PollDesc
PollDesc
は、Goランタイムのネットワークポーリングメカニズムで使用される内部構造体です。これは、特定のファイルディスクリプタ(またはWindowsのハンドル)に関連付けられたポーリング状態を管理するために使用されます。例えば、読み込み可能になったか、書き込み可能になったかなどのイベントを監視します。
netpoll
netpoll
は、Goランタイムが提供する非同期ネットワークI/Oの基盤となるメカニズムです。これは、複数のネットワーク接続からのI/Oイベントを効率的に処理するために、オペレーティングシステムが提供するポーリングAPI(Linuxのepoll
、BSD/macOSのkqueue
、WindowsのIOCPなど)を利用します。netpoll
は、Goのgoroutineスケジューラと連携し、I/Oが準備できるまでgoroutineをブロックし、準備ができたら再開することで、多数の同時接続を効率的に扱うことを可能にします。
epoll
とkqueue
epoll
: Linuxカーネルが提供する高性能なI/Oイベント通知メカニズムです。多数のファイルディスクリプタを効率的に監視し、I/Oイベントが発生したFDのみを通知します。kqueue
: FreeBSD、macOS、NetBSD、OpenBSDなどのBSD系OSで利用可能なイベント通知インターフェースです。epoll
と同様に、多数のファイルディスクリプタやその他のイベントソースからのイベントを効率的に監視します。
WindowsのI/Oモデルとハンドル
Windowsでは、Unix系のファイルディスクリプタとは異なり、「ハンドル(HANDLE)」という概念がI/Oオブジェクトの識別子として使われます。ハンドルは、カーネルオブジェクト(ファイル、ソケット、イベントなど)への参照であり、その実体はポインタのような値です。Windowsの非同期I/Oは、主にI/O完了ポート(IOCP)を介して行われます。IOCPは、複数の非同期I/O操作の完了を効率的に処理するためのメカニズムです。
技術的詳細
このコミットの技術的な核心は、ファイルディスクリプタの型をint32
からuintptr
に変更することによって、Goランタイムのネットワークポーリング層がより広範なプラットフォーム、特にWindowsに対応できるようになる点にあります。
-
型サイズの互換性:
- Unix系システムでは、ファイルディスクリプタは通常、比較的低い整数値で表現され、
int32
で十分な場合が多いです。 - しかし、Windowsのハンドルは、32ビットシステムでは32ビット、64ビットシステムでは64ビットの値を持ちます。
int32
は32ビットの符号付き整数であるため、64ビットシステムで64ビットのハンドル値を扱う場合にはオーバーフローが発生し、正しくハンドルを表現できなくなります。 uintptr
は、実行環境のポインタサイズ(32ビットまたは64ビット)に合わせてサイズが変化するため、32ビットシステムでも64ビットシステムでも、ポインタやハンドルを正確に表現できます。これにより、GoランタイムがWindowsのネイティブなハンドルを直接扱うことが可能になります。
- Unix系システムでは、ファイルディスクリプタは通常、比較的低い整数値で表現され、
-
ポインタとしての扱い:
uintptr
は、その名の通り「ポインタを保持できる整数型」であり、C言語のポインタ型とGoの整数型の間で安全に変換を行うための橋渡しとなります。- Goランタイムの
netpoll
実装は、C言語で書かれた部分(netpoll_epoll.c
,netpoll_kqueue.c
など)とGo言語で書かれた部分(fd_poll_runtime.go
,netpoll.goc
など)が混在しています。C言語側ではファイルディスクリプタやハンドルをポインタまたはポインタサイズの整数として扱うことが一般的であり、uintptr
への変更は、これらのC言語側の実装との整合性を高めます。
-
クロスプラットフォーム対応の柔軟性:
- この変更により、
PollDesc.fd
は、Unix系のFDもWindowsのハンドルも、抽象化されたuintptr
として扱うことができるようになります。 - これにより、
netpoll
のインターフェース自体は変更せずに、プラットフォーム固有の実装(netpoll_windows.c
のようなファイルが将来追加されることを想定)で、それぞれのOSのI/O識別子を適切に処理できるようになります。
- この変更により、
このコミットは、Go言語がより多くのプラットフォームで高性能なネットワークI/Oを提供するための、重要な基盤整備の一環と言えます。
コアとなるコードの変更箇所
このコミットでは、以下の5つのファイルが変更されています。主な変更は、PollDesc
構造体のfd
フィールドの型、およびnetpollopen
やnetpollclose
といった関連関数の引数や内部での型キャストをint32
からuintptr
に変更することです。
src/pkg/net/fd_poll_runtime.go
src/pkg/runtime/netpoll.goc
src/pkg/runtime/netpoll_epoll.c
src/pkg/runtime/netpoll_kqueue.c
src/pkg/runtime/runtime.h
具体的な変更点:
src/pkg/net/fd_poll_runtime.go
:runtime_pollOpen
関数の引数fd
の型がint
からuintptr
に変更。fd.sysfd
をruntime_pollOpen
に渡す際にuintptr(fd.sysfd)
と明示的に型キャスト。
src/pkg/runtime/netpoll.goc
:runtime·netpollopen
関数のプロトタイプ宣言で、fd
の型がint32
からuintptr
に変更。PollDesc
構造体内のfd
フィールドの型がint32
からuintptr
に変更。runtime_pollOpen
関数の引数fd
の型がint
からuintptr
に変更。
src/pkg/runtime/netpoll_epoll.c
:runtime·netpollopen
関数の引数fd
の型がint32
からuintptr
に変更。runtime·epollctl
関数にfd
を渡す際に(int32)fd
と型キャスト。runtime·netpollclose
関数の引数fd
の型がint32
からuintptr
に変更。runtime·epollctl
関数にfd
を渡す際に(int32)fd
と型キャスト。
src/pkg/runtime/netpoll_kqueue.c
:runtime·netpollopen
関数の引数fd
の型がint32
からuintptr
に変更。Kevent
構造体のident
フィールドにfd
を代入する際に(uint32)fd
と型キャスト。ev[0].ident
やev[1].ident
の比較で(uint32)fd
と型キャスト。runtime·netpollclose
関数の引数fd
の型がint32
からuintptr
に変更。
src/pkg/runtime/runtime.h
:runtime·netpollopen
とruntime·netpollclose
関数のプロトタイプ宣言で、fd
の型がint32
からuintptr
に変更。
コアとなるコードの解説
これらの変更は、Goランタイムのネットワークポーリングサブシステム全体にわたる型の一貫性を確保し、特にWindowsプラットフォームへの対応を容易にするためのものです。
PollDesc
構造体のfd
フィールド: このフィールドは、ポーリング対象となるファイルディスクリプタ(またはハンドル)を保持します。int32
からuintptr
への変更により、32ビットおよび64ビットシステムの両方で、Unix系のFDとWindowsのハンドルの両方を適切に格納できるようになります。runtime_pollOpen
関数: Go言語側からランタイムのポーリング機能を開くための関数です。引数の型をuintptr
に変更することで、GoのnetFD.sysfd
(システム固有のファイルディスクリプタ/ハンドル)を直接、型安全にランタイムに渡せるようになります。runtime·netpollopen
およびruntime·netpollclose
関数(C言語側): これらは、epoll
やkqueue
といったOSネイティブのポーリングAPIを呼び出すためのC言語関数です。引数の型をuintptr
に変更することで、Go側から渡されたuintptr
型の値を直接受け取ることができます。- C言語側では、
epoll_ctl
やkevent
といったシステムコールが期待する型(通常はint
やuint32
)に合わせて、受け取ったuintptr
値を明示的に型キャストしています。これは、uintptr
がポインタサイズに依存する汎用的な整数型であるのに対し、システムコールは特定のビット幅の整数を要求するためです。このキャストは、uintptr
が実際にFDやハンドルとして有効な値を保持していることを前提としています。
- C言語側では、
runtime.h
: ランタイムのC言語部分で利用されるヘッダファイルであり、関数のプロトタイプ宣言が含まれています。ここでの型変更は、ランタイム全体のインターフェースの一貫性を保つために必要です。
全体として、この変更は、Goランタイムが異なるOSのI/O識別子を抽象化し、統一されたuintptr
型で扱うことで、クロスプラットフォームなnetpoll
実装の柔軟性と堅牢性を高めるための基盤を築いています。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/38abb09a2e4c682d0dcbe2d592c32bf0f9c2d1c5
参考にした情報源リンク
- Go言語の
uintptr
に関するドキュメントや解説記事 - Go言語の
netpoll
に関する技術ブログやソースコード解説 - Linuxの
epoll
、BSDのkqueue
、WindowsのI/O完了ポート(IOCP)に関するOSドキュメントや解説 - Unix系OSのファイルディスクリプタとWindowsのハンドルの違いに関する情報
- Go言語の
cgo
に関するドキュメント