[インデックス 15399] ファイルの概要
このコミットは、Go言語の syscall
パッケージにおいて、FreeBSDシステムコールに対する if_announce
イベントのサポートを追加するものです。これにより、GoプログラムがFreeBSD上でネットワークインターフェースの到着(IFAN_ARRIVAL
)や離脱(IFAN_DEPARTURE
)といったイベントを検知し、処理できるようになります。
コミット
commit b1d51c63d6626e0e78f5ea0e1f4b6eda4af045e0
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Sun Feb 24 12:04:48 2013 +0900
syscall: add if_announce support for freebsd
Update #4866.
R=golang-dev, dave
CC=golang-dev
https://golang.org/cl/7398047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/b1d51c63d6626e0e78f5ea0e1f4b6eda4af045e0
元コミット内容
syscall: add if_announce support for freebsd
このコミットは、FreeBSDにおける if_announce
イベントのサポートをGo言語の syscall
パッケージに追加します。これは、Issue #4866 に関連する更新です。
変更の背景
Go言語の syscall
パッケージは、オペレーティングシステムの低レベルな機能(システムコール)にアクセスするためのインターフェースを提供します。FreeBSDのようなUNIX系OSでは、ネットワークインターフェースの追加や削除といったイベントをカーネルがユーザーランドに通知するメカニズムが存在します。このメカニズムの一つが if_announce
です。
このコミットが作成された背景には、GoプログラムがFreeBSD環境でネットワークインターフェースの状態変化をより詳細に、かつ効率的に監視・応答できるようにするという目的があります。具体的には、新しいネットワークインターフェースがシステムに接続された際(IFAN_ARRIVAL
)や、既存のインターフェースが切断された際(IFAN_DEPARTURE
)に、Goプログラムがこれらのイベントを検知し、適切な処理を実行できるようになることが求められました。
コミットメッセージに記載されている #4866
は、この機能追加の必要性を示唆するGoのIssueトラッカー上の課題番号であると考えられます。Goの標準ライブラリが様々なOSのシステムコールをサポートする中で、FreeBSD固有の重要なネットワークイベント通知メカニズムである if_announce
のサポートは、FreeBSD上でのGoアプリケーションのネットワーク機能の充実と安定性向上に寄与します。
前提知識の解説
FreeBSDの if_announce
FreeBSDにおける if_announce
は、カーネルがネットワークインターフェースに関するイベントをユーザーランドに通知するためのメカニズムです。これは ifnet
フレームワークの一部であり、ネットワークインターフェースのライフサイクル管理(作成、登録、破棄など)に関連するイベントをシグナルします。
具体的には、以下のようなイベントが if_announce
を通じて通知されます。
IFAN_ARRIVAL
: 新しいネットワークインターフェースがシステムに接続された、または利用可能になったことを示します。IFAN_DEPARTURE
: ネットワークインターフェースがシステムから切断された、または利用不可能になったことを示します。
これらのイベントは、ユーザーランドのユーティリティ(例: devd(8)
)が監視し、インターフェースの状態変化に応じて特定のアクションやスクリプトをトリガーするために利用されます。
Go言語の syscall
パッケージ
Go言語の syscall
パッケージは、Goプログラムが基盤となるオペレーティングシステムのプリミティブに直接アクセスするための低レベルなインターフェースを提供します。これにより、プロセス管理、ファイル操作、ネットワーク通信などのシステムコールを直接実行できます。
syscall
パッケージの主な特徴は以下の通りです。
- 低レベルな相互作用: GoアプリケーションとOSカーネル間の橋渡し役となり、プロセス作成、ファイルの読み書き、メモリ管理などのサービスを要求します。
- プラットフォーム固有:
syscall
パッケージ内の関数や定数の詳細、および利用可能性は、オペレーティングシステム(Windows, Linux, macOSなど)によって大きく異なります。 - 新規コードでの非推奨: 標準Goライブラリの
syscall
パッケージは「ロックダウン」されており、新しい開発ではgolang.org/x/sys
パッケージ、特にUnix系システムではgolang.org/x/sys/unix
の使用が強く推奨されています。これは、外部パッケージの方がより多くのシステムコールをサポートし、移植性が高く、新しい更新やシステム固有の実装が適用されるためです。 - 高レベルな代替: ほとんどの一般的なプログラミングタスクでは、Goの標準ライブラリが提供する
os
、time
、net
などのより移植性が高く、使いやすい高レベルなパッケージを使用することが推奨されます。可能な限り、syscall
よりもこれらの高レベルなパッケージを優先すべきです。
このコミットは、syscall
パッケージがまだ活発にOS固有の機能を取り込んでいた時期のものであり、FreeBSDの if_announce
をGoプログラムから利用可能にするための基盤を構築するものです。
技術的詳細
このコミットは、FreeBSDの if_announce
イベントをGoの syscall
パッケージで扱えるようにするために、主に以下の変更を行っています。
-
mkerrors.sh
の更新:mkerrors.sh
は、Goのsyscall
パッケージがOS固有のエラーコードや定数を生成するために使用するスクリプトです。このスクリプトにIFAN
というプレフィックスを持つ定数(IFAN_ARRIVAL
,IFAN_DEPARTURE
など)を認識させるための正規表現が追加されています。これにより、FreeBSDのカーネルヘッダーファイルからこれらの定数が正しくGoのコードに変換されるようになります。 -
types_freebsd.go
の更新: このファイルは、FreeBSD固有のシステムコールに関連するGoの型定義を含んでいます。SizeofIfAnnounceMsghdr
という定数が追加され、C.sizeof_struct_if_announcemsghdr
のサイズが定義されています。これは、if_announce
メッセージヘッダーのサイズを示すものです。IfAnnounceMsghdr
という新しいGoの構造体型が追加されています。この構造体は、FreeBSDカーネルがif_announce
イベントを通知する際に使用するstruct if_announcemsghdr
に対応します。
-
zerrors_freebsd_*.go
ファイルの更新:zerrors_freebsd_386.go
,zerrors_freebsd_amd64.go
,zerrors_freebsd_arm.go
は、それぞれ32ビット、64ビット、ARMアーキテクチャ向けのFreeBSD固有のエラーコードや定数を定義する自動生成ファイルです。これらのファイルにIFAN_ARRIVAL
とIFAN_DEPARTURE
の定数が追加されています。これらの定数は、ネットワークインターフェースの到着と離脱を示すイベントタイプです。 -
ztypes_freebsd_*.go
ファイルの更新:ztypes_freebsd_386.go
,ztypes_freebsd_amd64.go
,ztypes_freebsd_arm.go
は、FreeBSD固有のシステムコールに関連するGoの型定義を自動生成するファイルです。SizeofIfAnnounceMsghdr
定数の具体的な値(例:0x18
)が各アーキテクチャ向けに追加されています。これは、if_announcemsghdr
構造体の実際のサイズを示します。IfAnnounceMsghdr
構造体のGo言語での定義が追加されています。この構造体は、Msglen
(メッセージ長)、Version
(バージョン)、Type
(メッセージタイプ)、Index
(インターフェースインデックス)、Name
(インターフェース名)、What
(イベントタイプ、IFAN_ARRIVAL
またはIFAN_DEPARTURE
) などのフィールドを持ちます。これらのフィールドは、FreeBSDカーネルがif_announce
イベントを通知する際に送信する情報に対応します。
これらの変更により、Goプログラムは syscall
パッケージを通じてFreeBSDの if_announce
イベントを受信し、その内容をGoの構造体として解釈できるようになります。これにより、Goで書かれたネットワーク関連のツールやデーモンが、FreeBSD環境下でネットワークインターフェースの動的な変化に適切に対応できるようになります。
コアとなるコードの変更箇所
このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。
-
src/pkg/syscall/mkerrors.sh
:--- a/src/pkg/syscall/mkerrors.sh +++ b/src/pkg/syscall/mkerrors.sh @@ -207,7 +207,7 @@ ccflags="$@" $2 ~ /^LINUX_REBOOT_CMD_/ || $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || $2 !~ "NLA_TYPE_MASK" && - $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ || + $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ || $2 ~ /^SIOC/ || $2 ~ /^TIOC/ || $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
-
src/pkg/syscall/types_freebsd.go
:--- a/src/pkg/syscall/types_freebsd.go +++ b/src/pkg/syscall/types_freebsd.go @@ -193,12 +193,13 @@ type FdSet C.fd_set // Routing and interface messages const ( - SizeofIfMsghdr = C.sizeof_struct_if_msghdr - SizeofIfData = C.sizeof_struct_if_data - SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr - SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr - SizeofRtMsghdr = C.sizeof_struct_rt_msghdr - SizeofRtMetrics = C.sizeof_struct_rt_metrics + SizeofIfMsghdr = C.sizeof_struct_if_msghdr + SizeofIfData = C.sizeof_struct_if_data + SizeofIfaMsghdr = C.sizeof_struct_ifa_msghdr + SizeofIfmaMsghdr = C.sizeof_struct_ifma_msghdr + SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr + SizeofRtMsghdr = C.sizeof_struct_rt_msghdr + SizeofRtMetrics = C.sizeof_struct_rt_metrics ) type IfMsghdr C.struct_if_msghdr @@ -209,6 +210,8 @@ type IfaMsghdr C.struct_ifa_msghdr type IfmaMsghdr C.struct_ifma_msghdr +type IfAnnounceMsghdr C.struct_if_announcemsghdr + type RtMsghdr C.struct_rt_msghdr type RtMetrics C.struct_rt_metrics
-
src/pkg/syscall/zerrors_freebsd_386.go
(amd64, armも同様):--- a/src/pkg/syscall/zerrors_freebsd_386.go +++ b/src/pkg/syscall/zerrors_freebsd_386.go @@ -369,6 +369,8 @@ const ( F_UNLCK = 0x2 F_UNLCKSYS = 0x4 F_WRLCK = 0x3 + IFAN_ARRIVAL = 0x0 + IFAN_DEPARTURE = 0x1 IFF_ALLMULTI = 0x200 IFF_ALTPHYS = 0x4000 IFF_BROADCAST = 0x2
-
src/pkg/syscall/ztypes_freebsd_386.go
(amd64, armも同様):--- a/src/pkg/syscall/ztypes_freebsd_386.go +++ b/src/pkg/syscall/ztypes_freebsd_386.go @@ -271,12 +271,13 @@ type FdSet struct { } const ( - SizeofIfMsghdr = 0x60 - SizeofIfData = 0x50 - SizeofIfaMsghdr = 0x14 - SizeofIfmaMsghdr = 0x10 - SizeofRtMsghdr = 0x5c - SizeofRtMetrics = 0x38 + SizeofIfMsghdr = 0x60 + SizeofIfData = 0x50 + SizeofIfaMsghdr = 0x14 + SizeofIfmaMsghdr = 0x10 + SizeofIfAnnounceMsghdr = 0x18 + SizeofRtMsghdr = 0x5c + SizeofRtMetrics = 0x38 ) type IfMsghdr struct { @@ -339,6 +340,15 @@ type IfmaMsghdr struct { Pad_cgo_0 [2]byte } +type IfAnnounceMsghdr struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Name [16]int8 + What uint16 +} + type RtMsghdr struct { Msglen uint16 Version uint8
コアとなるコードの解説
src/pkg/syscall/mkerrors.sh
の変更
mkerrors.sh
は、Goの syscall
パッケージがC言語のヘッダーファイルから定数を自動生成する際に使用するシェルスクリプトです。変更点では、正規表現 ^(NETLINK|NLM|NLMSG|NLA|IFA|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/
に |IFAN
が追加されています。
これは、IFAN_
で始まる定数(例: IFAN_ARRIVAL
, IFAN_DEPARTURE
)も自動生成の対象に含めることを意味します。これにより、FreeBSDカーネルが定義する if_announce
関連の定数がGoの syscall
パッケージで利用可能になります。
src/pkg/syscall/types_freebsd.go
の変更
このファイルは、FreeBSD固有のシステムコールに関連するGoの型定義を手動で記述する場所です。
SizeofIfAnnounceMsghdr = C.sizeof_struct_if_announcemsghdr
の追加は、C言語のstruct if_announcemsghdr
のサイズをGoの定数として定義しています。これは、GoがCの構造体を扱う際にメモリレイアウトを正しく理解するために必要です。type IfAnnounceMsghdr C.struct_if_announcemsghdr
の追加は、C言語のstruct if_announcemsghdr
に対応するGoの型エイリアスを定義しています。これにより、Goコード内でこの構造体を型安全に参照できるようになります。
src/pkg/syscall/zerrors_freebsd_*.go
の変更
これらのファイルは、mkerrors.sh
スクリプトによって自動生成される、FreeBSD固有の定数定義を含んでいます。各アーキテクチャ(386, amd64, arm)向けに、IFAN_ARRIVAL
と IFAN_DEPARTURE
の定数が追加されています。
IFAN_ARRIVAL = 0x0
: ネットワークインターフェースが到着したことを示すイベントタイプ。IFAN_DEPARTURE = 0x1
: ネットワークインターフェースが離脱したことを示すイベントタイプ。 これらの定数は、Goプログラムがif_announce
メッセージを受信した際に、どのようなイベントが発生したかを識別するために使用されます。
src/pkg/syscall/ztypes_freebsd_*.go
の変更
これらのファイルも、mkerrors.sh
スクリプトによって自動生成される、FreeBSD固有の型定義を含んでいます。各アーキテクチャ向けに以下の変更が行われています。
SizeofIfAnnounceMsghdr
定数の具体的な値(例:0x18
for 386/arm,0x18
for amd64)が追加されています。これは、if_announcemsghdr
構造体の実際のバイトサイズを示し、Goがこの構造体を正しくパースするために重要です。IfAnnounceMsghdr
構造体のGo言語での定義が追加されています。この構造体は、FreeBSDカーネルがif_announce
イベントを通知する際に送信するメッセージのフォーマットをGoで表現したものです。Msglen uint16
: メッセージ全体の長さ。Version uint8
: メッセージのバージョン。Type uint8
: メッセージのタイプ(例:RTM_IFANNOUNCE
)。Index uint16
: イベントが発生したネットワークインターフェースのインデックス。Name [16]int8
: インターフェースの名前(例: "em0", "lo0")。What uint16
: 発生したイベントの種類(IFAN_ARRIVAL
またはIFAN_DEPARTURE
)。
これらの変更により、GoプログラムはFreeBSDの if_announce
イベントをシステムコールレベルで捕捉し、そのバイナリデータをGoの構造体にマッピングして、イベントの詳細をプログラム的に利用できるようになります。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/b1d51c63d6626e0e78f5ea0e1f4b6eda4af045e0
- Go Code Review: https://golang.org/cl/7398047
参考にした情報源リンク
- FreeBSD
if_announce
の概要: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFTq1gT9-OXg6l8jJ20y_DjER30EOjflAF4a1EACOlsuARuXZGx2jVXtLCOfZvF0PTBQLHhIpw4Tp2dRuTFytbUS54YS3M5-TzMwc-H0ijv6OSnWsWnf3NU - Go
syscall
パッケージの解説: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQE-OZ8Y4Bi7i5dK9ZytMQwBOrF8Bt458Lu0SVwWvg4iMUVp6yKk0oHtuPJOp3tDh7SQtlvgzQ8ddw-LrA8xEaKSaFfmiZ8r0Xt0r7en-QVE-t5_XhLpOTItALWit5Qhp7gcptFFJMuCs62fpMMy - Go
syscall
パッケージの推奨事項: https://go.dev/blog/go1.4-syscall - Go
x/sys
パッケージ: https://pkg.go.dev/golang.org/x/sys