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

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

このコミットは、Go言語のsyscallパッケージにおいて、Linuxシステムコールで使用されるCLONE_*定数を定義するものです。これにより、GoプログラムからLinuxのcloneシステムコールをより詳細に制御できるようになります。

コミット

commit d4f719ee13312e283af3346b7814f578e6db2155
Author: Rémy Oudompheng <oudomphe@phare.normalesup.org>
Date:   Fri Aug 23 22:26:49 2013 +0200

    syscall: define CLONE_* constants on Linux.
    
    Update #6214
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/13160043

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

https://github.com/golang/go/commit/d4f719ee13312e283af3346b7814f578e6db2155

元コミット内容

syscall: define CLONE_* constants on Linux.

このコミットは、LinuxにおけるCLONE_*定数をsyscallパッケージに定義することを目的としています。

変更の背景

この変更は、GoのIssue #6214 に関連しています。Go言語のsyscallパッケージは、オペレーティングシステムの低レベルな機能にアクセスするためのインターフェースを提供します。Linuxシステムでは、新しいプロセスやスレッドを作成するためにcloneシステムコールが使用されます。cloneシステムコールは、親プロセスと子プロセスの間で共有するリソース(メモリ空間、ファイルディスクリプタ、シグナルハンドラなど)を細かく制御するための様々なフラグ(CLONE_*定数)を受け取ります。

Goのランタイムや、Goで書かれた低レベルなシステムプログラミングを行う際に、これらのCLONE_*定数が必要となる場面がありました。しかし、当時のsyscallパッケージにはこれらの定数が定義されていなかったため、Goプログラムから直接cloneシステムコールを呼び出す際に、これらのフラグをGoのコード内で直接マジックナンバーとして記述するか、Cgoを介してC言語のヘッダファイルから取得する必要がありました。これはGoのコードの可読性、移植性、およびメンテナンス性を損なうものでした。

このコミットは、これらのCLONE_*定数をsyscallパッケージに明示的に定義することで、GoプログラムがよりGoらしい方法でcloneシステムコールを扱えるようにし、低レベルなシステムプログラミングの利便性を向上させることを目的としています。

前提知識の解説

Linuxのcloneシステムコール

Linuxにおけるcloneシステムコールは、新しい実行コンテキスト(プロセスまたはスレッド)を作成するための強力なシステムコールです。従来のforkシステムコールが親プロセスのほぼ完全なコピーを作成するのに対し、cloneは新しい実行コンテキストが親と共有するリソースを細かく指定できる点が特徴です。これにより、スレッド(多くのリソースを共有する軽量プロセス)や、特定の名前空間(namespace)を分離したコンテナのような環境を作成する際に利用されます。

cloneシステムコールは、以下のようなフラグ(CLONE_*定数)のビットマスクを受け取ります。

  • CLONE_VM: 親と子で同じメモリ空間を共有します。これにより、スレッドのような動作が可能になります。
  • CLONE_FS: 親と子で同じファイルシステム情報(カレントディレクトリ、ルートディレクトリなど)を共有します。
  • CLONE_FILES: 親と子で同じファイルディスクリプタテーブルを共有します。
  • CLONE_SIGHAND: 親と子で同じシグナルハンドラテーブルを共有します。
  • CLONE_PTRACE: 親が子をトレースできるようにします。
  • CLONE_VFORK: forkと同様に、子プロセスがexecveを呼び出すまで親プロセスをブロックします。
  • CLONE_PARENT: 親の親(grandparent)を新しいプロセスの親とします。
  • CLONE_THREAD: 新しいプロセスをスレッドグループのメンバーとして作成します。
  • CLONE_NEWNS: 新しいマウント名前空間を作成します。
  • CLONE_NEWPID: 新しいPID名前空間を作成します。
  • CLONE_NEWIPC: 新しいIPC名前空間を作成します。
  • CLONE_NEWNET: 新しいネットワーク名前空間を作成します。
  • CLONE_NEWUTS: 新しいUTS名前空間(hostnameなど)を作成します。
  • CLONE_NEWUSER: 新しいユーザー名前空間を作成します。
  • CLONE_CHILD_CLEARTID: 子プロセスが終了したときに、指定されたchild_tidptrの値をクリアし、futexウェイクアップを行います。
  • CLONE_CHILD_SETTID: 子プロセスのchild_tidptrに子プロセスのTID(スレッドID)を設定します。
  • CLONE_DETACHED: 親が子を待つ必要がないことを示します。
  • CLONE_UNTRACED: CLONE_PTRACEが設定されていても、子プロセスが親によってトレースされないようにします。
  • CLONE_SETTLS: 新しいTLS(Thread Local Storage)記述子を設定します。
  • CLONE_SYSVSEM: 親と子でSystem Vセマフォの調整を共有します。
  • CLONE_IO: 親と子でI/Oコンテキストを共有します。

