[インデックス 18232] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにFreeBSDシステム(386およびamd64アーキテクチャ)向けのTermios
構造体を追加するものです。これにより、GoプログラムからFreeBSDのターミナルI/O制御機能にアクセスできるようになります。
コミット
commit 5ce3e6a1efd834189057002e6b28180dee5657d4
Author: Michael Gehring <mg@ebfe.org>
Date: Mon Jan 13 13:57:38 2014 -0800
syscall: add syscall.Termios on freebsd/{386,amd64}
R=golang-codereviews, bradfitz, mg
CC=golang-codereviews
https://golang.org/cl/51580044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5ce3e6a1efd834189057002e6b28180dee5657d4
元コミット内容
syscall: add syscall.Termios on freebsd/{386,amd64}
このコミットは、FreeBSDの32ビット(386)および64ビット(amd64)アーキテクチャにおいて、syscall
パッケージにTermios
構造体を追加します。
変更の背景
Go言語のsyscall
パッケージは、オペレーティングシステムが提供する低レベルのシステムコールへのインターフェースを提供します。これにより、GoプログラムはOSのカーネル機能に直接アクセスできます。ターミナル(TTY)のI/O制御は、プログラムがユーザーとの対話において、入力のエコー、行バッファリング、特殊文字の処理などを細かく制御するために不可欠な機能です。
FreeBSDを含む多くのUnix系システムでは、ターミナル設定はtermios
構造体と関連する関数(tcgetattr
, tcsetattr
など)を通じて行われます。GoプログラムがこれらのOSレベルのターミナル制御機能を利用するためには、Goの型システムに対応するtermios
構造体の定義が必要でした。このコミットは、FreeBSD環境でGoプログラムがターミナル設定を操作できるように、この重要な構造体をsyscall
パッケージに追加することを目的としています。
前提知識の解説
システムコール (System Call)
システムコールは、ユーザー空間で実行されるプログラムが、カーネル空間で提供されるサービス(ファイルI/O、プロセス管理、メモリ管理、ネットワーク通信など)を要求するためのインターフェースです。Goのsyscall
パッケージは、これらのOS固有のシステムコールをGoの関数としてラップし、Goプログラムから安全かつ効率的に呼び出せるようにします。
ターミナルI/O制御 (Terminal I/O Control)
ターミナルI/O制御は、シリアルポートや仮想ターミナルデバイスを介したデータの送受信方法を管理するメカニズムです。これには以下のような設定が含まれます。
- 入力モード (Input Modes): 入力文字の処理方法(例: エコーの有無、行バッファリングの有無、特殊文字の解釈)。
- 出力モード (Output Modes): 出力文字の処理方法(例: 改行コードの変換)。
- 制御モード (Control Modes): ハードウェア制御(例: ボーレート、データビット、パリティ)。
- ローカルモード (Local Modes): 端末ドライバの動作(例: シグナル生成、フロー制御)。
- 特殊文字 (Special Characters): EOF、中断、サスペンドなどの特殊な制御文字。
これらの設定は、通常、C言語のtermios.h
ヘッダーファイルで定義されているstruct termios
構造体を通じて行われます。
termios
構造体
termios
構造体は、ターミナルデバイスの現在の設定を保持するためのデータ構造です。主要なメンバーは以下の通りです。
c_iflag
(input flags): 入力モードフラグc_oflag
(output flags): 出力モードフラグc_cflag
(control flags): 制御モードフラグc_lflag
(local flags): ローカルモードフラグc_cc
(control characters): 特殊制御文字の配列
これらのフラグはビットマスクとして機能し、複数の設定を同時に有効または無効にできます。
FreeBSD
FreeBSDは、UNIXをベースとしたオープンソースのオペレーティングシステムです。堅牢性、高性能、セキュリティに優れており、サーバー、組み込みシステム、デスクトップなど幅広い用途で利用されています。Go言語は、FreeBSDを含む複数のOSをサポートしており、各OSのシステムコールにアクセスするためのプラットフォーム固有のコードをsyscall
パッケージ内に持っています。
技術的詳細
このコミットの技術的な核心は、FreeBSDのC言語ヘッダーファイルで定義されているstruct termios
を、Go言語の型システムにマッピングすることです。
-
src/pkg/syscall/types_freebsd.go
の変更:#include <termios.h>
が追加されました。これにより、GoのCgoメカニズムを通じて、C言語のtermios
構造体の定義がGoのビルドプロセスに利用可能になります。type Termios C.struct_termios
というエイリアスが追加されました。これは、C言語のstruct termios
をGoのTermios
型として利用できるようにするためのものです。Goのsyscall
パッケージでは、C言語の構造体を直接Goの型として扱うために、このようなエイリアスが一般的に使用されます。
-
src/pkg/syscall/ztypes_freebsd_386.go
およびsrc/pkg/syscall/ztypes_freebsd_amd64.go
の変更:- これらのファイルは、Goのビルドプロセス中に自動生成されることが多い、プラットフォーム固有の型定義を含んでいます。このコミットでは、
Termios
構造体のGo言語での具体的なレイアウトが、386(32ビット)とamd64(64ビット)の両アーキテクチャ向けに定義されました。 - 定義された
Termios
構造体は、C言語のstruct termios
のメンバーに対応するGoのフィールドを持っています。Iflag
,Oflag
,Cflag
,Lflag
: これらはそれぞれC言語のc_iflag
,c_oflag
,c_cflag
,c_lflag
に対応し、ターミナルモードのフラグを保持します。Goでは通常、Cのunsigned int
やlong
がuint32
またはuint64
にマッピングされます。FreeBSDのtermios
ではこれらはtcflag_t
型であり、通常はunsigned long
またはunsigned int
です。Cc [20]uint8
: これはC言語のc_cc
配列に対応します。c_cc
は特殊制御文字を格納するための配列で、そのサイズはシステムによって異なりますが、FreeBSDでは通常NCCS
マクロで定義され、20バイトが一般的です。Ispeed
,Ospeed
: これらはそれぞれ入力および出力ボーレートを保持します。C言語ではspeed_t
型であり、通常はunsigned int
です。
- これらのファイルは、Goのビルドプロセス中に自動生成されることが多い、プラットフォーム固有の型定義を含んでいます。このコミットでは、
これらの変更により、GoプログラムはFreeBSD上でsyscall.Termios
型を使用してターミナル設定を取得、変更できるようになり、例えば、パスワード入力時のエコーを無効にしたり、非カノニカルモードで文字単位の入力を処理したりするような高度なターミナルアプリケーションを開発することが可能になります。
コアとなるコードの変更箇所
src/pkg/syscall/types_freebsd.go
--- a/src/pkg/syscall/types_freebsd.go
+++ b/src/pkg/syscall/types_freebsd.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>
@@ -248,3 +249,7 @@ type BpfInsn C.struct_bpf_insn
type BpfHdr C.struct_bpf_hdr
type BpfZbufHeader C.struct_bpf_zbuf_header
+
+// Terminal handling
+
+type Termios C.struct_termios
src/pkg/syscall/ztypes_freebsd_386.go
--- a/src/pkg/syscall/ztypes_freebsd_386.go
+++ b/src/pkg/syscall/ztypes_freebsd_386.go
@@ -443,3 +443,13 @@ type BpfZbufHeader struct {
User_gen uint32
X_bzh_pad [5]uint32
}
+
+type Termios struct {
+ Iflag uint32
+ Oflag uint32
+ Cflag uint32
+ Lflag uint32
+ Cc [20]uint8
+ Ispeed uint32
+ Ospeed uint32
+}
src/pkg/syscall/ztypes_freebsd_amd64.go
--- a/src/pkg/syscall/ztypes_freebsd_amd64.go
+++ b/src/pkg/syscall/ztypes_freebsd_amd64.go
@@ -446,3 +446,13 @@ type BpfZbufHeader struct {
User_gen uint32
X_bzh_pad [5]uint32
}
+
+type Termios struct {
+ Iflag uint32
+ Oflag uint32
+ Cflag uint32
+ Lflag uint32
+ Cc [20]uint8
+ Ispeed uint32
+ Ospeed uint32
+}
コアとなるコードの解説
src/pkg/syscall/types_freebsd.go
このファイルは、FreeBSDシステムコールに関連するGoの型定義の基盤となります。
#include <termios.h>
: Cgoディレクティブにより、C言語のtermios.h
ヘッダーファイルがインクルードされます。これにより、GoのビルドツールはC言語のstruct termios
の定義を認識し、Goの型にマッピングできるようになります。type Termios C.struct_termios
: これはGoの型エイリアスです。C言語のstruct termios
をGoのTermios
型として利用できるようにします。Goのsyscall
パッケージでは、OS固有のC構造体をGoの型として公開する際にこのパターンがよく用いられます。これにより、GoプログラムはC言語の構造体と互換性のあるメモリレイアウトを持つGoの構造体を扱うことができます。
src/pkg/syscall/ztypes_freebsd_386.go
および src/pkg/syscall/ztypes_freebsd_amd64.go
これらのファイルは、Goのgo tool cgo
によって生成される、プラットフォームおよびアーキテクチャ固有の型定義を含んでいます。これらは、C言語の構造体のメモリレイアウトをGoの構造体として正確に再現するために必要です。
type Termios struct { ... }
:Iflag
,Oflag
,Cflag
,Lflag
: これらはそれぞれ、入力、出力、制御、ローカルの各モードフラグに対応します。Goではuint32
型として定義されており、これはFreeBSDのtcflag_t
型(通常はunsigned int
またはunsigned long
)のサイズとアラインメントに合致するように選択されています。これらのフィールドは、ターミナルの動作を制御するビットマスクを保持します。Cc [20]uint8
: これは、特殊制御文字(例: EOF、行削除、中断など)を格納するための配列です。FreeBSDのtermios
構造体におけるc_cc
配列のサイズ(NCCS
マクロで定義)が20バイトであることに対応しています。uint8
の配列として定義することで、各バイトが制御文字を表します。Ispeed
,Ospeed
: これらはそれぞれ、入力および出力のボーレート(通信速度)を保持します。Goではuint32
型として定義されており、FreeBSDのspeed_t
型(通常はunsigned int
)に対応します。
これらの定義により、GoプログラムはFreeBSDのシステムコール(例: syscall.Tcgetattr
, syscall.Tcsetattr
)を呼び出す際に、このTermios
構造体を引数として渡し、ターミナル設定の取得や変更を行うことができるようになります。これは、GoでインタラクティブなCLIツールやシェルを開発する上で不可欠な機能です。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall - FreeBSDの
termios
マニュアルページ: https://www.freebsd.org/cgi/man.cgi?query=termios&sektion=4 - Go言語のCgoに関するドキュメント: https://go.dev/blog/cgo
参考にした情報源リンク
- Go言語の公式ドキュメント
- FreeBSDの公式マニュアルページ
- Unix系システムのターミナルI/O制御に関する一般的な情報源 (例: POSIX標準)
- GitHub上のGo言語リポジトリのソースコード
- Go言語のコードレビューシステム (Gerrit) の変更リスト: https://golang.org/cl/51580044