[インデックス 18328] ファイルの概要
このコミットは、Go言語のsyscall
パッケージに、DragonFly BSDとOpenBSDという2つのオペレーティングシステム向けにTermios
構造体を追加するものです。これにより、GoプログラムがこれらのOS上でターミナル設定をより低レベルで操作できるようになります。
コミット
commit 15dcd671be2ea2c21bfdd27f031d5b40debdc73e
Author: Michael Gehring <mg@ebfe.org>
Date: Wed Jan 22 10:39:10 2014 -0800
syscall: add syscall.Termios on dragonfly, openbsd
R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/55720043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/15dcd671be2ea2c21bfdd27f031d5b40debdc73e
元コミット内容
syscall: add syscall.Termios on dragonfly, openbsd
このコミットは、Goのsyscall
パッケージに、DragonFly BSDとOpenBSD向けにTermios
構造体を追加します。
変更の背景
Go言語はクロスプラットフォーム対応を重視しており、様々なオペレーティングシステム上で動作するように設計されています。syscall
パッケージは、Goプログラムが基盤となるOSのシステムコールにアクセスするためのインターフェースを提供します。システムコールは、ファイル操作、プロセス管理、ネットワーク通信、そしてターミナル(端末)の制御など、OSの低レベルな機能を利用するために不可欠です。
termios
は、POSIX(Portable Operating System Interface)標準で定義されている、ターミナルI/O(入出力)設定を制御するための構造体と関連する関数群です。これには、入力モード(例:エコーの有無、正規化)、出力モード(例:改行コード変換)、制御文字(例:Ctrl+Cによる割り込み)、ボーレート(通信速度)など、ターミナルの挙動を細かく設定するための情報が含まれます。
Goのsyscall
パッケージが特定のOSのtermios
構造体をサポートしていない場合、そのOS上でGoプログラムからターミナルの低レベルな制御を行うことができませんでした。例えば、パスワード入力時に入力をエコーしないように設定したり、生のキー入力を取得したりするようなアプリケーションは、termios
構造体へのアクセスなしには実現が困難です。
このコミットの背景には、DragonFly BSDとOpenBSDという特定のBSD系OSにおいて、Goのsyscall
パッケージがtermios
構造体を提供していなかったという状況があります。これにより、これらのOS上で動作するGoプログラムが、ターミナル関連の高度な機能を必要とする場合に制約を受けていました。このコミットは、これらのOSにおけるGoのターミナル制御機能を補完し、より幅広いアプリケーションの実現を可能にすることを目的としています。
前提知識の解説
1. システムコール (System Call)
システムコールは、ユーザー空間で実行されるプログラムが、カーネル空間で実行されるオペレーティングシステム(OS)の機能を利用するためのインターフェースです。プログラムがファイルを開いたり、メモリを割り当てたり、ネットワーク通信を行ったりする際には、直接ハードウェアにアクセスするのではなく、OSが提供するシステムコールを介してこれらの操作を要求します。Go言語のsyscall
パッケージは、このシステムコールへのアクセスを抽象化し、GoプログラムからOSの低レベル機能を利用できるようにします。
2. POSIX (Portable Operating System Interface)
POSIXは、UNIX系オペレーティングシステムのAPIに関する標準規格群です。異なるUNIX系OS間でのソフトウェアの移植性を高めることを目的としています。termios
構造体と関連する関数は、このPOSIX標準の一部として定義されており、ターミナルI/Oの制御に関する共通のインターフェースを提供します。
3. Termios (Terminal I/O)
termios
は、ターミナル(端末)の入出力設定を管理するためのデータ構造です。C言語では通常、<termios.h>
ヘッダーファイルで定義されるstruct termios
として提供されます。この構造体には、以下のようなターミナル制御に関する様々なフラグや設定値が含まれます。
c_iflag
(Input flags): 入力処理に関するフラグ。例:IGNBRK
(ブレーク無視),ICRNL
(CRをNLに変換),ECHO
(入力エコー)。c_oflag
(Output flags): 出力処理に関するフラグ。例:OPOST
(出力後処理有効),ONLCR
(NLをCR-NLに変換)。c_cflag
(Control flags): 制御モードに関するフラグ。例:CS8
(8ビット文字),CSTOPB
(2ストップビット),B9600
(ボーレート)。c_lflag
(Local flags): ローカルモードに関するフラグ。例:ICANON
(カノニカルモード),ISIG
(シグナル生成有効),NOFLSH
(フラッシュ無効)。c_cc
(Control characters): 制御文字の配列。例:VMIN
(読み込み最小文字数),VTIME
(読み込みタイムアウト),VINTR
(割り込み文字)。
これらの設定を変更することで、ターミナルの挙動を、例えば「入力された文字を画面に表示しない(パスワード入力時)」、「Enterキーが押されるまで入力をバッファリングしない(ゲームのリアルタイム入力)」、「特定のキー入力でプログラムを終了させる」といったようにカスタマイズできます。
4. DragonFly BSD と OpenBSD
これらは、BSD(Berkeley Software Distribution)系のオープンソースUNIXライクなオペレーティングシステムです。
- DragonFly BSD: FreeBSD 4.xからフォークして開発されたOSで、特にスケーラビリティとパフォーマンスに焦点を当てています。
- OpenBSD: セキュリティを最優先事項として開発されているOSで、コードの監査と堅牢性に非常に力を入れています。
Go言語は、これらのOSを含む多くのプラットフォームをサポートしており、それぞれのOSの特性に合わせたシステムコールインターフェースを提供する必要があります。
技術的詳細
このコミットの主要な目的は、Goのsyscall
パッケージがDragonFly BSDとOpenBSD上でtermios
構造体を認識し、利用できるようにすることです。Goのsyscall
パッケージは、C言語のシステムコールをGoの型にマッピングすることで、GoプログラムからOSの機能にアクセスできるようにしています。
具体的には、以下の2種類のファイルが変更されています。
-
types_*.go
ファイル: これらのファイル(例:src/pkg/syscall/types_dragonfly.go
,src/pkg/syscall/types_openbsd.go
)は、Goのsyscall
パッケージがC言語のヘッダーファイルから型定義をインポートするために使用されます。このコミットでは、#include <termios.h>
が追加され、C言語のstruct termios
がGoのTermios
型としてエクスポートされるように定義されています。これは、GoプログラムがC言語のtermios
構造体に対応するGoの型を認識できるようにするための第一歩です。// src/pkg/syscall/types_dragonfly.go および src/pkg/syscall/types_openbsd.go に追加 #include <termios.h> // termios.h ヘッダーをインクルード // ... 既存の型定義 ... // Terminal handling type Termios C.struct_termios // C言語の struct termios を Go の Termios 型として定義
C.struct_termios
は、Goのcgo
ツールがC言語の構造体をGoの型として扱うための構文です。 -
ztypes_*.go
ファイル: これらのファイル(例:src/pkg/syscall/ztypes_dragonfly_386.go
,src/pkg/syscall/ztypes_openbsd_amd64.go
など)は、Goのビルドプロセス中に自動生成されるファイルで、特定のアーキテクチャ(例:386
、amd64
)とOS(例:dragonfly
、openbsd
)に対応するシステムコールの型定義を含んでいます。このコミットでは、これらのファイルにGoのTermios
構造体の具体的なフィールド定義が追加されています。// src/pkg/syscall/ztypes_dragonfly_386.go などに Termios 構造体の定義を追加 type Termios struct { Iflag uint32 Oflag uint32 Cflag uint32 Lflag uint32 Cc [20]uint8 // 制御文字の配列 Ispeed uint32 // 入力ボーレート Ospeed uint32 // 出力ボーレート }
これらのフィールドは、C言語の
struct termios
の対応するフィールドと一致するように定義されており、Goプログラムがこれらのフィールドにアクセスしてターミナル設定を読み書きできるようにします。uint32
やint32
といった型は、OSのシステムコールが期待するデータ型に合わせられています。Cc
フィールドは、VMIN
やVTIME
などの制御文字を格納するための配列です。
この変更により、Go開発者はDragonFly BSDやOpenBSD上で、syscall.Termios
型を使用してターミナルの低レベルな設定をプログラムから直接操作できるようになります。例えば、syscall.Tcgetattr
やsyscall.Tcsetattr
といったシステムコール(これらはこのコミットでは直接追加されていませんが、Termios
構造体が存在することで利用可能になります)を介して、ターミナルのモードを変更したり、ボーレートを設定したりすることが可能になります。
コアとなるコードの変更箇所
このコミットでは、以下の6つのファイルが変更されています。
src/pkg/syscall/types_dragonfly.go
src/pkg/syscall/types_openbsd.go
src/pkg/syscall/ztypes_dragonfly_386.go
src/pkg/syscall/ztypes_dragonfly_amd64.go
src/pkg/syscall/ztypes_openbsd_386.go
src/pkg/syscall/ztypes_openbsd_amd64.go
それぞれのファイルで、termios.h
のインクルードと、Termios
構造体の定義が追加されています。
src/pkg/syscall/types_dragonfly.go
および src/pkg/syscall/types_openbsd.go
の変更
--- a/src/pkg/syscall/types_dragonfly.go
+++ b/src/pkg/syscall/types_dragonfly.go
@@ -18,6 +18,7 @@ package syscall
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
+#include <termios.h> // この行が追加
#include <stdio.h>
#include <unistd.h>
#include <sys/event.h>
@@ -239,3 +240,7 @@ type BpfProgram C.struct_bpf_program
type BpfInsn C.struct_bpf_insn
type BpfHdr C.struct_bpf_hdr
+
+// Terminal handling
+
+type Termios C.struct_termios // この型定義が追加
types_openbsd.go
も同様の変更です。
src/pkg/syscall/ztypes_dragonfly_386.go
および src/pkg/syscall/ztypes_dragonfly_amd64.go
の変更
--- a/src/pkg/syscall/ztypes_dragonfly_386.go
+++ b/src/pkg/syscall/ztypes_dragonfly_386.go
@@ -427,3 +427,13 @@ type BpfHdr struct {
Hdrlen uint16
Pad_cgo_0 [2]byte
}
+
+type Termios struct { // この構造体定義が追加
+ Iflag uint32
+ Oflag uint32
+ Cflag uint32
+ Lflag uint32
+ Cc [20]uint8
+ Ispeed uint32
+ Ospeed uint32
+}
ztypes_dragonfly_amd64.go
も同様の変更です。
src/pkg/syscall/ztypes_openbsd_386.go
および src/pkg/syscall/ztypes_openbsd_amd64.go
の変更
--- a/src/pkg/syscall/ztypes_openbsd_386.go
+++ b/src/pkg/syscall/ztypes_openbsd_386.go
@@ -427,3 +427,13 @@ type BpfTimeval struct {
Sec uint32
Usec uint32
}
+
+type Termios struct { // この構造体定義が追加
+ Iflag uint32
+ Oflag uint32
+ Cflag uint32
+ Lflag uint32
+ Cc [20]uint8
+ Ispeed int32 // OpenBSDではIspeedとOspeedがint32
+ Ospeed int32
+}
ztypes_openbsd_amd64.go
も同様の変更です。OpenBSDのTermios
構造体では、Ispeed
とOspeed
の型がint32
である点に注意が必要です。これはOSごとのtermios
構造体の定義の違いを反映しています。
コアとなるコードの解説
このコミットのコアとなる変更は、Goのsyscall
パッケージが、DragonFly BSDとOpenBSDのネイティブなtermios
構造体をGoの型システムにマッピングすることです。
-
#include <termios.h>
の追加:types_dragonfly.go
とtypes_openbsd.go
にこの行が追加されたことで、Goのcgo
ツールがコンパイル時にC言語のtermios.h
ヘッダーファイルを参照できるようになります。これにより、C言語で定義されているstruct termios
のレイアウトやフィールド情報をGoの型システムに取り込む準備が整います。 -
type Termios C.struct_termios
の定義: 同じくtypes_*.go
ファイルで、Termios
というGoの型がC言語のstruct termios
にエイリアスとして定義されています。これは、Goプログラムがsyscall.Termios
という型名で、基盤となるOSのtermios
構造体を扱うことを可能にします。この行自体はGoの型定義ですが、cgo
によってC言語の構造体とGoの構造体の間のマッピングが確立されます。 -
ztypes_*.go
におけるTermios
構造体の具体的な定義:ztypes_*.go
ファイル群は、Goのビルドシステムによって自動生成されるファイルであり、特定のOSとアーキテクチャにおけるシステムコールの型定義をGoのコードとして具体的に記述しています。このコミットで追加されたTermios
構造体の定義は、C言語のstruct termios
のメモリレイアウトとフィールドをGoの型で正確に再現したものです。Iflag
,Oflag
,Cflag
,Lflag
: これらはそれぞれ、入力、出力、制御、ローカルの各モードに関するフラグを保持するフィールドです。通常、ビットマスクとして使用され、ターミナルの挙動を細かく設定します。Cc
: これは制御文字の配列です。例えば、VMIN
(読み込み最小文字数)やVTIME
(読み込みタイムアウト)などの特殊な文字コードがここに格納されます。配列のサイズ([20]uint8
)は、OSのtermios
構造体におけるc_cc
配列のサイズに依存します。Ispeed
,Ospeed
: これらはそれぞれ、入力と出力のボーレート(通信速度)を保持するフィールドです。
これらのフィールドの型(
uint32
やint32
)は、対応するOSのC言語のstruct termios
におけるフィールドの型とサイズに厳密に合わせられています。これにより、Goプログラムがsyscall.Termios
構造体を操作する際に、OSのシステムコールが期待する正しいデータ形式で値を渡したり受け取ったりすることが保証されます。
この変更により、Goのsyscall
パッケージは、DragonFly BSDとOpenBSD上でターミナル制御を行うための基盤を提供します。例えば、Goの標準ライブラリのgolang.org/x/term
パッケージのような高レベルなターミナル操作ライブラリは、内部でこのsyscall.Termios
構造体を利用して、クロスプラットフォームなターミナル制御機能を提供できるようになります。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall - POSIX
termios
に関する情報 (例: manページ):man 3 termios
(UNIX系システムで実行) - Go言語の
x/term
パッケージ: https://pkg.go.dev/golang.org/x/term (このコミットで追加された低レベルAPIの上に構築される高レベルAPIの例)
参考にした情報源リンク
- Go言語のソースコード (特に
src/pkg/syscall
ディレクトリ) - POSIX標準のドキュメント (IEEE Std 1003.1)
- DragonFly BSDおよびOpenBSDのシステムプログラミングに関するドキュメント
man termios
(Linux/BSDシステムでのtermios
に関するマニュアルページ)- Goの
cgo
に関するドキュメント: https://go.dev/blog/cgoI have generated the detailed explanation of the commit as requested, following all the specified instructions and chapter structure. The output is in Markdown format and is printed to standard output. I have used the commit data and general knowledge abouttermios
,syscall
, and the mentioned operating systems to provide a comprehensive explanation. I did not need to perform additional web searches beyond my initial understanding, as the provided commit diff and my existing knowledge were sufficient to explain the technical details.