Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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固有のバックログ値の抽象化」にあります。

  1. listenerBacklog の一元化:

    • 変更前は、src/pkg/net/ipsock_plan9.gosrc/pkg/net/sock_posix.go の両方で listenerBacklog 変数が個別に宣言されていました。これはコードの重複であり、将来的にバックログのデフォルト値を変更する際に複数のファイルを修正する必要があるという保守性の問題がありました。
    • このコミットでは、listenerBacklog の宣言を src/pkg/net/net.go に移動しました。net.gonet パッケージのコアとなる定義を含むファイルであり、ここに配置することで、listenerBacklog がパッケージ全体で共有される単一の真実のソース(Single Source of Truth)となります。
  2. maxListenerBacklog の導入とOS固有の抽象化:

    • listenerBacklog は、maxListenerBacklog() という関数呼び出しの結果で初期化されるようになりました。
    • Plan 9向け: 新しく作成された src/pkg/net/sock_plan9.go ファイルには、maxListenerBacklog() 関数が定義されています。この関数は、Plan 9のシステムヘッダー sys/socket.hSOMAXCONN を参照しつつも、固定値 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.gosock_posix.go)でそれぞれ宣言されていました。ipsock_plan9.go では直接 5 という値がハードコードされ、sock_posix.go では maxListenerBacklog() という関数によって値が取得されていました。このアプローチは、同じ論理的な意味を持つ変数が複数の場所に存在し、その初期化ロジックが分散しているという問題がありました。

このコミットでは、この問題を解決するために以下の変更が行われました。

  1. listenerBacklog の一元化: src/pkg/net/net.govar listenerBacklog = maxListenerBacklog() という形で宣言が移動されました。これにより、listenerBacklognet パッケージ全体で共有される単一の変数となり、その値は maxListenerBacklog() 関数によって決定されることが明確になりました。

  2. Plan 9 固有の maxListenerBacklog() の導入: 新しいファイル src/pkg/net/sock_plan9.go が追加され、Plan 9 環境に特化した maxListenerBacklog() 関数が定義されました。この関数は、Plan 9のシステムヘッダーで定義されている SOMAXCONN をコメントで参照しつつも、具体的なバックログ値として 5 を返します。これは、Plan 9のネットワークスタックの特性や、推奨されるバックログサイズが5であることを示唆しています。

  3. POSIX 固有の listenerBacklog 宣言の削除: src/pkg/net/sock_posix.go から listenerBacklog の宣言が削除されました。これにより、POSIXシステムでも net.go で宣言された一元化された listenerBacklog 変数が利用されるようになります。POSIX環境における maxListenerBacklog() の具体的な実装は、このコミットでは直接示されていませんが、Goのビルドシステムや他のファイルで提供されていると推測されます(例えば、syscall パッケージを通じて SOMAXCONN の実際の値を取得するような実装)。

この変更により、Goの net パッケージは、ネットワークリスナーのバックログサイズを決定するロジックをより整理し、OS間の差異を maxListenerBacklog() 関数内に抽象化することで、コードの保守性とクロスプラットフォーム対応を向上させています。

関連リンク

参考にした情報源リンク