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

[インデックス 11391] ファイルの概要

このコミットは、Go言語の syscall パッケージにおいて、macOS (旧称 OS X) 環境で利用される NOTE_* 定数を追加するものです。これにより、GoプログラムがmacOSのkqueueメカニズムを通じてファイルシステムイベントやプロセスイベントなどをより詳細に監視できるようになります。

コミット

commit 82d06e8f3cca4bd680aaa0cef6b71d83df0382bc
Author: Robert Figueiredo <robfig@gmail.com>
Date:   Wed Jan 25 15:50:23 2012 -0500

    syscall: add NOTE_* constants on OS X
    
    R=rsc
    CC=golang-dev
    https://golang.org/cl/5570043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/82d06e8f3cca4bd680aaa0cef6b71d83df0382bc

元コミット内容

syscall: add NOTE_* constants on OS X

このコミットは、Go言語の syscall パッケージに、macOS (当時はOS X) で使用される NOTE_* 定数を追加することを目的としています。

変更の背景

Go言語の syscall パッケージは、オペレーティングシステムが提供する低レベルのシステムコールへのインターフェースを提供します。これにより、GoプログラムはOS固有の機能に直接アクセスできます。macOSでは、kqueue という効率的なイベント通知メカニズムが提供されており、ファイルディスクリプタやプロセス、ソケットなどの様々なオブジェクトに対するイベントを監視できます。

kqueue を利用する際には、監視したいイベントの種類を EVFILT_* (イベントフィルター) と NOTE_* (ノートフラグ) の組み合わせで指定します。このコミット以前は、Goの syscall パッケージにはmacOSの NOTE_* 定数が含まれていなかったため、Goプログラムから kqueue の全機能を活用することが困難でした。特に、ファイルシステムイベントの監視 (EVFILT_VNODE) やプロセスイベントの監視 (EVFILT_PROC) などで NOTE_* フラグは不可欠です。

この変更は、GoプログラムがmacOSのネイティブなイベント通知システムをより完全に、かつGoの慣用的な方法で利用できるようにするための基盤を整備するものです。

前提知識の解説

Go言語の syscall パッケージ

syscall パッケージは、Goプログラムがオペレーティングシステムのシステムコールに直接アクセスするための機能を提供します。これにより、ファイル操作、ネットワーク通信、プロセス管理など、OSレベルの低レイヤーな操作を行うことができます。このパッケージはOSに依存する部分が多く、各OS向けに異なる実装が提供されています。

macOSの kqueue

kqueue は、macOS (およびFreeBSD, NetBSD, OpenBSDなどのBSD系OS) で利用可能な、高性能なイベント通知インターフェズムです。従来の select()poll() と比較して、多数のファイルディスクリプタやイベントソースを効率的に監視できる点が特徴です。

kqueue は以下の主要な概念で構成されます。

  • kqueueディスクリプタ: kqueue() システムコールによって作成される、イベントキューへの参照です。
  • kevent構造体: 監視したいイベントの種類、対象、およびイベント発生時の情報を含む構造体です。
  • EVFILT_* (イベントフィルター): 監視するイベントのカテゴリを指定します。例えば、EVFILT_READ は読み込み可能イベント、EVFILT_WRITE は書き込み可能イベント、EVFILT_VNODE はVnode (ファイルシステムオブジェクト) イベント、EVFILT_PROC はプロセスイベントを指します。
  • NOTE_* (ノートフラグ): EVFILT_VNODEEVFILT_PROC などの特定のイベントフィルターと組み合わせて使用され、より詳細なイベントの種類を指定します。例えば、EVFILT_VNODENOTE_WRITE を組み合わせると、ファイルの書き込みイベントを監視できます。

kqueue の基本的な使用方法は以下の通りです。

  1. kqueue() を呼び出してkqueueディスクリプタを作成します。
  2. kevent 構造体を設定し、監視したいイベントと対象(ファイルディスクリプタ、プロセスIDなど)を指定します。
  3. kevent() を呼び出して、イベントをkqueueに登録したり、発生したイベントを取得したりします。

