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

[インデックス 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つのファイルが追加されています。

  1. src/lib/syscall/mksignal: これはPerlで書かれたスクリプトです。このスクリプトの役割は、OSのシステムヘッダーファイル(例: /usr/include/sys/signal.h/usr/include/asm/signal.h)を解析し、そこから#defineで定義されているシグナル定数(SIGINT, SIGHUPなど)を抽出することです。抽出された定数は、Go言語のconstブロックとして整形され、signal_amd64_darwin.gosignal_amd64_linux.goのようなGoソースファイルとして出力されます。 この自動生成プロセスにより、手動での定数定義のミスを防ぎ、OSのヘッダーファイルが更新された際にも容易にGoのコードを同期させることが可能になります。スクリプトはSIGSTKSZSIGEV_で始まる定数をスキップするロジックを含んでおり、これはGoのsyscallパッケージで必要とされない、あるいは異なる方法で扱われる定数をフィルタリングするためと考えられます。

  2. src/lib/syscall/signal_amd64_darwin.go: このファイルは、mksignalスクリプトによって生成されるGoのソースファイルの一例です。Darwin(macOS)オペレーティングシステム上のamd64アーキテクチャ向けに、システムシグナルの定数を定義しています。例えば、SIGHUP = 1, SIGINT = 2といった形で、Goのsyscallパッケージ内で利用可能な定数としてエクスポートされます。これにより、GoプログラムはDarwin環境でこれらのシグナルを正しく識別し、処理できるようになります。

  3. src/lib/syscall/signal_amd64_linux.go: 同様に、このファイルはLinuxオペレーティングシステム上のamd64アーキテクチャ向けに、システムシグナルの定数を定義しています。LinuxとDarwinではシグナル番号が異なる場合があるため、それぞれのOSに特化したファイルが必要となります。例えば、SIGBUSSIGSYSなどの番号が異なることがあり、SIGIOTSIGSTKFLTなどLinux固有のシグナルも含まれています。

これらのファイルが追加されることで、Goのビルドシステムは、特定のOSとアーキテクチャ向けにコンパイルされる際に、適切なシグナル定数を持つsyscallパッケージを生成できるようになります。これにより、Goプログラムが異なる環境でシグナルを正しく処理し、安定して動作するための基盤が強化されます。

コアとなるコードの変更箇所

このコミットでは、以下の3つのファイルが新規追加されています。

  1. 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
    
  2. 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;
    )
    
  3. 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 syscallexport 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のSIGSTKFLTSIGLOST)があるため、それぞれのOS向けに個別のファイルが必要です。これにより、Goプログラムは実行される環境に応じて正しいシグナル番号を使用できます。

これらのファイルがsyscallパッケージに組み込まれることで、GoプログラムはOSの低レベルなシグナル処理を、Goの型安全な定数を通じて行うことができるようになります。これは、Goがシステムプログラミング言語として機能するための基本的な要素の一つです。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード(特にsrc/syscallディレクトリ)
  • Unix系OSのシグナルに関する一般的なドキュメント(例: man 7 signal
  • Perlスクリプトの基本的な構文と機能
  • Go言語の初期開発に関する歴史的情報(Goのブログやメーリングリストのアーカイブなど)
  • GitHubのコミット履歴とファイル変更履歴