これらのフラグを適切に組み合わせることで、プロセスとスレッドの間の様々な共有レベルを実現できます。

Goのsyscallパッケージ

Go言語のsyscallパッケージは、Goプログラムから直接オペレーティングシステムのシステムコールを呼び出すための機能を提供します。これにより、ファイル操作、ネットワーク通信、プロセス管理など、OSレベルの機能にアクセスできます。このパッケージは、OS固有の定数(エラーコード、フラグなど)や構造体も定義しており、GoプログラムがOSのAPIと連携するための橋渡しをします。

mkerrors.shスクリプト

Goのsyscallパッケージには、OS固有の定数や構造体を自動生成するためのスクリプトが含まれています。mkerrors.shはその一つで、C言語のヘッダファイルからGoの定数定義を生成するために使用されます。このスクリプトは、特定のCヘッダファイルを読み込み、そこから必要な定数(例えば、#defineで定義されたもの)を抽出し、Goのソースコードとして出力します。これにより、手動で定数をGoのコードに移植する手間を省き、OSのヘッダファイルの変更に追従しやすくなります。

技術的詳細

このコミットの主要な変更点は、src/pkg/syscall/mkerrors.shスクリプトと、それによって生成されるsrc/pkg/syscall/zerrors_linux_*.goファイル群です。

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

    • #include <linux/sched.h>が追加されました。これは、CLONE_*定数が定義されているLinuxカーネルのヘッダファイルです。mkerrors.shスクリプトがこのヘッダファイルを読み込むことで、CLONE_*定数を抽出できるようになります。
    • 定数をフィルタリングする正規表現にCLONE_[A-Z_]+が追加されました。これにより、mkerrors.shCLONE_で始まるすべての定数をGoのコードに含めるように指示されます。
  2. src/pkg/syscall/zerrors_linux_386.go, src/pkg/syscall/zerrors_linux_amd64.go, src/pkg/syscall/zerrors_linux_arm.goの変更:

    • これらのファイルはmkerrors.shスクリプトによって自動生成されるファイルであり、各アーキテクチャ(386, amd64, arm)向けのLinuxシステムコール定数が含まれています。
    • このコミットにより、これらのファイルにCLONE_CHILD_CLEARTIDCLONE_CHILD_SETTIDCLONE_DETACHEDなど、多数のCLONE_*定数が追加されました。これらの定数は、対応するLinuxカーネルのヘッダファイルで定義されている値と一致します。
    • また、これらのファイルから不要な//line _const.go:Xのようなコメント行が削除されています。これは、cgo -godefsの出力形式の変更によるものと考えられます。

これらの変更により、Goプログラムはsyscall.CLONE_VMのように、Goの定数としてCLONE_*フラグを参照できるようになり、cloneシステムコールを呼び出す際にこれらのフラグを安全かつ可読性の高い方法で利用できるようになります。

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

src/pkg/syscall/mkerrors.sh

--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -100,6 +100,7 @@ includes_Linux='\
 #include <linux/reboot.h>
 #include <linux/rtnetlink.h>
 #include <linux/ptrace.h>
+#include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/icmpv6.h>
 #include <net/if.h>
@@ -243,6 +244,7 @@ ccflags="$@"
 		$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
 		$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ ||
 		$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
+\t\t$2 ~ /^CLONE_[A-Z_]+/ ||
 		$2 !~ /^(BPF_TIMEVAL)$/ &&
 		$2 ~ /^(BPF|DLT)_/ ||
 		$2 !~ "WMESGLEN" &&

src/pkg/syscall/zerrors_linux_386.go (amd64, armも同様の追加)

--- a/src/pkg/syscall/zerrors_linux_386.go
+++ b/src/pkg/syscall/zerrors_linux_386.go
@@ -4,12 +4,8 @@
 // Created by cgo -godefs - DO NOT EDIT
 // cgo -godefs -- -m32 _const.go
 
-//line _const.go:1
 package syscall
 
-//line _const.go:51
-//
-//line _const.go:50
 const (
 	AF_ALG                           = 0x26
 	AF_APPLETALK                     = 0x5
@@ -150,6 +146,28 @@ const (
 	BPF_TXA                          = 0x80
 	BPF_W                            = 0x0
 	BPF_X                            = 0x8
+\tCLONE_CHILD_CLEARTID             = 0x200000
+\tCLONE_CHILD_SETTID               = 0x1000000
+\tCLONE_DETACHED                   = 0x400000
+\tCLONE_FILES                      = 0x400
+\tCLONE_FS                         = 0x200
+\tCLONE_IO                         = 0x80000000
+\tCLONE_NEWIPC                     = 0x8000000
+\tCLONE_NEWNET                     = 0x40000000
+\tCLONE_NEWNS                      = 0x20000
+\tCLONE_NEWPID                     = 0x20000000
+\tCLONE_NEWUSER                    = 0x10000000
+\tCLONE_NEWUTS                     = 0x4000000
+\tCLONE_PARENT                     = 0x8000
+\tCLONE_PARENT_SETTID              = 0x100000
+\tCLONE_PTRACE                     = 0x2000
+\tCLONE_SETTLS                     = 0x80000
+\tCLONE_SIGHAND                    = 0x800
+\tCLONE_SYSVSEM                    = 0x40000
+\tCLONE_THREAD                     = 0x10000
+\tCLONE_UNTRACED                   = 0x800000
+\tCLONE_VFORK                      = 0x4000
+\tCLONE_VM                         = 0x100
 	DT_BLK                           = 0x6
 	DT_CHR                           = 0x2
 	DT_DIR                           = 0x4

コアとなるコードの解説

mkerrors.shの変更

  • #include <linux/sched.h>の追加: この行は、mkerrors.shスクリプトがCコンパイラを使って定数を抽出する際に、linux/sched.hヘッダファイルを含めるように指示しています。このヘッダファイルには、cloneシステムコールに関連するCLONE_*フラグの定義が含まれています。これにより、スクリプトはこれらの定数の値を取得できるようになります。

  • $2 ~ /^CLONE_[A-Z_]+/ ||の追加: この正規表現は、mkerrors.shスクリプトがCヘッダファイルから抽出する定数のフィルタリングルールに追加されました。$2は定数名を指します。このパターンは、定数名がCLONE_で始まり、その後に大文字の英字またはアンダースコアが続くすべての定数を対象とすることを示しています。これにより、CLONE_VMCLONE_FILESなどのすべての関連するCLONE定数がGoのsyscallパッケージに自動的に取り込まれるようになります。

zerrors_linux_*.goファイルの変更

これらのファイルは、mkerrors.shスクリプトによって自動生成されるGoのソースファイルです。このコミットによって、以下のCLONE_*定数が各アーキテクチャ(386, amd64, arm)のLinux向けsyscallパッケージに追加されました。

  • CLONE_CHILD_CLEARTID
  • CLONE_CHILD_SETTID
  • CLONE_DETACHED
  • CLONE_FILES
  • CLONE_FS
  • CLONE_IO
  • CLONE_NEWIPC
  • CLONE_NEWNET
  • CLONE_NEWNS
  • CLONE_NEWPID
  • CLONE_NEWUSER
  • CLONE_NEWUTS
  • CLONE_PARENT
  • CLONE_PARENT_SETTID
  • CLONE_PTRACE
  • CLONE_SETTLS
  • CLONE_SIGHAND
  • CLONE_SYSVSEM
  • CLONE_THREAD
  • CLONE_UNTRACED
  • CLONE_VFORK
  • CLONE_VM

これらの定数は、それぞれ対応するLinuxカーネルのヘッダファイルで定義されている16進数の値(例: 0x200000)で初期化されています。これにより、Goプログラムはこれらの定数を使用して、cloneシステムコールを呼び出す際に必要なフラグを正確に指定できるようになります。

また、削除された//line _const.go:Xのようなコメントは、Goのツールチェーン(特にcgo)が生成するコードのメタデータの一部であり、このコミットではその出力形式がクリーンアップされたことを示唆しています。これは機能的な変更ではなく、生成されるコードの見た目を改善するものです。

関連リンク

参考にした情報源リンク