[インデックス 11868] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるBSD系OS(FreeBSD, NetBSD, OpenBSD)向けのKill
システムコール定義の変更に関するものです。具体的には、Kill
関数のsignum
引数の型がint
からSignal
型に変更されています。これは、os/signal
パッケージの新しい設計との同期を図るための変更です。
コミット
commit adc1e0bcef9e7e4a7bf4fa6d5b83681d578b9e0f
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Tue Feb 14 11:20:39 2012 +0900
syscall: update BSD variants to sync with new os/signal
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5661051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/adc1e0bcef9e7e4a7bf4fa6d5b83681d578b9e0f
元コミット内容
syscall: update BSD variants to sync with new os/signal
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5661051
変更の背景
このコミットの背景には、Go言語の標準ライブラリにおけるシグナルハンドリングの改善と標準化があります。特に、os/signal
パッケージが導入または改訂され、シグナルをより型安全かつGoらしい方法で扱うための新しいSignal
型が定義されたことが挙げられます。
従来のシステムコールでは、シグナル番号は単なる整数型(int
)として扱われていました。しかし、これにより、誤ったシグナル番号が渡された場合にコンパイル時エラーではなく実行時エラーとなる可能性がありました。また、シグナルに関するセマンティクスがint
型だけでは表現しきれないという問題もありました。
新しいos/signal
パッケージの導入により、シグナルはSignal
という専用の型で表現されるようになりました。これにより、シグナルに関する操作がより明確になり、型チェックによる早期エラー検出が可能になります。この変更は、Go言語の設計思想である「型安全性」と「明確性」を追求する一環として行われました。
このコミットは、syscall
パッケージがos/signal
パッケージの新しいSignal
型と整合性を持つようにするための同期作業であり、Go言語全体のシグナル処理の一貫性を保つことを目的としています。
前提知識の解説
1. システムコール (System Call)
システムコールは、オペレーティングシステム (OS) のカーネルが提供するサービスを、ユーザー空間のプログラムが利用するためのインターフェースです。ファイル操作、プロセス管理、メモリ管理、ネットワーク通信など、OSの基本的な機能のほとんどはシステムコールを通じて提供されます。
Go言語のsyscall
パッケージは、これらのOS固有のシステムコールをGoプログラムから直接呼び出すための機能を提供します。これにより、低レベルのOS機能にアクセスしたり、OS固有の動作を制御したりすることが可能になります。
2. シグナル (Signal)
シグナルは、Unix系OSにおいてプロセス間通信やイベント通知のために使用されるソフトウェア割り込みの一種です。例えば、Ctrl+Cを押すとSIGINT
シグナルがプロセスに送られ、プロセスは通常終了します。他にも、子プロセスの終了を通知するSIGCHLD
、セグメンテーション違反を通知するSIGSEGV
など、様々なシグナルが存在します。
シグナルは、プロセスに対して特定のイベントが発生したことを通知し、それに応じてプロセスが特定の動作(シグナルハンドラの実行、プロセスの終了など)を行うように促します。
3. Kill
システムコール
Kill
システムコールは、指定されたプロセスID (PID) に対して特定のシグナルを送信するために使用されます。関数の基本的な形式は以下のようになります。
int kill(pid_t pid, int sig);
pid
: シグナルを送信する対象のプロセスID。sig
: 送信するシグナル番号。
このシステムコールは、プロセスを終了させるだけでなく、特定のシグナルを送信してプロセスの動作を制御するためにも使用されます。
4. Go言語のos/signal
パッケージ
os/signal
パッケージは、GoプログラムがOSからのシグナルを処理するための機能を提供します。このパッケージを使用することで、特定のシグナルを受信した際にカスタムの処理を実行したり、シグナルを無視したりすることができます。
このコミットが行われた時期(2012年頃)に、os/signal
パッケージはシグナルをよりGoらしい方法で扱うためのSignal
型を導入しました。このSignal
型は、OS固有のシグナル番号を抽象化し、Goプログラム内でシグナルをより安全かつ明確に扱うことを可能にします。
5. //sys
および //sysnb
コメント
Go言語のsyscall
パッケージのソースコードには、//sys
や//sysnb
といった特殊なコメントが頻繁に見られます。これらは、Goのツールチェーンがシステムコールを自動生成するために使用するディレクティブです。
//sys
: 通常のシステムコールを生成することを示します。//sysnb
: "no blocking" の略で、ノンブロッキングなシステムコールを生成することを示します。これは、Goのランタイムがシステムコール中に他のゴルーチンをスケジュールできるようにするために重要です。
これらのコメントは、Goのビルドプロセスにおいて、C言語のシステムコール定義からGoの関数シグネチャを自動的に生成するために利用されます。
技術的詳細
このコミットの技術的な詳細を掘り下げると、Go言語のクロスプラットフォーム対応と、型安全性の追求という2つの側面が見えてきます。
Go言語は、様々なOS上で動作するように設計されており、それぞれのOSが提供するシステムコールを抽象化して利用できるようにsyscall
パッケージを提供しています。しかし、OSによってシステムコールのシグネチャやセマンティクスが微妙に異なる場合があります。このため、syscall
パッケージ内では、各OS向けのファイル(例: syscall_freebsd.go
, syscall_netbsd.go
, syscall_openbsd.go
)にOS固有の実装が記述されています。
このコミットでは、BSD系のOS(FreeBSD, NetBSD, OpenBSD)におけるKill
システムコールのGo言語ラッパーの定義が変更されています。具体的には、Kill
関数の2番目の引数であるsignum
の型がint
からSignal
に変更されました。
--- a/src/pkg/syscall/syscall_freebsd.go
+++ b/src/pkg/syscall/syscall_freebsd.go
@@ -146,7 +146,7 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
//sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Getuid() (uid int)
//sys Issetugid() (tainted bool)
-//sys Kill(pid int, signum int) (err error)
+//sys Kill(pid int, signum Signal) (err error)
//sys Kqueue() (fd int, err error)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Link(path string, link string) (err error)
この変更は、os/signal
パッケージで定義された新しいSignal
型との整合性を保つために行われました。Signal
型は、Go言語の内部でシグナルを表現するためのカスタム型であり、これによりシグナルに関する操作がより型安全になります。例えば、os.Interrupt
やos.Kill
といった定数がSignal
型として提供され、これらをKill
関数に直接渡すことができるようになります。
この変更のメリットは以下の通りです。
- 型安全性:
int
型では任意の整数値をシグナル番号として渡せてしまいますが、Signal
型を使用することで、Goコンパイラが不正なシグナル番号の利用を検出できるようになります。これにより、実行時エラーのリスクが低減します。 - コードの可読性:
Signal
型を使用することで、コードを読む人がその引数がシグナル番号であることをより明確に理解できます。 - 一貫性:
os/signal
パッケージとsyscall
パッケージの間でシグナル表現の一貫性が保たれ、Go言語全体でのシグナル処理の設計がより統一されます。
この変更は、Go言語が初期の段階から、低レベルのシステムプログラミングにおいても高いレベルの安全性と使いやすさを追求していたことを示しています。
コアとなるコードの変更箇所
変更は以下の3つのファイルにわたっています。
src/pkg/syscall/syscall_freebsd.go
src/pkg/syscall/syscall_netbsd.go
src/pkg/syscall/syscall_openbsd.go
それぞれのファイルで、Kill
システムコールの定義行が変更されています。
--- a/src/pkg/syscall/syscall_freebsd.go
+++ b/src/pkg/syscall/syscall_freebsd.go
@@ -146,7 +146,7 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
//sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Getuid() (uid int)
//sys Issetugid() (tainted bool)
-//sys Kill(pid int, signum int) (err error)
+//sys Kill(pid int, signum Signal) (err error)
//sys Kqueue() (fd int, err error)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Link(path string, link string) (err error)
他の2つのファイル(syscall_netbsd.go
とsyscall_openbsd.go
)も同様の変更が加えられています。
コアとなるコードの解説
変更された行は、Goのsyscall
パッケージがOSのシステムコールをGoの関数として公開するための特殊なコメント構文を使用しています。
元の行:
//sys Kill(pid int, signum int) (err error)
変更後の行:
//sys Kill(pid int, signum Signal) (err error)
この//sys
コメントは、Goのビルドツールがこの行を解析し、対応するGoの関数シグネチャを自動的に生成するために使用されます。
//sys
: これは、この行がシステムコール定義であることを示すディレクティブです。Kill
: 生成されるGo関数の名前です。(pid int, signum int)
: 生成されるGo関数の引数リストです。pid int
: プロセスIDを表すint
型の引数。signum int
(変更前): シグナル番号を表すint
型の引数。signum Signal
(変更後): シグナル番号を表すSignal
型の引数。
(err error)
: 生成されるGo関数の戻り値リストです。システムコールがエラーを返す可能性があるため、通常はerror
型が含まれます。
この変更により、Goのsyscall.Kill
関数を呼び出す際に、signum
引数としてint
型ではなくos/signal
パッケージで定義されたSignal
型を渡すことが必須となります。これにより、Goコンパイラが型チェックを行い、不正なシグナル番号の利用を早期に検出できるようになります。
例えば、変更前は以下のようなコードがコンパイルできてしまいましたが、シグナル番号として意味のない値が渡される可能性がありました。
// 変更前 (概念的なコード)
syscall.Kill(1234, 999) // 999は有効なシグナル番号ではないかもしれない
変更後は、Signal
型を使用することで、より安全な呼び出しが強制されます。
// 変更後 (概念的なコード)
import "os"
import "syscall"
syscall.Kill(1234, os.Interrupt) // os.Interrupt は Signal 型
// syscall.Kill(1234, 999) // これはコンパイルエラーになる
この変更は、Go言語の標準ライブラリが、低レベルのOSインターフェースを扱いながらも、Go言語の型システムを活用して堅牢性と安全性を高める努力の一端を示しています。
関連リンク
- Go言語の
os/signal
パッケージのドキュメント (現在のバージョン): https://pkg.go.dev/os/signal - Go言語の
syscall
パッケージのドキュメント (現在のバージョン): https://pkg.go.dev/syscall - Go言語のChange List (CL) 5661051: https://golang.org/cl/5661051 (コミットメッセージに記載されているCLへのリンク)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Unix系OSのシグナルに関する一般的な情報源 (例:
man 7 signal
,man 2 kill
) - Go言語のソースコードリポジトリ (特に
src/pkg/syscall
ディレクトリ) - Go言語のコミット履歴とChange List (CL) の議論
- Go言語の設計に関するブログ記事や議論(当時の情報)
[インデックス 11868] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるBSD系OS(FreeBSD, NetBSD, OpenBSD)向けのKill
システムコール定義の変更に関するものです。具体的には、Kill
関数のsignum
引数の型がint
からSignal
型に変更されています。これは、os/signal
パッケージの新しい設計との同期を図るための変更です。
コミット
commit adc1e0bcef9e7e4a7bf4fa6d5b83681d578b9e0f
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date: Tue Feb 14 11:20:39 2012 +0900
syscall: update BSD variants to sync with new os/signal
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5661051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/adc1e0bcef9e7e4a7bf4fa6d5b83681d578b9e0f
元コミット内容
syscall: update BSD variants to sync with new os/signal
R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/5661051
変更の背景
このコミットの背景には、Go言語の標準ライブラリにおけるシグナルハンドリングの改善と標準化があります。特に、Go 1のリリース時期(2012年頃)にos/signal
パッケージが改訂され、シグナルをより型安全かつGoらしい方法で扱うための新しいSignal
型が導入されたことが挙げられます。
従来のシステムコールでは、シグナル番号は単なる整数型(int
)として扱われていました。しかし、これにより、誤ったシグナル番号が渡された場合にコンパイル時エラーではなく実行時エラーとなる可能性がありました。また、シグナルに関するセマンティクスがint
型だけでは表現しきれないという問題もありました。
Web検索の結果によると、2012年頃のos/signal
パッケージの変更では、signal.Notify
関数がシグナル受信の主要なメカニズムとして導入され、chan os.Signal
型のチャネルを通じてシグナルが通知されるようになりました。このos.Signal
型自体はインターフェースであり、syscall.SIGINT
やsyscall.SIGTERM
のような具体的なシグナル値がこのインターフェースを満たす形でチャネルに送られます。
この変更により、シグナルはSignal
という専用の型(またはインターフェース)で表現されるようになりました。これにより、シグナルに関する操作がより明確になり、型チェックによる早期エラー検出が可能になります。この変更は、Go言語の設計思想である「型安全性」と「明確性」を追求する一環として行われました。
このコミットは、syscall
パッケージがos/signal
パッケージの新しいSignal
型と整合性を持つようにするための同期作業であり、Go言語全体のシグナル処理の一貫性を保つことを目的としています。これにより、GoのプログラムがOSシグナルを扱う際に、より統一された、Goらしいアプローチが提供されることになります。
前提知識の解説
1. システムコール (System Call)
システムコールは、オペレーティングシステム (OS) のカーネルが提供するサービスを、ユーザー空間のプログラムが利用するためのインターフェースです。ファイル操作、プロセス管理、メモリ管理、ネットワーク通信など、OSの基本的な機能のほとんどはシステムコールを通じて提供されます。
Go言語のsyscall
パッケージは、これらのOS固有のシステムコールをGoプログラムから直接呼び出すための機能を提供します。これにより、低レベルのOS機能にアクセスしたり、OS固有の動作を制御したりすることが可能になります。
2. シグナル (Signal)
シグナルは、Unix系OSにおいてプロセス間通信やイベント通知のために使用されるソフトウェア割り込みの一種です。例えば、Ctrl+Cを押すとSIGINT
シグナルがプロセスに送られ、プロセスは通常終了します。他にも、子プロセスの終了を通知するSIGCHLD
、セグメンテーション違反を通知するSIGSEGV
など、様々なシグナルが存在します。
シグナルは、プロセスに対して特定のイベントが発生したことを通知し、それに応じてプロセスが特定の動作(シグナルハンドラの実行、プロセスの終了など)を行うように促します。
3. Kill
システムコール
Kill
システムコールは、指定されたプロセスID (PID) に対して特定のシグナルを送信するために使用されます。関数の基本的な形式は以下のようになります。
int kill(pid_t pid, int sig);
pid
: シグナルを送信する対象のプロセスID。sig
: 送信するシグナル番号。
このシステムコールは、プロセスを終了させるだけでなく、特定のシグナルを送信してプロセスの動作を制御するためにも使用されます。
4. Go言語のos/signal
パッケージとSignal
型
os/signal
パッケージは、GoプログラムがOSからのシグナルを処理するための機能を提供します。このパッケージを使用することで、特定のシグナルを受信した際にカスタムの処理を実行したり、シグナルを無視したりすることができます。
このコミットが行われた時期(2012年頃)に、os/signal
パッケージはシグナルをよりGoらしい方法で扱うためのSignal
型を導入しました。このSignal
型は、OS固有のシグナル番号を抽象化し、Goプログラム内でシグナルをより安全かつ明確に扱うことを可能にします。具体的には、os.Signal
はインターフェースとして定義され、syscall
パッケージ内の具体的なシグナル定数(例: syscall.SIGINT
)がこのインターフェースを実装します。これにより、Goの型システムを活用してシグナルを扱う際の堅牢性が向上しました。
5. //sys
および //sysnb
コメント
Go言語のsyscall
パッケージのソースコードには、//sys
や//sysnb
といった特殊なコメントが頻繁に見られます。これらは、Goのツールチェーンがシステムコールを自動生成するために使用するディレクティブです。
//sys
: 通常のシステムコールを生成することを示します。//sysnb
: "no blocking" の略で、ノンブロッキングなシステムコールを生成することを示します。これは、Goのランタイムがシステムコール中に他のゴルーチンをスケジュールできるようにするために重要です。
これらのコメントは、Goのビルドプロセスにおいて、C言語のシステムコール定義からGoの関数シグネチャを自動的に生成するために利用されます。
技術的詳細
このコミットの技術的な詳細を掘り下げると、Go言語のクロスプラットフォーム対応と、型安全性の追求という2つの側面が見えてきます。
Go言語は、様々なOS上で動作するように設計されており、それぞれのOSが提供するシステムコールを抽象化して利用できるようにsyscall
パッケージを提供しています。しかし、OSによってシステムコールのシグネチャやセマンティクスが微妙に異なる場合があります。このため、syscall
パッケージ内では、各OS向けのファイル(例: syscall_freebsd.go
, syscall_netbsd.go
, syscall_openbsd.go
)にOS固有の実装が記述されています。
このコミットでは、BSD系のOS(FreeBSD, NetBSD, OpenBSD)におけるKill
システムコールのGo言語ラッパーの定義が変更されています。具体的には、Kill
関数の2番目の引数であるsignum
の型がint
からSignal
に変更されました。
--- a/src/pkg/syscall/syscall_freebsd.go
+++ b/src/pkg/syscall/syscall_freebsd.go
@@ -146,7 +146,7 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
//sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Getuid() (uid int)
//sys Issetugid() (tainted bool)
-//sys Kill(pid int, signum int) (err error)
+//sys Kill(pid int, signum Signal) (err error)
//sys Kqueue() (fd int, err error)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Link(path string, link string) (err error)
この変更は、os/signal
パッケージで定義された新しいSignal
型との整合性を保つために行われました。Signal
型は、Go言語の内部でシグナルを表現するためのカスタム型であり、これによりシグナルに関する操作がより型安全になります。例えば、os.Interrupt
やos.Kill
といった定数がSignal
型として提供され、これらをKill
関数に直接渡すことができるようになります。
この変更のメリットは以下の通りです。
- 型安全性:
int
型では任意の整数値をシグナル番号として渡せてしまいますが、Signal
型を使用することで、Goコンパイラが不正なシグナル番号の利用を検出できるようになります。これにより、実行時エラーのリスクが低減します。 - コードの可読性:
Signal
型を使用することで、コードを読む人がその引数がシグナル番号であることをより明確に理解できます。 - 一貫性:
os/signal
パッケージとsyscall
パッケージの間でシグナル表現の一貫性が保たれ、Go言語全体でのシグナル処理の設計がより統一されます。
この変更は、Go言語が初期の段階から、低レベルのシステムプログラミングにおいても高いレベルの安全性と使いやすさを追求していたことを示しています。
コアとなるコードの変更箇所
変更は以下の3つのファイルにわたっています。
src/pkg/syscall/syscall_freebsd.go
src/pkg/syscall/syscall_netbsd.go
src/pkg/syscall/syscall_openbsd.go
それぞれのファイルで、Kill
システムコールの定義行が変更されています。
--- a/src/pkg/syscall/syscall_freebsd.go
+++ b/src/pkg/syscall/syscall_freebsd.go
@@ -146,7 +146,7 @@ func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
//sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Getuid() (uid int)
//sys Issetugid() (tainted bool)
-//sys Kill(pid int, signum int) (err error)
+//sys Kill(pid int, signum Signal) (err error)
//sys Kqueue() (fd int, err error)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Link(path string, link string) (err error)
他の2つのファイル(syscall_netbsd.go
とsyscall_openbsd.go
)も同様の変更が加えられています。
コアとなるコードの解説
変更された行は、Goのsyscall
パッケージがOSのシステムコールをGoの関数として公開するための特殊なコメント構文を使用しています。
元の行:
//sys Kill(pid int, signum int) (err error)
変更後の行:
//sys Kill(pid int, signum Signal) (err error)
この//sys
コメントは、Goのビルドツールがこの行を解析し、対応するGoの関数シグネチャを自動的に生成するために使用されます。
//sys
: これは、この行がシステムコール定義であることを示すディレクティブです。Kill
: 生成されるGo関数の名前です。(pid int, signum int)
: 生成されるGo関数の引数リストです。pid int
: プロセスIDを表すint
型の引数。signum int
(変更前): シグナル番号を表すint
型の引数。signum Signal
(変更後): シグナル番号を表すSignal
型の引数。
(err error)
: 生成されるGo関数の戻り値リストです。システムコールがエラーを返す可能性があるため、通常はerror
型が含まれます。
この変更により、Goのsyscall.Kill
関数を呼び出す際に、signum
引数としてint
型ではなくos/signal
パッケージで定義されたSignal
型を渡すことが必須となります。これにより、Goコンパイラが型チェックを行い、不正なシグナル番号の利用を早期に検出できるようになります。
例えば、変更前は以下のようなコードがコンパイルできてしまいましたが、シグナル番号として意味のない値が渡される可能性がありました。
// 変更前 (概念的なコード)
syscall.Kill(1234, 999) // 999は有効なシグナル番号ではないかもしれない
変更後は、Signal
型を使用することで、より安全な呼び出しが強制されます。
// 変更後 (概念的なコード)
import "os"
import "syscall"
syscall.Kill(1234, os.Interrupt) // os.Interrupt は Signal 型
// syscall.Kill(1234, 999) // これはコンパイルエラーになる
この変更は、Go言語の標準ライブラリが、低レベルのOSインターフェースを扱いながらも、Go言語の型システムを活用して堅牢性と安全性を高める努力の一端を示しています。
関連リンク
- Go言語の
os/signal
パッケージのドキュメント (現在のバージョン): https://pkg.go.dev/os/signal - Go言語の
syscall
パッケージのドキュメント (現在のバージョン): https://pkg.go.dev/syscall - Go言語のChange List (CL) 5661051: https://golang.org/cl/5661051 (コミットメッセージに記載されているCLへのリンク)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Unix系OSのシグナルに関する一般的な情報源 (例:
man 7 signal
,man 2 kill
) - Go言語のソースコードリポジトリ (特に
src/pkg/syscall
ディレクトリ) - Go言語のコミット履歴とChange List (CL) の議論
- Go言語の設計に関するブログ記事や議論(当時の情報)
- Web検索結果: "Go os/signal package changes 2012 Signal type" (特に、
os/signal
パッケージの変更がGo 1のリリースと同時期に行われ、signal.Notify
関数とos.Signal
インターフェースが導入された点)