[インデックス 18314] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるファイルロック関連のAPI変更を扱っています。具体的には、Flock_t
構造体のメソッドであったLock
を、独立した関数FcntlFlock
へとリネームし、そのシグネチャを変更しています。これにより、ファイルロック操作のセマンティクスがより明確になり、Goの慣用的なスタイルに近づけられています。
コミット
commit 367ad4534f2d06e71f0182eb42ffa3e3c58da89a
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Jan 21 16:27:39 2014 -0800
syscall: rename method Flock_t.Lock to func FcntlFlock
Update #7059
R=rsc
CC=golang-codereviews
https://golang.org/cl/55370043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/367ad4534f2d06e71f0182eb42ffa3e3c58da89a
元コミット内容
このコミットの元の内容は、syscall
パッケージ内のFlock_t
型に定義されていたLock
というメソッドを、FcntlFlock
という名前の独立した関数に変更することです。
変更前:
func (lk *Flock_t) Lock(fd uintptr, cmd int) error
変更後:
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error
この変更は、Issue #7059に関連しています。
変更の背景
この変更の背景には、Go言語のAPI設計における慣用的なパターンと、fcntl
システムコールがファイルディスクリプタ(fd
)とコマンド(cmd
)を主要な引数として受け取るという性質があります。
元々Flock_t.Lock
というメソッドとして定義されていた場合、Flock_t
のインスタンスがレシーバとして渡され、そのインスタンスに対してロック操作を行うというセマンティクスを示唆します。しかし、fcntl
システムコールによるファイルロックは、特定のファイルディスクリプタに対して行われる操作であり、Flock_t
構造体自体がロック操作の「対象」というよりは、ロックの種類や範囲を記述するための「引数」としての役割が強いです。
メソッドとして定義されていると、Flock_t
がロック操作の主体であるかのような誤解を招く可能性があります。これを独立した関数FcntlFlock
として定義し、Flock_t
のポインタを引数として明示的に渡す形にすることで、fcntl
システムコールがファイルディスクリプタとコマンドを主軸とし、Flock_t
がその補助的な情報を提供するという、より正確なセマンティクスを表現できます。
また、Goの標準ライブラリでは、特定のデータ構造に密接に関連しない汎用的な操作は、メソッドではなく関数として提供されることが多いです。この変更は、GoのAPI設計ガイドラインに沿ったものと言えます。
前提知識の解説
このコミットを理解するためには、以下の前提知識が必要です。
1. fcntl
システムコール
fcntl
(ファイル制御)は、Unix系オペレーティングシステムにおけるシステムコールの一つで、オープンされたファイルディスクリプタに対して様々な操作を行うために使用されます。その機能は多岐にわたり、ファイルロック、ファイルディスクリプタの複製、ファイルステータスフラグの取得/設定などが含まれます。
fcntl
システムコールの一般的な形式は以下の通りです。
int fcntl(int fd, int cmd, ... /* arg */ );
fd
: 操作対象のファイルディスクリプタ。cmd
: 実行する操作を指定するコマンド。arg
:cmd
に応じて追加の引数。ファイルロックの場合、flock
構造体へのポインタが渡されます。
2. ファイルロック
ファイルロックは、複数のプロセスが同時に同じファイルにアクセスする際に、データの整合性を保つために使用されるメカニズムです。主に以下の2種類があります。
- 共有ロック (Shared Lock / Read Lock): 複数のプロセスが同時に取得でき、読み取り操作に適しています。
- 排他ロック (Exclusive Lock / Write Lock): 一度に1つのプロセスしか取得できず、書き込み操作に適しています。
fcntl
システムコールでは、F_GETLK
, F_SETLK
, F_SETLKW
といったコマンドを使用してファイルロックを操作します。
3. flock
構造体 (Unix/Linux)
fcntl
システムコールでファイルロックを操作する際に使用される構造体で、ロックの種類、開始オフセット、長さ、プロセスIDなどを指定します。Goのsyscall
パッケージでは、これをFlock_t
として抽象化しています。
一般的なflock
構造体のメンバーは以下の通りです(システムによって異なる場合があります)。
l_type
: ロックの種類(F_RDLCK
:共有ロック、F_WRLCK
:排他ロック、F_UNLCK
:ロック解除)。l_whence
: ロック範囲の開始オフセットの基準(SEEK_SET
:ファイルの先頭から、SEEK_CUR
:現在のファイルポインタから、SEEK_END
:ファイルの末尾から)。l_start
: ロック範囲の開始オフセット。l_len
: ロック範囲の長さ。l_pid
: ロックを保持しているプロセスのID(F_GETLK
で使用)。
4. F_GETLK
, F_SETLK
, F_SETLKW
コマンド
F_GETLK
: 指定されたロック(flock
構造体で記述)が、他のプロセスによってブロックされるかどうかをテストします。ブロックされる場合、そのロックを保持しているプロセスの情報がflock
構造体に書き込まれます。ロックが取得可能であれば、l_type
はF_UNLCK
に設定されます。F_SETLK
: 指定されたロックを設定または解除します。ロックがすぐに取得できない場合、エラー(EAGAIN
またはEACCES
)を返します。非ブロック操作です。F_SETLKW
:F_SETLK
と同様にロックを設定または解除しますが、ロックがすぐに取得できない場合、ロックが利用可能になるまで呼び出し元のプロセスをブロック(待機)させます。ブロック操作です。
5. Go言語のsyscall
パッケージ
Go言語のsyscall
パッケージは、低レベルなオペレーティングシステムプリミティブへのアクセスを提供します。これには、システムコール、プロセス管理、ファイルシステム操作などが含まれます。このパッケージは、OS固有の機能に直接アクセスする必要がある場合に使用されますが、通常はより高レベルな標準ライブラリ(例: os
パッケージ)を使用することが推奨されます。
技術的詳細
このコミットの技術的な核心は、Goのsyscall
パッケージにおけるfcntl
システムコールのラッパー関数の設計変更です。
変更前の設計 (Flock_t.Lock
メソッド)
// Lock performs a fcntl syscall for F_GETLK, F_SETLK or F_SETLKW commands.
func (lk *Flock_t) Lock(fd uintptr, cmd int) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
if errno == 0 {
return nil
}
return errno
}
変更前は、Flock_t
構造体のポインタlk
をレシーバとするメソッドLock
として定義されていました。この設計では、Flock_t
のインスタンスがロック操作の「主体」であるかのように見えます。しかし、実際のfcntl
システムコールは、ファイルディスクリプタfd
とコマンドcmd
が主要な引数であり、Flock_t
はcmd
に応じた追加情報を提供する役割です。
変更後の設計 (FcntlFlock
関数)
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
if errno == 0 {
return nil
}
return errno
}
変更後は、FcntlFlock
という独立した関数として定義され、Flock_t
のポインタlk
は明示的な引数として渡されます。この変更により、関数シグネチャがfcntl
システムコールの引数の順序(fd
, cmd
, flock_ptr
)とより密接に一致し、APIの意図がより明確になります。
fd uintptr
: ロック操作を行うファイルディスクリプタ。cmd int
:F_GETLK
,F_SETLK
,F_SETLKW
などのfcntl
コマンド。lk *Flock_t
: ロックの種類、範囲、その他の詳細を記述するFlock_t
構造体へのポインタ。
この変更は、GoのAPI設計原則である「明確さ」と「慣用性」を追求したものです。Flock_t
はロック操作のパラメータであり、操作自体はファイルディスクリプタに対して行われるという事実を、関数シグネチャがより正確に反映するようになりました。
また、fcntl64Syscall
という変数を使用している点も注目に値します。これは、32ビットシステムでSYS_FCNTL64
を使用する必要がある場合に対応するための抽象化です。これにより、異なるアーキテクチャ間での互換性が保たれています。
コアとなるコードの変更箇所
--- a/src/pkg/syscall/flock.go
+++ b/src/pkg/syscall/flock.go
@@ -12,8 +12,8 @@ import "unsafe"
// systems by flock_linux_32bit.go to be SYS_FCNTL64.
var fcntl64Syscall uintptr = SYS_FCNTL
-// Lock performs a fcntl syscall for F_GETLK, F_SETLK or F_SETLKW commands.
-func (lk *Flock_t) Lock(fd uintptr, cmd int) error {
+// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
+func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
if errno == 0 {
return nil
コアとなるコードの解説
変更はsrc/pkg/syscall/flock.go
ファイル内で行われています。
- 行12-13: コメントが更新され、
fcntl64Syscall
変数がSYS_FCNTL
またはSYS_FCNTL64
のいずれかになることが示されています。これは、異なるシステム(特に32ビットLinuxシステム)でのfcntl
システムコールのバリエーションに対応するためです。 - 行15 (削除):
func (lk *Flock_t) Lock(fd uintptr, cmd int) error {
という行が削除されました。これは、Flock_t
型のメソッドとしてのLock
の定義です。 - 行16 (追加):
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
という行が追加されました。これは、独立した関数FcntlFlock
の定義です。引数の順序が変更され、lk *Flock_t
が明示的な引数として追加されています。 - 行17-21: 関数の本体は変更されていません。
Syscall
関数を呼び出して実際のfcntl
システムコールを実行し、その結果(エラーコードerrno
)を返しています。unsafe.Pointer(lk)
は、Flock_t
構造体へのポインタをuintptr
に変換し、システムコールに渡すために使用されます。
この変更は、APIのセマンティクスを改善し、Goの慣用的なスタイルに合わせるためのリファクタリングです。機能的な変更は伴わず、既存の動作は維持されます。
関連リンク
- Go Issue 7059: https://github.com/golang/go/issues/7059 (このコミットが解決したIssue)
- Go Code Review 55370043: https://golang.org/cl/55370043 (このコミットのコードレビュー)
参考にした情報源リンク
fcntl
man page: https://man7.org/linux/man-pages/man2/fcntl.2.html- Go
syscall
package documentation: https://pkg.go.dev/syscall - Go
unsafe
package documentation: https://pkg.go.dev/unsafe - Go言語のAPI設計に関する一般的なガイドライン (Goの公式ドキュメントやブログ記事を参照)
- 例: https://go.dev/blog/package-names (パッケージ名に関するものだが、API設計全般の思想が垣間見える)
- 例: https://go.dev/doc/effective_go (Effective Go)
- 例: https://go.dev/doc/code (Go Code Review Comments)
[インデックス 18314] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるファイルロック関連のAPI変更を扱っています。具体的には、Flock_t
構造体のメソッドであったLock
を、独立した関数FcntlFlock
へとリネームし、そのシグネチャを変更しています。これにより、ファイルロック操作のセマンティクスがより明確になり、Goの慣用的なスタイルに近づけられています。
コミット
commit 367ad4534f2d06e71f0182eb42ffa3e3c58da89a
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Jan 21 16:27:39 2014 -0800
syscall: rename method Flock_t.Lock to func FcntlFlock
Update #7059
R=rsc
CC=golang-codereviews
https://golang.org/cl/55370043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/367ad4534f2d06e71f0182eb42ffa3e3c58da89a
元コミット内容
このコミットの元の内容は、syscall
パッケージ内のFlock_t
型に定義されていたLock
というメソッドを、FcntlFlock
という名前の独立した関数に変更することです。
変更前:
func (lk *Flock_t) Lock(fd uintptr, cmd int) error
変更後:
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error
この変更は、Issue #7059に関連しています。
変更の背景
この変更の背景には、Go言語のAPI設計における慣用的なパターンと、fcntl
システムコールがファイルディスクリプタ(fd
)とコマンド(cmd
)を主要な引数として受け取るという性質があります。
元々Flock_t.Lock
というメソッドとして定義されていた場合、Flock_t
のインスタンスがレシーバとして渡され、そのインスタンスに対してロック操作を行うというセマンティクスを示唆します。しかし、fcntl
システムコールによるファイルロックは、特定のファイルディスクリプタに対して行われる操作であり、Flock_t
構造体自体がロック操作の「対象」というよりは、ロックの種類や範囲を記述するための「引数」としての役割が強いです。
メソッドとして定義されていると、Flock_t
がロック操作の主体であるかのような誤解を招く可能性があります。これを独立した関数FcntlFlock
として定義し、Flock_t
のポインタを引数として明示的に渡す形にすることで、fcntl
システムコールがファイルディスクリプタとコマンドを主軸とし、Flock_t
がその補助的な情報を提供するという、より正確なセマンティクスを表現できます。
また、Goの標準ライブラリでは、特定のデータ構造に密接に関連しない汎用的な操作は、メソッドではなく関数として提供されることが多いです。この変更は、GoのAPI設計ガイドラインに沿ったものと言えます。
前提知識の解説
このコミットを理解するためには、以下の前提知識が必要です。
1. fcntl
システムコール
fcntl
(ファイル制御)は、Unix系オペレーティングシステムにおけるシステムコールの一つで、オープンされたファイルディスクリプタに対して様々な操作を行うために使用されます。その機能は多岐にわたり、ファイルロック、ファイルディスクリプタの複製、ファイルステータスフラグの取得/設定などが含まれます。
fcntl
システムコールの一般的な形式は以下の通りです。
int fcntl(int fd, int cmd, ... /* arg */ );
fd
: 操作対象のファイルディスクリプタ。cmd
: 実行する操作を指定するコマンド。arg
:cmd
に応じて追加の引数。ファイルロックの場合、flock
構造体へのポインタが渡されます。
2. ファイルロック
ファイルロックは、複数のプロセスが同時に同じファイルにアクセスする際に、データの整合性を保つために使用されるメカニズムです。主に以下の2種類があります。
- 共有ロック (Shared Lock / Read Lock): 複数のプロセスが同時に取得でき、読み取り操作に適しています。
- 排他ロック (Exclusive Lock / Write Lock): 一度に1つのプロセスしか取得できず、書き込み操作に適しています。
fcntl
システムコールでは、F_GETLK
, F_SETLK
, F_SETLKW
といったコマンドを使用してファイルロックを操作します。
3. flock
構造体 (Unix/Linux)
fcntl
システムコールでファイルロックを操作する際に使用される構造体で、ロックの種類、開始オフセット、長さ、プロセスIDなどを指定します。Goのsyscall
パッケージでは、これをFlock_t
として抽象化しています。
一般的なflock
構造体のメンバーは以下の通りです(システムによって異なる場合があります)。
l_type
: ロックの種類(F_RDLCK
:共有ロック、F_WRLCK
:排他ロック、F_UNLCK
:ロック解除)。l_whence
: ロック範囲の開始オフセットの基準(SEEK_SET
:ファイルの先頭から、SEEK_CUR
:現在のファイルポインタから、SEEK_END
:ファイルの末尾から)。l_start
: ロック範囲の開始オフセット。l_len
: ロック範囲の長さ。l_pid
: ロックを保持しているプロセスのID(F_GETLK
で使用)。
4. F_GETLK
, F_SETLK
, F_SETLKW
コマンド
F_GETLK
: 指定されたロック(flock
構造体で記述)が、他のプロセスによってブロックされるかどうかをテストします。ブロックされる場合、そのロックを保持しているプロセスの情報がflock
構造体に書き込まれます。ロックが取得可能であれば、l_type
はF_UNLCK
に設定されます。F_SETLK
: 指定されたロックを設定または解除します。ロックがすぐに取得できない場合、エラー(EAGAIN
またはEACCES
)を返します。非ブロック操作です。F_SETLKW
:F_SETLK
と同様にロックを設定または解除しますが、ロックがすぐに取得できない場合、ロックが利用可能になるまで呼び出し元のプロセスをブロック(待機)させます。ブロック操作です。
5. Go言語のsyscall
パッケージ
Go言語のsyscall
パッケージは、低レベルなオペレーティングシステムプリミティブへのアクセスを提供します。これには、システムコール、プロセス管理、ファイルシステム操作などが含まれます。このパッケージは、OS固有の機能に直接アクセスする必要がある場合に使用されますが、通常はより高レベルな標準ライブラリ(例: os
パッケージ)を使用することが推奨されます。
技術的詳細
このコミットの技術的な核心は、Goのsyscall
パッケージにおけるfcntl
システムコールのラッパー関数の設計変更です。
変更前の設計 (Flock_t.Lock
メソッド)
// Lock performs a fcntl syscall for F_GETLK, F_SETLK or F_SETLKW commands.
func (lk *Flock_t) Lock(fd uintptr, cmd int) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
if errno == 0 {
return nil
}
return errno
}
変更前は、Flock_t
構造体のポインタlk
をレシーバとするメソッドLock
として定義されていました。この設計では、Flock_t
のインスタンスがロック操作の「主体」であるかのように見えます。しかし、実際のfcntl
システムコールは、ファイルディスクリプタfd
とコマンドcmd
が主要な引数であり、Flock_t
はcmd
に応じた追加情報を提供する役割です。
変更後の設計 (FcntlFlock
関数)
// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
if errno == 0 {
return nil
}
return errno
}
変更後は、FcntlFlock
という独立した関数として定義され、Flock_t
のポインタlk
は明示的な引数として渡されます。この変更により、関数シグネチャがfcntl
システムコールの引数の順序(fd
, cmd
, flock_ptr
)とより密接に一致し、APIの意図がより明確になります。
fd uintptr
: ロック操作を行うファイルディスクリプタ。cmd int
:F_GETLK
,F_SETLK
,F_SETLKW
などのfcntl
コマンド。lk *Flock_t
: ロックの種類、範囲、その他の詳細を記述するFlock_t
構造体へのポインタ。
この変更は、GoのAPI設計原則である「明確さ」と「慣用性」を追求したものです。Flock_t
はロック操作のパラメータであり、操作自体はファイルディスクリプタに対して行われるという事実を、関数シグネチャがより正確に反映するようになりました。
また、fcntl64Syscall
という変数を使用している点も注目に値します。これは、32ビットシステムでSYS_FCNTL64
を使用する必要がある場合に対応するための抽象化です。これにより、異なるアーキテクチャ間での互換性が保たれています。
コアとなるコードの変更箇所
--- a/src/pkg/syscall/flock.go
+++ b/src/pkg/syscall/flock.go
@@ -12,8 +12,8 @@ import "unsafe"
// systems by flock_linux_32bit.go to be SYS_FCNTL64.
var fcntl64Syscall uintptr = SYS_FCNTL
-// Lock performs a fcntl syscall for F_GETLK, F_SETLK or F_SETLKW commands.
-func (lk *Flock_t) Lock(fd uintptr, cmd int) error {
+// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
+func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
_, _, errno := Syscall(fcntl64Syscall, fd, uintptr(cmd), uintptr(unsafe.Pointer(lk)))
if errno == 0 {
return nil
コアとなるコードの解説
変更はsrc/pkg/syscall/flock.go
ファイル内で行われています。
- 行12-13: コメントが更新され、
fcntl64Syscall
変数がSYS_FCNTL
またはSYS_FCNTL64
のいずれかになることが示されています。これは、異なるシステム(特に32ビットLinuxシステム)でのfcntl
システムコールのバリエーションに対応するためです。 - 行15 (削除):
func (lk *Flock_t) Lock(fd uintptr, cmd int) error {
という行が削除されました。これは、Flock_t
型のメソッドとしてのLock
の定義です。 - 行16 (追加):
func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
という行が追加されました。これは、独立した関数FcntlFlock
の定義です。引数の順序が変更され、lk *Flock_t
が明示的な引数として追加されています。 - 行17-21: 関数の本体は変更されていません。
Syscall
関数を呼び出して実際のfcntl
システムコールを実行し、その結果(エラーコードerrno
)を返しています。unsafe.Pointer(lk)
は、Flock_t
構造体へのポインタをuintptr
に変換し、システムコールに渡すために使用されます。
この変更は、APIのセマンティクスを改善し、Goの慣用的なスタイルに合わせるためのリファクタリングです。機能的な変更は伴わず、既存の動作は維持されます。
関連リンク
- Go Issue 7059: https://github.com/golang/go/issues/7059 (このコミットが解決したIssue)
- Go Code Review 55370043: https://golang.org/cl/55370043 (このコミットのコードレビュー)
参考にした情報源リンク
fcntl
man page: https://man7.org/linux/man-pages/man2/fcntl.2.html- Go
syscall
package documentation: https://pkg.go.dev/syscall - Go
unsafe
package documentation: https://pkg.go.dev/unsafe - Go言語のAPI設計に関する一般的なガイドライン (Goの公式ドキュメントやブログ記事を参照)
- 例: https://go.dev/blog/package-names (パッケージ名に関するものだが、API設計全般の思想が垣間見える)
- 例: https://go.dev/doc/effective_go (Effective Go)
- 例: https://go.dev/doc/code (Go Code Review Comments)