mkerrors.sh スクリプト

Go言語の syscall パッケージには、OS固有の定数や構造体を自動生成するためのスクリプトが含まれています。mkerrors.sh はその一つで、C言語のヘッダーファイルから定数定義を抽出し、Goのソースコード (zerrors_darwin_386.go, zerrors_darwin_amd64.go など) を生成する役割を担っています。これにより、手動で大量の定数を記述する手間を省き、OSのヘッダーファイルの変更に追従しやすくなります。

技術的詳細

このコミットの技術的な核心は、mkerrors.sh スクリプトの正規表現に NOTE| を追加した点にあります。

mkerrors.sh は、C言語のヘッダーファイルを解析し、特定のパターンにマッチする定数をGoのコードとして出力します。変更前のスクリプトでは、NOTE_ で始まる定数がこのパターンに含まれていなかったため、macOSのシステムヘッダーファイルに定義されている NOTE_* 定数がGoの syscall パッケージに自動的に取り込まれませんでした。

具体的には、mkerrors.sh 内の定数名を識別するための正規表現が以下のように変更されました。

--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -177,7 +177,7 @@ ccflags="$@"
 		$2 ~ /^SIG[^_]/ ||
 		$2 ~ /^IN_/ ||
 		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
-		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
+		$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
 		$2 == "SOMAXCONN" ||
 		$2 == "NAME_MAX" ||
 		$2 == "IFNAMSIZ" ||

この変更により、mkerrors.sh が実行されると、NOTE_ プレフィックスを持つすべての定数(例: NOTE_DELETE, NOTE_WRITE, NOTE_FORK, NOTE_EXEC など)が src/pkg/syscall/zerrors_darwin_386.go および src/pkg/syscall/zerrors_darwin_amd64.go に自動的に生成されるようになります。

これらの zerrors_darwin_*.go ファイルは、Goの syscall パッケージがmacOSのシステムコールと連携するために必要な、アーキテクチャ固有の定数定義を含んでいます。NOTE_* 定数が追加されることで、Go開発者は kqueue を利用して、よりきめ細やかなイベント監視ロジックをGoで記述できるようになります。

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

このコミットで変更された主要なファイルは以下の3つです。

  1. src/pkg/syscall/mkerrors.sh:

    • このシェルスクリプトは、Goの syscall パッケージのOS固有の定数ファイルを生成するためのものです。
    • 変更点: 定数名を識別するための正規表現に NOTE| が追加されました。
  2. src/pkg/syscall/zerrors_darwin_386.go:

    • macOS (32-bit Intelアーキテクチャ) 向けの syscall 定数定義が自動生成されるファイルです。
    • 変更点: mkerrors.sh の変更に伴い、NOTE_* 定数が多数追加されました。これにより、ファイルの行数が増加し、既存の定数の並び順も一部変更されています。
  3. src/pkg/syscall/zerrors_darwin_amd64.go:

    • macOS (64-bit Intelアーキテクチャ) 向けの syscall 定数定義が自動生成されるファイルです。
    • 変更点: zerrors_darwin_386.go と同様に、NOTE_* 定数が追加され、ファイルの内容が更新されました。

コアとなるコードの解説

src/pkg/syscall/mkerrors.sh の変更

--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -177,7 +177,7 @@ ccflags="$@"
 		$2 ~ /^SIG[^_]/ ||
 		$2 ~ /^IN_/ ||
 		$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
-\t\t$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
+\t\t$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
 		$2 == "SOMAXCONN" ||
 		$2 == "NAME_MAX" ||
 		$2 == "IFNAMSIZ" ||

