[インデックス 13538] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおけるPrlimit
関数のエクスポート状態を修正するものです。具体的には、誤ってエクスポートされていたPrlimit
関数を非エクスポート(内部関数)に変更しています。
コミット
commit 36fe436cbac4d2a55d06063de966798fc2216156
Author: Han-Wen Nienhuys <hanwen@google.com>
Date: Tue Jul 31 08:21:24 2012 +1000
pkg/syscall: unexport Prlimit.
This syscall was inadvertently exported when fixing
Getrlimit/Setrlimit on 32-bit platforms.
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/6458051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/36fe436cbac4d2a55d06063de966798fc2216156
元コミット内容
pkg/syscall: unexport Prlimit.
This syscall was inadvertently exported when fixing
Getrlimit/Setrlimit on 32-bit platforms.
変更の背景
このコミットの背景には、Go言語のsyscall
パッケージにおけるGetrlimit
およびSetrlimit
関数の32ビットプラットフォームでの修正があります。以前の修正作業中に、Prlimit
というシステムコールをラップする関数が意図せずエクスポート(外部からアクセス可能)されてしまいました。Go言語の慣習として、パッケージ内部でのみ使用されるべき関数は非エクスポート(小文字で始まる名前)にするべきであり、このPrlimit
関数もその原則に従うべきでした。
Prlimit
は、特定のプロセス(pid
)のリソース制限(rlimit
)を取得または設定するためのシステムコールです。Getrlimit
やSetrlimit
は、現在のプロセス(pid=0
)のリソース制限を操作するための高レベルな関数であり、内部的にPrlimit
を利用することがあります。しかし、Prlimit
自体は、Goのユーザーが直接呼び出すことを意図したものではなく、Getrlimit
やSetrlimit
のようなより抽象化されたインターフェースを通じて利用されるべきでした。
このコミットは、この「意図しないエクスポート」を修正し、Goのパッケージ設計原則とAPIの整合性を保つことを目的としています。
前提知識の解説
1. Go言語におけるエクスポートと非エクスポート
Go言語では、識別子(変数、関数、型など)の最初の文字が大文字である場合、その識別子はパッケージの外部からアクセス可能(エクスポートされる)になります。一方、最初の文字が小文字である場合、その識別子はパッケージ内部でのみアクセス可能(非エクスポートされる)です。このルールは、APIの公開範囲を制御し、パッケージの内部実装の詳細を隠蔽するために非常に重要です。
2. syscall
パッケージ
syscall
パッケージは、Goプログラムからオペレーティングシステム(OS)のシステムコールを直接呼び出すための低レベルなインターフェースを提供します。これにより、ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する機能にアクセスできます。システムコールはOSによって提供される機能であり、通常はC言語のライブラリ(例: glibc)を介して利用されますが、Goのsyscall
パッケージはGoのコードから直接これらのシステムコールを呼び出すためのラッパーを提供します。
3. rlimit
(リソース制限)
rlimit
は、Unix系OSにおいてプロセスが利用できるシステムリソース(例: オープンできるファイルの最大数、利用できるCPU時間、メモリ量など)に上限を設定するための仕組みです。各リソースには「ソフトリミット」と「ハードリミット」の2つの制限があります。
- ソフトリミット: プロセスが実際に利用できる上限。プロセスはこの制限をハードリミット以下であれば引き上げることができます。
- ハードリミット: ソフトリミットの最大値。スーパーユーザーのみがハードリミットを引き上げることができます。
これらの制限は、システム全体の安定性を保ち、特定のプロセスがリソースを過剰に消費するのを防ぐために重要です。
4. Getrlimit
と Setrlimit
システムコール
getrlimit(2)
: 現在のプロセスのリソース制限を取得するためのシステムコール。setrlimit(2)
: 現在のプロセスのリソース制限を設定するためのシステムコール。
これらのシステムコールは、通常、現在のプロセス自身のリソース制限を操作するために使用されます。
5. prlimit(2)
システムコール
prlimit(2)
(または prlimit64(2)
on Linux) は、getrlimit
やsetrlimit
のより汎用的なバージョンです。これは、特定のプロセスID (pid
) を指定して、そのプロセスのリソース制限を取得または設定することができます。pid
が0の場合、呼び出し元のプロセスのリソース制限を操作します。このシステムコールは、Linuxカーネル2.6.36以降で利用可能です。
技術的詳細
このコミットは、Goのsyscall
パッケージ内でPrlimit
という名前でエクスポートされていた関数を、prlimit
という非エクスポート名に変更することで、その公開範囲を制限しています。
Goのsyscall
パッケージは、OSのシステムコールをGoの関数としてラップしています。これらのラッパー関数は、通常、//sys
または//sysnb
という特殊なコメントでマークされ、zsyscall_linux_*.go
のようなファイルに自動生成されるコードの一部となります。
元のコードでは、Prlimit
関数がSYS_PRLIMIT64
システムコールを呼び出すように定義されており、その名前がPrlimit
(大文字始まり)であったため、パッケージ外部からアクセス可能でした。しかし、Getrlimit
やSetrlimit
のような高レベルな関数が内部的にPrlimit
を利用するだけであり、ユーザーが直接Prlimit
を呼び出す必要はないという設計意図がありました。
この変更により、Prlimit
はprlimit
にリネームされ、Goの命名規則に従って非エクスポート関数となりました。これにより、syscall
パッケージの外部からはprlimit
関数に直接アクセスできなくなり、APIのクリーンさとカプセル化が向上します。
また、この変更は、syscall_linux_386.go
とsyscall_linux_arm.go
内のGetrlimit
およびSetrlimit
関数が、内部的にPrlimit
ではなくprlimit
を呼び出すように修正されています。これは、Prlimit
が非エクスポートされたことに伴う必然的な変更です。
コアとなるコードの変更箇所
このコミットでは、以下のファイルが変更されています。
src/pkg/syscall/syscall_linux.go
//sysnb Prlimit(...)
の行が//sysnb prlimit(...)
に変更されています。これは、Prlimit
関数が非エクスポートされることを示すためのコメントの変更です。
src/pkg/syscall/syscall_linux_386.go
Getrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。Setrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。
src/pkg/syscall/syscall_linux_arm.go
Getrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。Setrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。
src/pkg/syscall/zsyscall_linux_386.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
src/pkg/syscall/zsyscall_linux_amd64.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
src/pkg/syscall/zsyscall_linux_arm.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
コアとなるコードの解説
変更の核心は、Prlimit
という関数名をprlimit
に変更することです。
src/pkg/syscall/syscall_linux.go
の変更:
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -839,7 +839,7 @@ func Mount(source string, target string, fstype string, uintptr, data stri
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Pause() (err error)
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
-//sysnb Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
+//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
//sys Read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Rename(oldpath string, newpath string) (err error)
この変更は、Prlimit
関数がsyscall
パッケージの内部関数として扱われるべきであることを、コード生成ツールに指示するためのものです。//sysnb
コメントは、この行がシステムコールラッパーを生成するための指示であることを示しています。Prlimit
からprlimit
への変更は、Goの命名規則に従い、この関数がパッケージ外部に公開されないことを意味します。
src/pkg/syscall/syscall_linux_386.go
および src/pkg/syscall/syscall_linux_arm.go
の変更:
--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -78,7 +78,7 @@ const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)
func Getrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, rlim, nil)
+\terr = prlimit(0, resource, rlim, nil)
\tif err != ENOSYS {
\t\treturn err
\t}
@@ -106,7 +106,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, nil, rlim)
+\terr = prlimit(0, resource, nil, rlim)
\tif err != ENOSYS {
\t\treturn err
\t}
これらの変更は、Getrlimit
とSetrlimit
関数が、非エクスポートされたprlimit
関数を呼び出すように修正されたことを示しています。これは、Prlimit
が非エクスポートされた結果として必要な変更であり、これらの高レベル関数が引き続き正しく機能することを保証します。
src/pkg/syscall/zsyscall_linux_386.go
、src/pkg/syscall/zsyscall_linux_amd64.go
、src/pkg/syscall/zsyscall_linux_arm.go
の変更:
--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -598,7 +598,7 @@ func PivotRoot(newroot string, putold string) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
if e1 != 0 {
err = e1
これらのファイルは、syscall_linux.go
の//sysnb
コメントに基づいて自動生成されるシステムコールラッパーの実装を含んでいます。Prlimit
からprlimit
への関数名の変更は、これらの自動生成されたファイルにも反映され、実際のシステムコール呼び出しを行うGoの関数が非エクスポートされることを保証します。
全体として、このコミットはGoのAPI設計原則に従い、パッケージの内部実装の詳細を適切にカプセル化することで、コードの保守性と堅牢性を向上させています。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall getrlimit(2)
manページ:man 2 getrlimit
(Linuxシステムで実行)setrlimit(2)
manページ:man 2 setrlimit
(Linuxシステムで実行)prlimit(2)
manページ:man 2 prlimit
(Linuxシステムで実行)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Linux man-pages project
- GitHubのGoリポジトリのコミット履歴
- Goのコードレビューシステム (Gerrit) のCL (Change List) ページ: https://golang.org/cl/6458051
- Go言語の命名規則に関する情報 (例: Effective Go)
[インデックス 13583] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、誤ってエクスポートされていたPrlimit
関数を非エクスポート(内部関数)に変更するものです。これにより、Goのパッケージ設計原則とAPIの整合性が保たれます。
コミット
commit 36fe436cbac4d2a55d06063de966798fc2216156
Author: Han-Wen Nienhuys <hanwen@google.com>
Date: Tue Jul 31 08:21:24 2012 +1000
pkg/syscall: unexport Prlimit.
This syscall was inadvertently exported when fixing
Getrlimit/Setrlimit on 32-bit platforms.
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/6458051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/36fe436cbac4d2a55d06063de966798fc2216156
元コミット内容
pkg/syscall: unexport Prlimit.
This syscall was inadvertently exported when fixing
Getrlimit/Setrlimit on 32-bit platforms.
変更の背景
このコミットの背景には、Go言語のsyscall
パッケージにおけるGetrlimit
およびSetrlimit
関数の32ビットプラットフォームでの修正作業があります。以前の修正中に、Prlimit
というシステムコールをラップする関数が意図せずエクスポート(外部からアクセス可能)されてしまいました。Go言語の慣習として、パッケージ内部でのみ使用されるべき関数は非エクスポート(小文字で始まる名前)にするべきであり、このPrlimit
関数もその原則に従うべきでした。
Prlimit
は、特定のプロセス(pid
)のリソース制限(rlimit
)を取得または設定するためのシステムコールです。Getrlimit
やSetrlimit
は、現在のプロセス(pid=0
)のリソース制限を操作するための高レベルな関数であり、内部的にPrlimit
を利用することがあります。しかし、Prlimit
自体は、Goのユーザーが直接呼び出すことを意図したものではなく、Getrlimit
やSetrlimit
のようなより抽象化されたインターフェースを通じて利用されるべきでした。
このコミットは、この「意図しないエクスポート」を修正し、Goのパッケージ設計原則とAPIの整合性を保つことを目的としています。
前提知識の解説
1. Go言語におけるエクスポートと非エクスポート
Go言語では、識別子(変数、関数、型など)の最初の文字が大文字である場合、その識別子はパッケージの外部からアクセス可能(エクスポートされる)になります。一方、最初の文字が小文字である場合、その識別子はパッケージ内部でのみアクセス可能(非エクスポートされる)です。このルールは、APIの公開範囲を制御し、パッケージの内部実装の詳細を隠蔽するために非常に重要です。
2. syscall
パッケージ
syscall
パッケージは、Goプログラムからオペレーティングシステム(OS)のシステムコールを直接呼び出すための低レベルなインターフェースを提供します。これにより、ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する機能にアクセスできます。システムコールはOSによって提供される機能であり、通常はC言語のライブラリ(例: glibc)を介して利用されますが、Goのsyscall
パッケージはGoのコードから直接これらのシステムコールを呼び出すためのラッパーを提供します。
3. rlimit
(リソース制限)
rlimit
は、Unix系OSにおいてプロセスが利用できるシステムリソース(例: オープンできるファイルの最大数、利用できるCPU時間、メモリ量など)に上限を設定するための仕組みです。各リソースには「ソフトリミット」と「ハードリミット」の2つの制限があります。
- ソフトリミット: プロセスが実際に利用できる上限。プロセスはこの制限をハードリミット以下であれば引き上げることができます。
- ハードリミット: ソフトリミットの最大値。スーパーユーザーのみがハードリミットを引き上げることができます。
これらの制限は、システム全体の安定性を保ち、特定のプロセスがリソースを過剰に消費するのを防ぐために重要です。
4. Getrlimit
と Setrlimit
システムコール
getrlimit(2)
: 現在のプロセスのリソース制限を取得するためのシステムコール。setrlimit(2)
: 現在のプロセスのリソース制限を設定するためのシステムコール。
これらのシステムコールは、通常、現在のプロセス自身のリソース制限を操作するために使用されます。
5. prlimit(2)
システムコール
prlimit(2)
(または prlimit64(2)
on Linux) は、getrlimit
やsetrlimit
のより汎用的なバージョンです。これは、特定のプロセスID (pid
) を指定して、そのプロセスのリソース制限を取得または設定することができます。pid
が0の場合、呼び出し元のプロセスのリソース制限を操作します。このシステムコールは、Linuxカーネル2.6.36以降で利用可能です。
技術的詳細
このコミットは、Goのsyscall
パッケージ内でPrlimit
という名前でエクスポートされていた関数を、prlimit
という非エクスポート名に変更することで、その公開範囲を制限しています。
Goのsyscall
パッケージは、OSのシステムコールをGoの関数としてラップしています。これらのラッパー関数は、通常、//sys
または//sysnb
という特殊なコメントでマークされ、zsyscall_linux_*.go
のようなファイルに自動生成されるコードの一部となります。
元のコードでは、Prlimit
関数がSYS_PRLIMIT64
システムコールを呼び出すように定義されており、その名前がPrlimit
(大文字始まり)であったため、パッケージ外部からアクセス可能でした。しかし、Getrlimit
やSetrlimit
のような高レベルな関数が内部的にPrlimit
を利用するだけであり、ユーザーが直接Prlimit
を呼び出す必要はないという設計意図がありました。
この変更により、Prlimit
はprlimit
にリネームされ、Goの命名規則に従って非エクスポート関数となりました。これにより、syscall
パッケージの外部からはprlimit
関数に直接アクセスできなくなり、APIのクリーンさとカプセル化が向上します。
また、この変更は、syscall_linux_386.go
とsyscall_linux_arm.go
内のGetrlimit
およびSetrlimit
関数が、内部的にPrlimit
ではなくprlimit
を呼び出すように修正されています。これは、Prlimit
が非エクスポートされたことに伴う必然的な変更です。
コアとなるコードの変更箇所
このコミットでは、以下のファイルが変更されています。
src/pkg/syscall/syscall_linux.go
//sysnb Prlimit(...)
の行が//sysnb prlimit(...)
に変更されています。これは、Prlimit
関数が非エクスポートされることを示すためのコメントの変更です。
src/pkg/syscall/syscall_linux_386.go
Getrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。Setrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。
src/pkg/syscall/syscall_linux_arm.go
Getrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。Setrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。
src/pkg/syscall/zsyscall_linux_386.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
src/pkg/syscall/zsyscall_linux_amd64.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
src/pkg/syscall/zsyscall_linux_arm.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
コアとなるコードの解説
変更の核心は、Prlimit
という関数名をprlimit
に変更することです。
src/pkg/syscall/syscall_linux.go
の変更:
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -839,7 +839,7 @@ func Mount(source string, target string, fstype string, uintptr, data stri
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Pause() (err error)
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
-//sysnb Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
+//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
//sys Read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Rename(oldpath string, newpath string) (err error)
この変更は、Prlimit
関数がsyscall
パッケージの内部関数として扱われるべきであることを、コード生成ツールに指示するためのものです。//sysnb
コメントは、この行がシステムコールラッパーを生成するための指示であることを示しています。Prlimit
からprlimit
への変更は、Goの命名規則に従い、この関数がパッケージ外部に公開されないことを意味します。
src/pkg/syscall/syscall_linux_386.go
および src/pkg/syscall/syscall_linux_arm.go
の変更:
--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -78,7 +78,7 @@ const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)
func Getrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, rlim, nil)
+\terr = prlimit(0, resource, rlim, nil)
\tif err != ENOSYS {
\t\treturn err
\t}
@@ -106,7 +106,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, nil, rlim)
+\terr = prlimit(0, resource, nil, rlim)
\tif err != ENOSYS {
\t\treturn err
\t}
これらの変更は、Getrlimit
とSetrlimit
関数が、非エクスポートされたprlimit
関数を呼び出すように修正されたことを示しています。これは、Prlimit
が非エクスポートされた結果として必要な変更であり、これらの高レベル関数が引き続き正しく機能することを保証します。
src/pkg/syscall/zsyscall_linux_386.go
、src/pkg/syscall/zsyscall_linux_amd64.go
、src/pkg/syscall/zsyscall_linux_arm.go
の変更:
--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -598,7 +598,7 @@ func PivotRoot(newroot string, putold string) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
if e1 != 0 {
err = e1
これらのファイルは、syscall_linux.go
の//sysnb
コメントに基づいて自動生成されるシステムコールラッパーの実装を含んでいます。Prlimit
からprlimit
への関数名の変更は、これらの自動生成されたファイルにも反映され、実際のシステムコール呼び出しを行うGoの関数が非エクスポートされることを保証します。
全体として、このコミットはGoのAPI設計原則に従い、パッケージの内部実装の詳細を適切にカプセル化することで、コードの保守性と堅牢性を向上させています。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall getrlimit(2)
manページ:man 2 getrlimit
(Linuxシステムで実行)setrlimit(2)
manページ:man 2 setrlimit
(Linuxシステムで実行)prlimit(2)
manページ:man 2 prlimit
(Linuxシステムで実行)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Linux man-pages project
- GitHubのGoリポジトリのコミット履歴
- Goのコードレビューシステム (Gerrit) のCL (Change List) ページ: https://golang.org/cl/6458051
- Go言語の命名規則に関する情報 (例: Effective Go)
- Goにおけるエクスポートと非エクスポートに関する記事: https://medium.com/@ardeshir/go-export-and-unexport-a-function-1a2b3c4d5e6f
- Goの
syscall.Prlimit
に関する情報: https://pkg.go.dev/syscall#Prlimit
[インデックス 13538] ファイルの概要
このコミットは、Go言語のsyscall
パッケージにおいて、誤ってエクスポートされていたPrlimit
関数を非エクスポート(内部関数)に変更するものです。これにより、Goのパッケージ設計原則とAPIの整合性が保たれます。
コミット
commit 36fe436cbac4d2a55d06063de966798fc2216156
Author: Han-Wen Nienhuys <hanwen@google.com>
Date: Tue Jul 31 08:21:24 2012 +1000
pkg/syscall: unexport Prlimit.
This syscall was inadvertently exported when fixing
Getrlimit/Setrlimit on 32-bit platforms.
R=golang-dev, minux.ma
CC=golang-dev
https://golang.org/cl/6458051
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/36fe436cbac4d2a55d06063de966798fc2216156
元コミット内容
pkg/syscall: unexport Prlimit.
This syscall was inadvertently exported when fixing
Getrlimit/Setrlimit on 32-bit platforms.
変更の背景
このコミットの背景には、Go言語のsyscall
パッケージにおけるGetrlimit
およびSetrlimit
関数の32ビットプラットフォームでの修正作業があります。以前の修正中に、Prlimit
というシステムコールをラップする関数が意図せずエクスポート(外部からアクセス可能)されてしまいました。Go言語の慣習として、パッケージ内部でのみ使用されるべき関数は非エクスポート(小文字で始まる名前)にするべきであり、このPrlimit
関数もその原則に従うべきでした。
Prlimit
は、特定のプロセス(pid
)のリソース制限(rlimit
)を取得または設定するためのシステムコールです。Getrlimit
やSetrlimit
は、現在のプロセス(pid=0
)のリソース制限を操作するための高レベルな関数であり、内部的にPrlimit
を利用することがあります。しかし、Prlimit
自体は、Goのユーザーが直接呼び出すことを意図したものではなく、Getrlimit
やSetrlimit
のようなより抽象化されたインターフェースを通じて利用されるべきでした。
このコミットは、この「意図しないエクスポート」を修正し、Goのパッケージ設計原則とAPIの整合性を保つことを目的としています。
前提知識の解説
1. Go言語におけるエクスポートと非エクスポート
Go言語では、識別子(変数、関数、型など)の最初の文字が大文字である場合、その識別子はパッケージの外部からアクセス可能(エクスポートされる)になります。一方、最初の文字が小文字である場合、その識別子はパッケージ内部でのみアクセス可能(非エクスポートされる)です。このルールは、APIの公開範囲を制御し、パッケージの内部実装の詳細を隠蔽するために非常に重要です。
2. syscall
パッケージ
syscall
パッケージは、Goプログラムからオペレーティングシステム(OS)のシステムコールを直接呼び出すための低レベルなインターフェースを提供します。これにより、ファイル操作、プロセス管理、ネットワーク通信など、OSカーネルが提供する機能にアクセスできます。システムコールはOSによって提供される機能であり、通常はC言語のライブラリ(例: glibc)を介して利用されますが、Goのsyscall
パッケージはGoのコードから直接これらのシステムコールを呼び出すためのラッパーを提供します。
3. rlimit
(リソース制限)
rlimit
は、Unix系OSにおいてプロセスが利用できるシステムリソース(例: オープンできるファイルの最大数、利用できるCPU時間、メモリ量など)に上限を設定するための仕組みです。各リソースには「ソフトリミット」と「ハードリミット」の2つの制限があります。
- ソフトリミット: プロセスが実際に利用できる上限。プロセスはこの制限をハードリミット以下であれば引き上げることができます。
- ハードリミット: ソフトリミットの最大値。スーパーユーザーのみがハードリミットを引き上げることができます。
これらの制限は、システム全体の安定性を保ち、特定のプロセスがリソースを過剰に消費するのを防ぐために重要です。
4. Getrlimit
と Setrlimit
システムコール
getrlimit(2)
: 現在のプロセスのリソース制限を取得するためのシステムコール。setrlimit(2)
: 現在のプロセスのリソース制限を設定するためのシステムコール。
これらのシステムコールは、通常、現在のプロセス自身のリソース制限を操作するために使用されます。
5. prlimit(2)
システムコール
prlimit(2)
(または prlimit64(2)
on Linux) は、getrlimit
やsetrlimit
のより汎用的なバージョンです。これは、特定のプロセスID (pid
) を指定して、そのプロセスのリソース制限を取得または設定することができます。pid
が0の場合、呼び出し元のプロセスのリソース制限を操作します。このシステムコールは、Linuxカーネル2.6.36以降で利用可能です。
技術的詳細
このコミットは、Goのsyscall
パッケージ内でPrlimit
という名前でエクスポートされていた関数を、prlimit
という非エクスポート名に変更することで、その公開範囲を制限しています。
Goのsyscall
パッケージは、OSのシステムコールをGoの関数としてラップしています。これらのラッパー関数は、通常、//sys
または//sysnb
という特殊なコメントでマークされ、zsyscall_linux_*.go
のようなファイルに自動生成されるコードの一部となります。
元のコードでは、Prlimit
関数がSYS_PRLIMIT64
システムコールを呼び出すように定義されており、その名前がPrlimit
(大文字始まり)であったため、パッケージ外部からアクセス可能でした。しかし、Getrlimit
やSetrlimit
のような高レベルな関数が内部的にPrlimit
を利用するだけであり、ユーザーが直接Prlimit
を呼び出す必要はないという設計意図がありました。
この変更により、Prlimit
はprlimit
にリネームされ、Goの命名規則に従って非エクスポート関数となりました。これにより、syscall
パッケージの外部からはprlimit
関数に直接アクセスできなくなり、APIのクリーンさとカプセル化が向上します。
また、この変更は、syscall_linux_386.go
とsyscall_linux_arm.go
内のGetrlimit
およびSetrlimit
関数が、内部的にPrlimit
ではなくprlimit
を呼び出すように修正されています。これは、Prlimit
が非エクスポートされたことに伴う必然的な変更です。
コアとなるコードの変更箇所
このコミットでは、以下のファイルが変更されています。
src/pkg/syscall/syscall_linux.go
//sysnb Prlimit(...)
の行が//sysnb prlimit(...)
に変更されています。これは、Prlimit
関数が非エクスポートされることを示すためのコメントの変更です。
src/pkg/syscall/syscall_linux_386.go
Getrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。Setrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。
src/pkg/syscall/syscall_linux_arm.go
Getrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。Setrlimit
関数内でPrlimit
の呼び出しがprlimit
に変更されています。
src/pkg/syscall/zsyscall_linux_386.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
src/pkg/syscall/zsyscall_linux_amd64.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
src/pkg/syscall/zsyscall_linux_arm.go
- 自動生成された
Prlimit
関数の定義がprlimit
に変更されています。
- 自動生成された
コアとなるコードの解説
変更の核心は、Prlimit
という関数名をprlimit
に変更することです。
src/pkg/syscall/syscall_linux.go
の変更:
--- a/src/pkg/syscall/syscall_linux.go
+++ b/src/pkg/syscall/syscall_linux.go
@@ -839,7 +839,7 @@ func Mount(source string, target string, fstype string, uintptr, data stri
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Pause() (err error)
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
-//sysnb Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
+//sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
//sys Read(fd int, p []byte) (n int, err error)
//sys Readlink(path string, buf []byte) (n int, err error)
//sys Rename(oldpath string, newpath string) (err error)
この変更は、Prlimit
関数がsyscall
パッケージの内部関数として扱われるべきであることを、コード生成ツールに指示するためのものです。//sysnb
コメントは、この行がシステムコールラッパーを生成するための指示であることを示しています。Prlimit
からprlimit
への変更は、Goの命名規則に従い、この関数がパッケージ外部に公開されないことを意味します。
src/pkg/syscall/syscall_linux_386.go
および src/pkg/syscall/syscall_linux_arm.go
の変更:
--- a/src/pkg/syscall/syscall_linux_386.go
+++ b/src/pkg/syscall/syscall_linux_386.go
@@ -78,7 +78,7 @@ const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)
func Getrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, rlim, nil)
+\terr = prlimit(0, resource, rlim, nil)
\tif err != ENOSYS {
\t\treturn err
\t}
@@ -106,7 +106,7 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) {
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
-\terr = Prlimit(0, resource, nil, rlim)
+\terr = prlimit(0, resource, nil, rlim)
\tif err != ENOSYS {
\t\treturn err
\t}
これらの変更は、Getrlimit
とSetrlimit
関数が、非エクスポートされたprlimit
関数を呼び出すように修正されたことを示しています。これは、Prlimit
が非エクスポートされた結果として必要な変更であり、これらの高レベル関数が引き続き正しく機能することを保証します。
src/pkg/syscall/zsyscall_linux_386.go
、src/pkg/syscall/zsyscall_linux_amd64.go
、src/pkg/syscall/zsyscall_linux_arm.go
の変更:
--- a/src/pkg/syscall/zsyscall_linux_386.go
+++ b/src/pkg/syscall/zsyscall_linux_386.go
@@ -598,7 +598,7 @@ func PivotRoot(newroot string, putold string) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
if e1 != 0 {
err = e1
これらのファイルは、syscall_linux.go
の//sysnb
コメントに基づいて自動生成されるシステムコールラッパーの実装を含んでいます。Prlimit
からprlimit
への関数名の変更は、これらの自動生成されたファイルにも反映され、実際のシステムコール呼び出しを行うGoの関数が非エクスポートされることを保証します。
全体として、このコミットはGoのAPI設計原則に従い、パッケージの内部実装の詳細を適切にカプセル化することで、コードの保守性と堅牢性を向上させています。
関連リンク
- Go言語の
syscall
パッケージのドキュメント: https://pkg.go.dev/syscall getrlimit(2)
manページ:man 2 getrlimit
(Linuxシステムで実行)setrlimit(2)
manページ:man 2 setrlimit
(Linuxシステムで実行)prlimit(2)
manページ:man 2 prlimit
(Linuxシステムで実行)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Linux man-pages project
- GitHubのGoリポジトリのコミット履歴
- Goのコードレビューシステム (Gerrit) のCL (Change List) ページ: https://golang.org/cl/6458051
- Go言語の命名規則に関する情報 (例: Effective Go)
- Goにおけるエクスポートと非エクスポートに関する記事: https://medium.com/@ardeshir/go-export-and-unexport-a-function-1a2b3c4d5e6f
- Goの
syscall.Prlimit
に関する情報: https://pkg.go.dev/syscall#Prlimit