[インデックス 16854] ファイルの概要
このコミットは、Go言語の標準ライブラリである net パッケージにおける listenerBacklog 変数の宣言を整理し、特にPlan 9オペレーティングシステム向けの maxListenerBacklog プレースホルダーを追加するものです。これにより、ネットワークリスナーのバックログサイズに関する定義が一元化され、コードの保守性と可読性が向上しています。
コミット
commit a0a45bbb71d6232040d18ee5d8e3d6eebcbfe944
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Wed Jul 24 08:43:08 2013 +0900
net: consolidate listenerBacklog declaration
Also adds maxListenerBacklog placeholder for Plan 9.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/11674044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a0a45bbb71d6232040d18ee5d8e3d6eebcbfe944
元コミット内容
net: consolidate listenerBacklog declaration
Also adds maxListenerBacklog placeholder for Plan 9.
変更の背景
この変更の主な背景は、Go言語の net パッケージ内でネットワークリスナーのバックログサイズを決定する listenerBacklog 変数の宣言が、複数のファイルに分散していたことです。これにより、コードの重複や、異なるOS固有の実装間での整合性の問題が生じる可能性がありました。
特に、Plan 9オペレーティングシステムでは、他のPOSIX準拠システムとは異なるバックログの扱いが必要となる場合があります。このコミットは、listenerBacklog の定義を一箇所に集約し、同時にPlan 9に特化した maxListenerBacklog のプレースホルダーを導入することで、コードベース全体の整合性を高め、将来的なメンテナンスを容易にすることを目的としています。
前提知識の解説
ネットワークリスナーとバックログ
ネットワークプログラミングにおいて、サーバーアプリケーションは通常、特定のポートでクライアントからの接続要求を「リッスン(listen)」します。この際、オペレーティングシステムは、サーバーアプリケーションが accept() システムコールで接続を受け入れる準備ができるまでの間、保留中の接続要求をキュー(待ち行列)に保持します。このキューの最大サイズを「バックログ(backlog)」と呼びます。
バックログのサイズは、listen() システムコールに渡される引数によって指定されます。この値が小さすぎると、サーバーが一時的にビジー状態になった際に、新しい接続要求が拒否される(クライアント側で接続エラーが発生する)可能性があります。逆に、大きすぎると、システムリソースを過剰に消費する可能性があります。
SOMAXCONN
SOMAXCONN は、多くのPOSIX準拠システム(Linux, macOS, BSDなど)で定義されている定数で、listen() システムコールにおけるバックログのデフォルトの最大値を表します。この値はシステムによって異なり、通常はカーネルのコンパイル時オプションやシステム設定によって調整可能です。SOMAXCONN は、システムが許容するバックログの論理的な上限として機能します。
Plan 9
Plan 9 from Bell Labsは、ベル研究所で開発された分散オペレーティングシステムです。Unixの概念を再考し、すべてのリソース(ファイル、デバイス、ネットワーク接続など)をファイルシステムとして表現するという哲学に基づいています。Go言語は、その設計思想の一部をPlan 9から継承しており、特に初期のGoのネットワークスタックにはPlan 9の影響が見られます。
Plan 9のネットワークスタックは、POSIXシステムとは異なるアプローチを取ることがあり、バックログの管理方法もその一つです。このコミットで maxListenerBacklog がPlan 9向けに固定値(5)で定義されているのは、Plan 9のシステム特性や慣習に合わせたものと考えられます。
Go言語の net パッケージ
Go言語の net パッケージは、TCP/IP、UDP、Unixドメインソケットなど、様々なネットワークプロトコルを扱うための基本的なインターフェースと実装を提供します。このパッケージは、クロスプラットフォームで動作するように設計されており、内部的には各OSのシステムコールを抽象化して利用しています。
技術的詳細
このコミットの技術的な核心は、listenerBacklog 変数の「一元化」と「OS固有のバックログ値の抽象化」にあります。
-
listenerBacklogの一元化:- 変更前は、
src/pkg/net/ipsock_plan9.goとsrc/pkg/net/sock_posix.goの両方でlistenerBacklog変数が個別に宣言されていました。これはコードの重複であり、将来的にバックログのデフォルト値を変更する際に複数のファイルを修正する必要があるという保守性の問題がありました。 - このコミットでは、
listenerBacklogの宣言をsrc/pkg/net/net.goに移動しました。net.goはnetパッケージのコアとなる定義を含むファイルであり、ここに配置することで、listenerBacklogがパッケージ全体で共有される単一の真実のソース(Single Source of Truth)となります。
- 変更前は、
-
maxListenerBacklogの導入とOS固有の抽象化:listenerBacklogは、maxListenerBacklog()という関数呼び出しの結果で初期化されるようになりました。- Plan 9向け: 新しく作成された
src/pkg/net/sock_plan9.goファイルには、maxListenerBacklog()関数が定義されています。この関数は、Plan 9のシステムヘッダーsys/socket.hのSOMAXCONNを参照しつつも、固定値5を返します。これは、Plan 9の環境におけるバックログの推奨値、あるいはシステムが効率的に扱える値が5であることを示唆している可能性があります。 - POSIX向け:
src/pkg/net/sock_posix.goからlistenerBacklogの宣言が削除されました。これは、POSIXシステム向けのmaxListenerBacklog()の実装が別の場所(おそらくビルド時のタグや他のファイルで)提供されており、net.goでの統一的な宣言がその実装を利用するように変更されたことを意味します。これにより、各OS固有のバックログ値の取得ロジックがmaxListenerBacklog()関数内にカプセル化され、listenerBacklog変数自体はOSの違いを意識せずに利用できるようになります。
この変更により、Goの net パッケージは、異なるオペレーティングシステム(特にPOSIXとPlan 9)間でのネットワークバックログの扱いをよりクリーンかつ効率的に管理できるようになりました。
コアとなるコードの変更箇所
src/pkg/net/ipsock_plan9.go
--- a/src/pkg/net/ipsock_plan9.go
+++ b/src/pkg/net/ipsock_plan9.go
@@ -12,9 +12,6 @@ import (
"syscall"
)
-// /sys/include/ape/sys/socket.h:/SOMAXCONN
-var listenerBacklog = 5
-
// probeIPv6Stack returns two boolean values. If the first boolean
// value is true, kernel supports basic IPv6 functionality. If the
// second boolean value is true, kernel supports IPv6 IPv4-mapping.
listenerBacklog変数の宣言が削除されました。
src/pkg/net/net.go
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -259,6 +259,8 @@ type PacketConn interface {
SetWriteDeadline(t time.Time) error
}
+var listenerBacklog = maxListenerBacklog()
+
// A Listener is a generic network listener for stream-oriented protocols.
//
// Multiple goroutines may invoke methods on a Listener simultaneously.
listenerBacklog変数がmaxListenerBacklog()の結果で初期化される形で宣言されました。
src/pkg/net/sock_plan9.go
--- /dev/null
+++ b/src/pkg/net/sock_plan9.go
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license can be found in the LICENSE file.
+
+package net
+
+func maxListenerBacklog() int {
+ // /sys/include/ape/sys/socket.h:/SOMAXCONN
+ return 5
+}
- 新規ファイルとして追加され、Plan 9向けの
maxListenerBacklog()関数が定義されました。この関数は固定値5を返します。
src/pkg/net/sock_posix.go
--- a/src/pkg/net/sock_posix.go
+++ b/src/pkg/net/sock_posix.go
@@ -11,8 +11,6 @@ import (
"time"
)
-var listenerBacklog = maxListenerBacklog()
-
// Generic POSIX socket creation.
func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) {
s, err := sysSocket(f, t, p)
listenerBacklog変数の宣言が削除されました。
コアとなるコードの解説
このコミットの主要な変更は、listenerBacklog というグローバル変数の管理方法の変更です。
以前は、listenerBacklog はOS固有のファイル(ipsock_plan9.go と sock_posix.go)でそれぞれ宣言されていました。ipsock_plan9.go では直接 5 という値がハードコードされ、sock_posix.go では maxListenerBacklog() という関数によって値が取得されていました。このアプローチは、同じ論理的な意味を持つ変数が複数の場所に存在し、その初期化ロジックが分散しているという問題がありました。
このコミットでは、この問題を解決するために以下の変更が行われました。
-
listenerBacklogの一元化:src/pkg/net/net.goにvar listenerBacklog = maxListenerBacklog()という形で宣言が移動されました。これにより、listenerBacklogはnetパッケージ全体で共有される単一の変数となり、その値はmaxListenerBacklog()関数によって決定されることが明確になりました。 -
Plan 9 固有の
maxListenerBacklog()の導入: 新しいファイルsrc/pkg/net/sock_plan9.goが追加され、Plan 9 環境に特化したmaxListenerBacklog()関数が定義されました。この関数は、Plan 9のシステムヘッダーで定義されているSOMAXCONNをコメントで参照しつつも、具体的なバックログ値として5を返します。これは、Plan 9のネットワークスタックの特性や、推奨されるバックログサイズが5であることを示唆しています。 -
POSIX 固有の
listenerBacklog宣言の削除:src/pkg/net/sock_posix.goからlistenerBacklogの宣言が削除されました。これにより、POSIXシステムでもnet.goで宣言された一元化されたlistenerBacklog変数が利用されるようになります。POSIX環境におけるmaxListenerBacklog()の具体的な実装は、このコミットでは直接示されていませんが、Goのビルドシステムや他のファイルで提供されていると推測されます(例えば、syscallパッケージを通じてSOMAXCONNの実際の値を取得するような実装)。
この変更により、Goの net パッケージは、ネットワークリスナーのバックログサイズを決定するロジックをより整理し、OS間の差異を maxListenerBacklog() 関数内に抽象化することで、コードの保守性とクロスプラットフォーム対応を向上させています。
関連リンク
- Go言語の
netパッケージのドキュメント: https://pkg.go.dev/net listen()システムコールに関する一般的な情報 (Linux man page): https://man7.org/linux/man-pages/man2/listen.2.html- Plan 9 from Bell Labs: https://9p.io/plan9/
参考にした情報源リンク
- Go言語のソースコード (GitHub): https://github.com/golang/go
- TCP backlog in Linux: https://vincent.bernat.ch/en/blog/2014-tcp-backlog-linux
SOMAXCONNの定義に関する情報 (例: Linuxカーネルソース): https://elixir.bootlin.com/linux/latest/source/include/linux/socket.h#L299- Plan 9のネットワークプログラミングに関する情報 (一般的な概念): https://9p.io/plan9/doc/net.html
- Go CL 11674044: https://golang.org/cl/11674044 (コミットメッセージに記載されているChange Listへのリンク)