[インデックス 1276] ファイルの概要
このコミットは、Go言語の初期開発段階におけるビルド修正に関するものです。具体的には、syscall
パッケージ内で使用されるシグナル定義に関連するファイルが以前のコミットで漏れていたため、ビルドが失敗していた問題を解決します。
コミット
commit 3e8faa640fa49f432060097e8dabbf8e4ecc2ef9
Author: Russ Cox <rsc@golang.org>
Date: Thu Dec 4 10:18:53 2008 -0800
fix build - forgot these files
TBR=r
OCL=20448
CL=20448
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/3e8faa640fa49f432060097e8dabbf8e4ecc2ef9
元コミット内容
fix build - forgot these files
TBR=r
OCL=20448
CL=20448
変更の背景
このコミットは、Go言語のビルドプロセスにおいて、以前の変更で必要なファイルがコミットされずに漏れてしまったことによるビルドエラーを修正するために行われました。具体的には、syscall
パッケージがシステムシグナルを扱うために必要な定数定義ファイルが不足しており、これがビルドの失敗を引き起こしていました。この修正は、Go言語が様々なオペレーティングシステム(この場合はDarwinとLinux)とアーキテクチャ(amd64)で正しく動作するための基盤を確立する上で不可欠なステップでした。
前提知識の解説
Go言語の初期開発
このコミットは2008年12月に行われており、Go言語が一般に公開される前の非常に初期の段階に当たります。この時期は、言語の基本的な構造、標準ライブラリ、およびビルドシステムが活発に開発・整備されていた時期です。そのため、このような「ファイルの忘れ」によるビルドエラーは、開発プロセスにおいて頻繁に発生しうる典型的な問題でした。
syscall
パッケージ
syscall
パッケージは、Goプログラムがオペレーティングシステムの低レベルな機能(システムコール)にアクセスするためのインターフェースを提供します。これには、ファイル操作、プロセス管理、ネットワーク通信、そしてシグナル処理などが含まれます。Go言語がクロスプラットフォームで動作するためには、各OSのシステムコールや定数の違いを吸収し、Goの統一されたインターフェースを通じてアクセスできるようにする必要があります。
シグナル (Signal)
シグナルは、Unix系オペレーティングシステムにおいて、プロセスに対して非同期的にイベントを通知するメカニズムです。例えば、Ctrl+Cを押すとSIGINT
シグナルがプロセスに送られ、プロセスは通常終了します。その他にも、プログラムのエラー(SIGSEGV
:セグメンテーション違反、SIGFPE
:浮動小数点例外)、タイマーイベント(SIGALRM
)、子プロセスの状態変化(SIGCHLD
)など、様々な目的でシグナルが使用されます。各シグナルには一意の番号と名前が割り当てられていますが、その番号はOSによって異なる場合があります。
mksignal
スクリプト
mksignal
は、このコミットで追加されたPerlスクリプトです。その目的は、特定のOSのヘッダーファイル(例: /usr/include/sys/signal.h
)を読み込み、そこからシグナル定数(SIGINT
, SIGHUP
など)を抽出し、Go言語のソースコードとして出力することです。これにより、手動でシグナル定数を定義する手間を省き、OSのヘッダーファイルとの同期を保つことができます。これは、異なるOS間でシグナル番号が異なるという問題を自動的に解決するための一般的なアプローチです。
技術的詳細
このコミットの技術的な核心は、Go言語のsyscall
パッケージが、各オペレーティングシステム(OS)およびアーキテクチャ(CPU)に特化したシグナル定数をどのように扱うかという点にあります。
Go言語はクロスプラットフォームを強く意識して設計されており、異なるOSやCPUアーキテクチャ上で同じGoのコードが動作するように抽象化されています。しかし、低レベルなシステムコールやOS固有の定数(シグナル番号など)は、OSやアーキテクチャによって異なるため、これらをGoのコードベースに適切に組み込む必要があります。
このコミットでは、以下の3つのファイルが追加されています。
-
src/lib/syscall/mksignal
: これはPerlで書かれたスクリプトです。このスクリプトの役割は、OSのシステムヘッダーファイル(例:/usr/include/sys/signal.h
や/usr/include/asm/signal.h
)を解析し、そこから#define
で定義されているシグナル定数(SIGINT
,SIGHUP
など)を抽出することです。抽出された定数は、Go言語のconst
ブロックとして整形され、signal_amd64_darwin.go
やsignal_amd64_linux.go
のようなGoソースファイルとして出力されます。 この自動生成プロセスにより、手動での定数定義のミスを防ぎ、OSのヘッダーファイルが更新された際にも容易にGoのコードを同期させることが可能になります。スクリプトはSIGSTKSZ
やSIGEV_
で始まる定数をスキップするロジックを含んでおり、これはGoのsyscall
パッケージで必要とされない、あるいは異なる方法で扱われる定数をフィルタリングするためと考えられます。 -
src/lib/syscall/signal_amd64_darwin.go
: このファイルは、mksignal
スクリプトによって生成されるGoのソースファイルの一例です。Darwin(macOS)オペレーティングシステム上のamd64アーキテクチャ向けに、システムシグナルの定数を定義しています。例えば、SIGHUP = 1
,SIGINT = 2
といった形で、Goのsyscall
パッケージ内で利用可能な定数としてエクスポートされます。これにより、GoプログラムはDarwin環境でこれらのシグナルを正しく識別し、処理できるようになります。 -
src/lib/syscall/signal_amd64_linux.go
: 同様に、このファイルはLinuxオペレーティングシステム上のamd64アーキテクチャ向けに、システムシグナルの定数を定義しています。LinuxとDarwinではシグナル番号が異なる場合があるため、それぞれのOSに特化したファイルが必要となります。例えば、SIGBUS
やSIGSYS
などの番号が異なることがあり、SIGIOT
やSIGSTKFLT
などLinux固有のシグナルも含まれています。
これらのファイルが追加されることで、Goのビルドシステムは、特定のOSとアーキテクチャ向けにコンパイルされる際に、適切なシグナル定数を持つsyscall
パッケージを生成できるようになります。これにより、Goプログラムが異なる環境でシグナルを正しく処理し、安定して動作するための基盤が強化されます。
コアとなるコードの変更箇所
このコミットでは、以下の3つのファイルが新規追加されています。
-
src/lib/syscall/mksignal
(新規ファイル, 26行追加) Perlスクリプト。OSのシグナルヘッダーファイルからGoのシグナル定数ファイルを生成する。# Copyright 2009 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. my $command = "mksignal ". join(' ', @ARGV); print <<EOF; // Generated by mksignal; DO NOT EDIT. // $command package syscall export const( EOF while(<>){ next if /SIGSTKSZ/; next if /SIGEV_/; if(/^#define\s+(SIG[^_\s]\w*)\s+([0-9]+)/){ print "\t$1 = $2;\\n"; } } print <<EOF; ) EOF
-
src/lib/syscall/signal_amd64_darwin.go
(新規ファイル, 43行追加) Darwin (macOS) amd64アーキテクチャ向けのシグナル定数定義。mksignal
によって生成される。// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Generated by mksignal; DO NOT EDIT. // mksignal /usr/include/sys/signal.h package syscall export const( SIGHUP = 1; SIGINT = 2; SIGQUIT = 3; SIGILL = 4; SIGTRAP = 5; SIGABRT = 6; SIGPOLL = 7; SIGEMT = 7; SIGFPE = 8; SIGKILL = 9; SIGBUS = 10; SIGSEGV = 11; SIGSYS = 12; SIGPIPE = 13; SIGALRM = 14; SIGTERM = 15; SIGURG = 16; SIGSTOP = 17; SIGTSTP = 18; SIGCONT = 19; SIGCHLD = 20; SIGTTIN = 21; SIGTTOU = 22; SIGIO = 23; SIGXCPU = 24; SIGXFSZ = 25; SIGVTALRM = 26; SIGPROF = 27; SIGWINCH = 28; SIGINFO = 29; SIGUSR1 = 30; SIGUSR2 = 31; )
-
src/lib/syscall/signal_amd64_linux.go
(新規ファイル, 46行追加) Linux amd64アーキテクチャ向けのシグナル定数定義。mksignal
によって生成される。// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Generated by mksignal; DO NOT EDIT. // mksignal /usr/include/asm/signal.h package syscall export const( SIGHUP = 1; SIGINT = 2; SIGQUIT = 3; SIGILL = 4; SIGTRAP = 5; SIGABRT = 6; SIGIOT = 6; SIGBUS = 7; SIGFPE = 8; SIGKILL = 9; SIGUSR1 = 10; SIGSEGV = 11; SIGUSR2 = 12; SIGPIPE = 13; SIGALRM = 14; SIGTERM = 15; SIGSTKFLT = 16; SIGCHLD = 17; SIGCONT = 18; SIGSTOP = 19; SIGTSTP = 20; SIGTTIN = 21; SIGTTOU = 22; SIGURG = 23; SIGXCPU = 24; SIGXFSZ = 25; SIGVTALRM = 26; SIGPROF = 27; SIGWINCH = 28; SIGIO = 29; SIGLOST = 29; SIGPWR = 30; SIGSYS = 31; SIGUNUSED = 31; SIGRTMIN = 32; )
コアとなるコードの解説
src/lib/syscall/mksignal
このPerlスクリプトは、Go言語のクロスプラットフォーム対応における重要な自動化ツールです。OSごとに異なるシグナル定数を手動で管理するのではなく、既存のシステムヘッダーファイルから自動的に抽出してGoのコードを生成することで、開発の手間を省き、エラーのリスクを低減します。
スクリプトの主要なロジックは以下の通りです。
- ヘッダーコメントの生成: 生成されたファイルが自動生成であることを示すコメントと、生成に使用されたコマンドライン引数を記録します。
- パッケージ宣言と
const
ブロックの開始:package syscall
とexport const(
を出力し、Goの定数定義の構造を準備します。 - 入力ファイルの解析: 標準入力から行を読み込みます。これは通常、
mksignal /usr/include/sys/signal.h
のように、OSのシグナルヘッダーファイルの内容がパイプで渡されることを想定しています。 - フィルタリング:
next if /SIGSTKSZ/
:SIGSTKSZ
というシグナル定数をスキップします。これはGoのsyscall
パッケージでは直接必要とされないか、異なる方法で扱われるためと考えられます。next if /SIGEV_/
:SIGEV_
で始まるシグナル定数(例:SIGEV_NONE
,SIGEV_SIGNAL
など)をスキップします。これらは通常、sigevent
構造体に関連するもので、Goのシグナル処理の文脈では直接定数としてエクスポートする必要がない場合があります。
- 定数の抽出と出力:
if(/^#define\s+(SIG[^_\s]\w*)\s+([0-9]+)/)
:#define
で始まり、SIG
で始まるシグナル名とそれに続く数値(シグナル番号)を正規表現でマッチさせます。print "\t$1 = $2;\\n"
: マッチしたシグナル名と番号をGoの定数定義形式(例:SIGHUP = 1;
)で出力します。
const
ブロックの終了:)
とEOF
を出力し、Goの定数定義を閉じます。
このスクリプトは、Go言語のビルドシステムの一部として実行され、各ターゲットOS/アーキテクチャ向けのシグナル定数ファイルを生成する役割を担っています。
src/lib/syscall/signal_amd64_darwin.go
および src/lib/syscall/signal_amd64_linux.go
これらのファイルは、mksignal
スクリプトによって生成されるGoのソースコードです。それぞれのファイルは、特定のOS(DarwinまたはLinux)とアーキテクチャ(amd64)におけるシステムシグナルの定数を定義しています。
- ヘッダーコメント: 自動生成されたファイルであることを明示し、生成に使用された
mksignal
コマンドを記録しています。 - パッケージ宣言:
package syscall
と宣言されており、これらの定数がsyscall
パッケージの一部であることを示します。 export const(...)
ブロック: Goのconst
ブロック内で、各シグナル名に対応する整数値が定義されています。例えば、SIGHUP = 1;
は、SIGHUP
という定数が整数値1
を持つことを意味します。- OSごとの差異: DarwinとLinuxでは、同じシグナル名でも異なる番号が割り当てられている場合や、片方のOSにしか存在しないシグナル(例: Linuxの
SIGSTKFLT
やSIGLOST
)があるため、それぞれのOS向けに個別のファイルが必要です。これにより、Goプログラムは実行される環境に応じて正しいシグナル番号を使用できます。
これらのファイルがsyscall
パッケージに組み込まれることで、GoプログラムはOSの低レベルなシグナル処理を、Goの型安全な定数を通じて行うことができるようになります。これは、Goがシステムプログラミング言語として機能するための基本的な要素の一つです。
関連リンク
- Go言語の公式GitHubリポジトリ: https://github.com/golang/go
- Go言語の
syscall
パッケージに関するドキュメント(現在のバージョン): https://pkg.go.dev/syscall
参考にした情報源リンク
- Go言語のソースコード(特に
src/syscall
ディレクトリ) - Unix系OSのシグナルに関する一般的なドキュメント(例:
man 7 signal
) - Perlスクリプトの基本的な構文と機能
- Go言語の初期開発に関する歴史的情報(Goのブログやメーリングリストのアーカイブなど)
- GitHubのコミット履歴とファイル変更履歴