[インデックス 10664] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、Linuxシステムコールであるflock()
をサポートするために必要な定数を追加するものです。具体的には、LOCK_SH
(共有ロック)、LOCK_EX
(排他ロック)、LOCK_NB
(非ブロックモード)、LOCK_UN
(ロック解除) といったflock()
に関連する定数が、i386およびamd64アーキテクチャ向けのzerrors_linux_386.go
とzerrors_linux_amd64.go
ファイルに追加されました。これらの定数は、mkerrors.sh
スクリプトによって自動生成されるように設定が更新されています。
コミット
commit 83c30f3ec28cc87b8814fb29c7bd88c311dace58
Author: Andrea Spadaccini <spadaccio@google.com>
Date: Thu Dec 8 15:12:08 2011 +0900
syscall: add constants for flock() system call under Linux.
The values have been generated only for the i386 and amd64 architectures.
R=golang-dev, mikioh.mikioh, dsymonds
CC=bradfitz, dsymonds, golang-dev
https://golang.org/cl/5452060
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/83c30f3ec28cc87b8814fb29c7bd88c311dace58
元コミット内容
Linuxシステムコールflock()
のための定数をsyscall
パッケージに追加しました。これらの値はi386とamd64アーキテクチャ向けに生成されています。
変更の背景
Go言語の標準ライブラリであるsyscall
パッケージは、オペレーティングシステムが提供する低レベルな機能(システムコール)へのアクセスを提供します。flock()
はUnix系システムにおけるファイルロックのための重要なシステムコールであり、複数のプロセスが同時にファイルにアクセスする際にデータの整合性を保つために使用されます。
このコミット以前は、Goのsyscall
パッケージにはLinuxのflock()
システムコールを直接利用するための必要な定数が含まれていませんでした。これにより、Goプログラムからflock()
を呼び出す際に、これらの定数を手動で定義するか、あるいはCgoを介してC言語のライブラリを呼び出す必要がありました。これはGoの哲学である「シンプルさ」や「効率性」に反するものであり、またクロスプラットフォーム対応の観点からも望ましくありませんでした。
この変更の背景には、Goプログラムがよりネイティブに、かつ効率的にLinuxのファイルロック機能を利用できるようにするという目的があります。特に、ファイルベースのデータストアや、複数のGoプロセスが共有ファイルにアクセスするようなアプリケーションにおいて、flock()
のサポートは不可欠です。
前提知識の解説
flock()
システムコール
flock()
は、Unix系オペレーティングシステムで提供されるファイルロックのためのシステムコールです。これは、ファイル全体に対するアドバイザリロック(協調ロック)を提供します。アドバイザリロックとは、OSがロックの強制を行わず、アプリケーションがロックの規則に従うことを期待するロックメカニズムです。
flock()
には主に以下の2種類のロックがあります。
- 共有ロック (Shared Lock):
LOCK_SH
で指定されます。複数のプロセスが同時にファイルに対して共有ロックを取得できます。これは主に読み取りアクセスに使用されます。 - 排他ロック (Exclusive Lock):
LOCK_EX
で指定されます。一度に1つのプロセスのみがファイルに対して排他ロックを取得できます。これは主に書き込みアクセスに使用されます。
また、ロックの動作を制御するためのフラグも存在します。
- 非ブロックモード (Non-blocking):
LOCK_NB
で指定されます。ロックがすぐに取得できない場合、flock()
はブロックせずにエラーを返します。 - ロック解除 (Unlock):
LOCK_UN
で指定されます。ファイルから既存のロックを解除します。
flock()
は、open()
で開かれたファイルディスクリプタに対して適用され、プロセスが終了するか、ファイルディスクリプタが閉じられるか、明示的にLOCK_UN
でロックが解除されるまで有効です。
Go言語の syscall
パッケージ
Go言語のsyscall
パッケージは、低レベルなオペレーティングシステムプリミティブへのインターフェースを提供します。これには、システムコール、プロセス管理、ファイルI/O、ネットワーク操作などが含まれます。このパッケージは、GoプログラムがOS固有の機能に直接アクセスできるようにするために使用されます。
syscall
パッケージは、各OSおよびアーキテクチャに特化した定数や関数を多数含んでいます。これらの定数は、通常、C言語のヘッダーファイル(例: /usr/include/sys/file.h
)で定義されている値に対応します。Goのビルドシステムは、これらのOS固有の定数を自動生成するためのスクリプト(例: mkerrors.sh
)を使用することがよくあります。
mkerrors.sh
スクリプトと zerrors_linux_*.go
ファイル
Goのsyscall
パッケージでは、OSやアーキテクチャに依存する定数やエラーコードを自動生成するために、mkerrors.sh
のようなスクリプトが使用されます。これらのスクリプトは、C言語のヘッダーファイルを解析し、対応するGoの定数定義を生成します。
生成された定数は、zerrors_linux_386.go
やzerrors_linux_amd64.go
のようなファイルに格納されます。ファイル名のz
は、これらのファイルが自動生成されたものであることを示す慣例的なプレフィックスです。linux_386
やlinux_amd64
は、それぞれLinuxオペレーティングシステム上の32ビットIntelアーキテクチャ(i386)と64ビットIntelアーキテクチャ(amd64)に対応することを示しています。これにより、Goは異なるOSやCPUアーキテクチャに対して適切なシステムコール定数を提供できます。
技術的詳細
このコミットの技術的な核心は、Goのsyscall
パッケージがLinuxのflock()
システムコールをネイティブにサポートするために、必要な定数を追加し、その自動生成プロセスを更新した点にあります。
-
mkerrors.sh
の更新:src/pkg/syscall/mkerrors.sh
スクリプトは、C言語のヘッダーファイルからGoの定数を生成するためのものです。このコミットでは、以下の変更が加えられました。#include <sys/file.h>
の追加:flock()
に関連する定数(LOCK_SH
,LOCK_EX
など)は、通常、C言語のsys/file.h
ヘッダーファイルで定義されています。この行を追加することで、mkerrors.sh
がこれらの定数を認識し、その値を抽出できるようになります。$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
の追加: これは正規表現パターンであり、mkerrors.sh
がCヘッダーファイルから抽出するシンボル名のリストに、LOCK_SH
、LOCK_EX
、LOCK_NB
、LOCK_UN
といったパターンに一致する定数を含めるように指示します。これにより、これらのflock()
関連定数がGoのsyscall
パッケージに自動的に取り込まれるようになります。
-
zerrors_linux_386.go
およびzerrors_linux_amd64.go
への定数追加:mkerrors.sh
スクリプトが実行されると、その出力としてzerrors_linux_386.go
とzerrors_linux_amd64.go
ファイルが更新されます。これらのファイルには、Linuxのi386およびamd64アーキテクチャにおけるflock()
定数の実際の値がGoのconst
として追加されます。追加された定数は以下の通りです。
LOCK_EX = 0x2
(排他ロック)LOCK_NB = 0x4
(非ブロックモード)LOCK_SH = 0x1
(共有ロック)LOCK_UN = 0x8
(ロック解除)
これらの16進数の値は、Linuxカーネルの内部で定義されている
flock()
操作に対応するビットフラグの値と一致します。Goプログラムはこれらの定数を使用することで、syscall.Flock()
のような関数を呼び出す際に、適切なロックタイプや動作を指定できるようになります。
この変更により、Go開発者はLinux上でファイルロックを実装する際に、Cgoを介さずにGoのsyscall
パッケージを直接利用できるようになり、コードの可読性、移植性、およびパフォーマンスが向上します。
コアとなるコードの変更箇所
src/pkg/syscall/mkerrors.sh
--- a/src/pkg/syscall/mkerrors.sh
+++ b/src/pkg/syscall/mkerrors.sh
@@ -108,6 +108,7 @@ includes_OpenBSD='\
includes='\
#include <sys/types.h>\
+#include <sys/file.h>\
#include <fcntl.h>\
#include <dirent.h>\
#include <sys/socket.h>\
@@ -153,6 +154,7 @@ ccflags="$@"\
$2 ~ /^E[A-Z0-9_]+$/ ||\
$2 ~ /^SIG[^_]/ ||\
$2 ~ /^IN_/ ||\
+\t\t$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)_/ ||\
$2 == "SOMAXCONN" ||\
$2 == "NAME_MAX" ||
src/pkg/syscall/zerrors_linux_386.go
--- a/src/pkg/syscall/zerrors_linux_386.go
+++ b/src/pkg/syscall/zerrors_linux_386.go
@@ -478,6 +478,10 @@ const (
LINUX_REBOOT_CMD_SW_SUSPEND = 0xd000fce2
LINUX_REBOOT_MAGIC1 = 0xfee1dead
LINUX_REBOOT_MAGIC2 = 0x28121969
+ LOCK_EX = 0x2
+ LOCK_NB = 0x4
+ LOCK_SH = 0x1
+ LOCK_UN = 0x8
MADV_DOFORK = 0xb
MADV_DONTFORK = 0xa
MADV_DONTNEED = 0x4
src/pkg/syscall/zerrors_linux_amd64.go
--- a/src/pkg/syscall/zerrors_linux_amd64.go
+++ b/src/pkg/syscall/zerrors_linux_amd64.go
@@ -478,6 +478,10 @@ const (
LINUX_REBOOT_CMD_SW_SUSPEND = 0xd000fce2
LINUX_REBOOT_MAGIC1 = 0xfee1dead
LINUX_REBOOT_MAGIC2 = 0x28121969
+ LOCK_EX = 0x2
+ LOCK_NB = 0x4
+ LOCK_SH = 0x1
+ LOCK_UN = 0x8
MADV_DOFORK = 0xb
MADV_DONTFORK = 0xa
MADV_DONTNEED = 0x4
コアとなるコードの解説
src/pkg/syscall/mkerrors.sh
の変更
-
#include <sys/file.h>
の追加: この行は、mkerrors.sh
スクリプトがC言語のヘッダーファイルを解析する際に、sys/file.h
の内容も読み込むように指示します。flock()
システムコールに関連する定数(LOCK_SH
,LOCK_EX
,LOCK_NB
,LOCK_UN
)は、このヘッダーファイルで定義されているため、これを含めることでスクリプトがこれらの定数の値を取得できるようになります。 -
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
の追加: これは、mkerrors.sh
スクリプト内の正規表現パターンを拡張するものです。スクリプトはCヘッダーファイルから様々な定数を抽出しますが、このパターンを追加することで、LOCK_
で始まり、その後にSH
、EX
、NB
、UN
のいずれかが続く定数名も抽出対象に含めるようになります。これにより、flock()
に必要な定数がGoのコードに自動的にマッピングされるようになります。
src/pkg/syscall/zerrors_linux_386.go
および src/pkg/syscall/zerrors_linux_amd64.go
の変更
これらのファイルは、mkerrors.sh
スクリプトによって自動生成されるGoのソースファイルであり、Linuxシステムコールに関連する定数が定義されています。このコミットにより、以下のflock()
関連定数が追加されました。
LOCK_EX = 0x2
: 排他ロックの定数。ファイルに対して書き込みアクセスを行う際に使用され、他のプロセスが同時にロックを取得することを防ぎます。LOCK_NB = 0x4
: 非ブロックモードの定数。flock()
呼び出し時にこのフラグを指定すると、ロックがすぐに取得できない場合にブロックせずにエラーを返します。LOCK_SH = 0x1
: 共有ロックの定数。ファイルに対して読み取りアクセスを行う際に使用され、複数のプロセスが同時に共有ロックを取得できます。LOCK_UN = 0x8
: ロック解除の定数。ファイルに設定されているロックを明示的に解除するために使用されます。
これらの定数がGoのsyscall
パッケージに直接追加されたことで、Goプログラムはこれらのシンボリックな定数名を使用してflock()
システムコールを呼び出すことが可能になり、コードの可読性と保守性が向上します。また、これらの値はLinuxカーネルが期待する正確な値であるため、GoプログラムがLinuxのファイルロック機能を正しく利用できるようになります。
関連リンク
参考にした情報源リンク
flock(2)
- Linux man page: https://man7.org/linux/man-pages/man2/flock.2.html- Go
syscall
package documentation: https://pkg.go.dev/syscall sys/file.h
(通常はLinuxシステム上に存在):/usr/include/sys/file.h
(ローカルファイルシステムパス)