この変更は、mkerrors.sh スクリプトがCヘッダーファイルからGoの定数を抽出する際に使用する正規表現を修正しています。具体的には、EVFILT| の後に NOTE| が追加されました。これにより、NOTE_ で始まるすべての定数(例: NOTE_DELETE, NOTE_WRITE, NOTE_FORK, NOTE_EXEC など)が、Goの syscall パッケージのmacOS固有の定数ファイル (zerrors_darwin_386.go, zerrors_darwin_amd64.go) に含まれるようになります。

src/pkg/syscall/zerrors_darwin_386.go および src/pkg/syscall/zerrors_darwin_amd64.go の変更

これらのファイルは mkerrors.sh によって自動生成されるため、手動での変更は行われません。mkerrors.sh の変更が適用された後、これらのファイルが再生成され、以下のような NOTE_* 定数が追加されました(例として一部を抜粋)。

const (
    // ... 既存の定数 ...
    NOTE_ABSOLUTE                     = 0x8
    NOTE_ATTRIB                       = 0x8
    NOTE_CHILD                        = 0x4
    NOTE_DELETE                       = 0x1
    NOTE_EXEC                         = 0x20000000
    NOTE_EXIT                         = 0x80000000
    NOTE_EXITSTATUS                   = 0x4000000
    NOTE_EXTEND                       = 0x4
    NOTE_FFAND                        = 0x40000000
    NOTE_FFCOPY                       = 0xc0000000
    NOTE_FFCTRLMASK                   = 0xc0000000
    NOTE_FFLAGSMASK                   = 0xffffff
    NOTE_FFNOP                        = 0x0
    NOTE_FFOR                         = 0x80000000
    NOTE_FORK                         = 0x40000000
    NOTE_LINK                         = 0x10
    NOTE_LOWAT                        = 0x1
    NOTE_NONE                         = 0x80
    NOTE_NSECONDS                     = 0x4
    NOTE_PCTRLMASK                    = -0x100000
    NOTE_PDATAMASK                    = 0xfffff
    NOTE_REAP                         = 0x10000000
    NOTE_RENAME                       = 0x20
    NOTE_RESOURCEEND                  = 0x2000000
    NOTE_REVOKE                       = 0x40
    NOTE_SECONDS                      = 0x1
    NOTE_SIGNAL                       = 0x8000000
    NOTE_TRACK                        = 0x1
    NOTE_TRACKERR                     = 0x2
    NOTE_TRIGGER                      = 0x1000000
    NOTE_USECONDS                     = 0x2
    NOTE_VM_ERROR                     = 0x10000000
    NOTE_VM_PRESSURE                  = 0x80000000
    NOTE_VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000
    NOTE_VM_PRESSURE_TERMINATE        = 0x40000000
    NOTE_WRITE                        = 0x2
    // ... その他の定数 ...
)

これらの定数がGoの syscall パッケージに組み込まれることで、Go開発者は syscall.Kevent 構造体や syscall.Kqueue 関数と組み合わせて、macOSの kqueue が提供する豊富なイベント監視機能をGoプログラムから直接利用できるようになります。例えば、ファイルの削除、書き込み、名前変更、属性変更などのイベントを EVFILT_VNODE と対応する NOTE_* フラグを使って監視することが可能になります。

関連リンク

  • Go syscall パッケージのドキュメント: https://pkg.go.dev/syscall
  • macOS kqueue のmanページ (例: man 2 kqueue, man 2 kevent): これらのmanページは、macOSにおける kqueue の詳細な動作と利用可能な EVFILT_* および NOTE_* フラグについて説明しています。
  • GoのChange List (CL) 5570043: https://golang.org/cl/5570043 (コミットメッセージに記載されている元のCL)

参考にした情報源リンク

  • Go言語のソースコード (特に src/pkg/syscall ディレクトリ)
  • macOSのシステムプログラミングに関するドキュメント
  • BSD系OSの kqueue に関する資料
  • Goのコードレビューシステム (Gerrit) のChange List (CL) 5570043
  • Goの公式ドキュメント
  • GoのIssue Tracker (関連するIssueがあれば)
  • mkerrors.sh のようなGoのツールチェーンに関する情報