Provided by: manpages-ja-dev_0.5.0.0.20131015+dfsg-2_all
名前
getrlimit, setrlimit, prlimit - 資源の制限を取得/設定する
書式
#include <sys/time.h> #include <sys/resource.h> int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim); int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlimit *old_limit); glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照): prlimit(): _GNU_SOURCE && _FILE_OFFSET_BITS == 64
説明
getrlimit() と setrlimit() はそれぞれ資源 (resource) の制限 (limit) の設定と取得を行う。 各リソースには、それに対応するソフトリミッ トとハードリミットがあり、 rlimit 構造体で定義 される: struct rlimit { rlim_t rlim_cur; /* ソフトリミット */ rlim_t rlim_max; /* ハードリミット (rlim_cur より小さくない) */ }; ソフトリミットは、カーネルが対応するリソースに対して課す制限値である。 ハードリミットはソ フトリミットの上限として働く。 特権を持たないプロセスは、ソフトリミットの値を 0 からハード リミットの範囲に設定することと、 ハードリミットを下げることのみができる (一度下げたハード リミットは上げられない)。 特権プロセス (Linux では CAP_SYS_RESOURCE ケーパビリティ (capability) を持つプロセス) は ソフトリミットとハードリミットを自由に変更できる。 値 RLIM_INFINITY はリソースに制限がないことを表す (この値は getrlimit() が返す構造体と setrlimit() に渡す構造体の両方で使用される)。 resource 引き数は次のいずれか 1 つである。 RLIMIT_AS プロセスの仮想メモリ (アドレス空間) の最大サイズ (バイト単位)。 この制限は brk(2), mmap(2), mremap(2) の呼び出しに影響し、この制限を超えた場合は エラー ENOMEM で失敗 する。 また自動的なスタック拡張にも失敗する (さらに sigaltstack(2) を使った代替ス タックを利用可能にしていなかった場合には、 SIGSEGV を生成してそのプロセスを kill す る)。 この値は long 型なので、32 ビットの long 型を持つマシンでは、 この制限は最大 で 2 GiB になるか、この資源が無制限になる。 RLIMIT_CORE core ファイルの最大サイズ。 0 の場合、core ファイルは生成されない。 0 以外の場 合、このサイズより大きいダンプは切り詰められる。 RLIMIT_CPU CPU 時間の上限 (秒数)。プロセスがソフトリミットに達した場合に、 SIGXCPU シグナルを 送る。このシグナルに対するデフォルトの動作は、 プロセスの終了である。ただし、シグナ ルをキャッチして、ハンドラがメイン プログラムに制御を返すこともできる。プロセスが CPU 時間を使い続けた 場合は、ハードリミットに達するまで 1 秒毎にプロセスに SIGXCPU を送り、 ハードリミットに達すると SIGKILL を送る。 (ソフトリミットを超過したときの 動作は、 Linux における動作である。ソフ トリミットを超えて CPU 時間を使い続けるプロ セスの扱い方についての実装は 変化してきている。 このシグナルをキャッチする必要のあ る 移植性を考えた アプリケーションでは、 最初に SIGXCPU を受け取った時点で正しく終 了 すべきである。) RLIMIT_DATA プロセスのデータセグメント (初期化されたデータ・初期化されていないデータ・ヒープ) の最大値。 このリミットは brk(2) と sbrk(2) の呼び出しに影響する。 これらの関数 は、このリソースのソフトリミットに達すると、 エラー ENOMEM で失敗する。 RLIMIT_FSIZE プロセスが作成できるファイルサイズの最大値。 このサイズを超えてファイルを拡張する と、 SIGXFSZ シグナルを送る。 デフォルトでは、このシグナルはプロセスを終了する。 プ ロセスをキャッチすることもできるが、 関連するシステムコール (write(2), truncate(2) など) はエラー EFBIG で失敗する。 RLIMIT_LOCKS (初期の Linux 2.4 のみ) このプロセスが実行できる flock(2) ロック数と fcntl(2) リース数の合計値を制限す る。 RLIMIT_MEMLOCK RAM 内にロックできるメモリの最大バイト数。 実際には、この制限はシステムページサイズ の最も近い倍数に 切り捨てて丸められる。 この制限は mlock(2), mlockall(2), mmap(2) の MAP_LOCKED 操作に影響する。 Linux 2.6.9 以降では shmctl(2) SHM_LOCK 操作にも影 響する。 この操作は呼び出し元プロセスの実 (real) ユーザー ID にロックされる 共有メ モリセグメント (shmget(2) を参照) の合計バイト数の最大値を設定する。 shmctl(2) SHM_LOCK によるロックは、 mlock(2), mlockall(2), mmap(2) の MAP_LOCKED によって確 立されるプロセス毎のメモリロックとは分けて数える。 1 つのプロセスはこの制限までのバ イトをロックできる。 この制限には 2 つの種類がある。 2.6.9 より前の Linux カーネル では、 この制限は特権プロセスによってロックされるメモリの合計を制御していた。 Linux 2.6.9 以降では、特権プロセスがロックするメモリの合計に制限はなく、 代わりにこの制限 は非特権プロセスがロックするメモリの合計に 適用されるようになった。 RLIMIT_MSGQUEUE (Linux 2.6.8 以降) 呼び出し元プロセスの実ユーザー ID に対して、 POSIX メッセージキューのために確保でき るバイト数の制限を指定する。 この制限は mq_open(3) に対して適用される。 ユーザが作 成した各々のメッセージキューのバイト数は 以下の式により計算され、(そのキューが削除 されるまでの間) この制限の計算対象に含められる。 bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) + attr.mq_maxmsg * attr.mq_msgsize ここで attr は mq_attr 構造体であり、 mq_open(3) の第 4 引き数として指定される。 sizeof(struct msg_msg *) (Linux/i386 では 4 バイト) を含む最初の加数は、 ユーザーが 長さ 0 のメッセージを無制限に作れないこと保証している (このようなメッセージであって も、 記録のためのオーバーヘッドでシステムメモリを消費する)。 RLIMIT_NICE (Linux 2.6.12 以降, 下記の「バグ」の節も参照) setpriority(2) や nice(2) を使って引き上げられるプロセスの nice 値の上限を指定す る。 nice 値の実際の上限は 20 - rlim_cur で計算される (このような変な状況は、リソー ス制限値として負の数を指定できないため 発生する。通常、負の値は特別な意味を持ってい るからである。 例えば、通常は RLIM_INFINITY の値は -1 である)。 RLIMIT_NOFILE このプロセスがオープンできるファイルディスクリプタ数の最大値より 1 大きい値を指定す る。 (open(2), pipe(2), dup(2) などにより) この上限を超えようとした場合、エラー EMFILE が発生する (歴史的に、BSD ではこの上限は RLIMIT_OFILE という名前となってい る)。 RLIMIT_NPROC 呼び出したプロセスの実ユーザー ID で作成できる最大プロセス数 (より正確には Linux で はスレッド数)。 この上限に達すると、 fork(2) はエラー EAGAIN で失敗する。 RLIMIT_RSS プロセスの resident set (RAM 上に存在する仮想ページの数) の 上限を (ページ数で) 指 定する。 この制限は 2.4.30 より前でしか影響がなく、 madvise(2) に MADV_WILLNEED を 指定した関数コールにしか影響しない。 RLIMIT_RTPRIO (Linux 2.6.12 以降, バグの節も参照) sched_setscheduler(2) や sched_setparam(2) を使って設定できる、そのプロセスのリア ルタイム優先度の上限を指定する。 RLIMIT_RTTIME (Linux 2.6.25 以降) リアルタイムスケジューリング方針でスケジューリングされるプロセスが ブロッキング型の システムコールを呼び出さずに消費することのできる CPU 時間の合計についての上限を (マ イクロ秒単位で) 指定する。 この上限の目的のため、プロセスがブロッキング型のシステム コールを 呼び出す度に、消費された CPU 時間のカウントは 0 にリセットされる。 プロセ スが CPU を使い続けようとしたが他のプロセスに置き換えられた (preempted) 場合や、そ のプロセスのタイムスライスが満了した場合、 そのプロセスが sched_yield(2) を呼び出 した場合は、CPU 時間のカウントはリセットされない。 ソフトリミットに達すると、そのプロセスに SIGXCPU シグナルが送られる。そのプロセスが このシグナルを捕捉するか 無視して、CPU 時間を消費し続けた場合には、 ハードリミット に達するまで 1 秒に 1 回 SIGXCPU が生成され続けることになる。 ハードリミットに達し た時点で、そのプロセスには SIGKILL シグナルが送られる。 この上限を意図的に使用するのは、暴走したリアルタイムプロセスを 停止して、システムが 動かなくなるのを避ける場合である。 RLIMIT_SIGPENDING (Linux 2.6.8 以降) 呼び出し元プロセスの実ユーザー ID に対して キューに入れられるシグナルの 数の制限を 指定する。この制限をチェックするため、標準シグナルとリアルタ イムシグナルの両方がカ ウントされる。しかし、この制限は sigqueue(3) に対してのみ適用され、 kill(2) 使うこ とで、そのプロセスに対してま だキューに入れられていない シグナルのインスタンスを キューに入れることが できる。 RLIMIT_STACK プロセススタックの最大サイズをバイト単位で指定する。 この上限に達すると、 SIGSEGV シグナルが生成される。 このシグナルを扱うためには、 プロセスは代りのシグナルスタッ ク (sigaltstack(2)) を使用しなければならない。 Linux 2.6.23 以降では、この制限はプロセスのコマンドライン引き数と環境変数 に使用さ れる空間の合計サイズの上限の決定にも使用される。詳細については execve(2) を参照。 prlimit() Linux 固有の prlimit() システムコールは、 setrlimit() と getrlimit の機能を合わせて拡張し たものである。 このシステムコールを使って、任意のプロセスのリソース上限の設定と取得を行う ことができる。 resource 引き数は setrlimit() や getrlimit() と同じ意味である。 new_limit 引き数が NULL 以外の場合、 new_limit が指す rlimit 構造体を使って resource のソ フトリミットとハードリミットの新しい値が設定される。 old_limit 引き数が NULL 以外の場合、 prlimit() の呼び出しが成功すると、 resource の直前のソフトリミットとハードリミットが old_limit が指す rlimit 構造体に格納される。 pid 引き数は呼び出しの操作対象となるプロセス ID を指定する。 pid が 0 の場合、呼び出しは呼 び出し元プロセスに対して適用される。 自分以外のプロセスのリソースの設定と取得を行うために は、 呼び出し元プロセスが CAP_SYS_RESOURCE ケーパビリティを持っているか、 対象となるプロセ スの実ユーザ ID、 実効ユーザ ID、 保存 set-user-ID が呼び出し元プロセスの実ユーザ ID と一 致し、 かつ、 対象となるプロセスの実グループ ID、 実効グループ ID、 保存 set-group-ID が呼 び出し元プロセスの実グループ ID と一致していなければならない。
返り値
成功した場合、これらのシステムコールは 0 を返す。 エラーの場合は -1 が返され、 errno が適 切に設定される。
エラー
EFAULT 場所を指すポインタ引き数がアクセス可能なアドレス空間外を指している。 EINVAL resource で指定された値が有効でない。 または、 setrlimit() や prlimit() で、 rlim->rlim_cur が rlim->rlim_max よりも大きかった。 EPERM 特権のないプロセスがハードリミットを上げようとした。 これを行うためには CAP_SYS_RESOURCE ケーパビリティが必要である。 または、特権のないプロセスが RLIMIT_NOFILE ハードリミットを 現在のカーネルの最大値 (NR_OPEN) 以上に増やそうとし た。 または、呼び出したプロセスが pid で指定されたプロセスのリミットを 設定する許可 を持っていなかった。 ESRCH pid で指定された ID のプロセスが見つからなかった。
バージョン
prlimit() システムコールは Linux 2.6.36 以降で利用できる。 ライブラリのサポートは glibc 2.13 以降で利用できる。
準拠
getrlimit(), setrlimit(): SVr4, 4.3BSD, POSIX.1-2001. prlimit(): Linux 固有。 RLIMIT_MEMLOCK と RLIMIT_NPROC は BSD から派生し、 POSIX.1-2001 には指定されていない。 こ れらは BSD 系と Linux に存在するが、他の実装は少ない。 RLIMIT_RSS は BSD から派生 し、POSIX.1-2001 には指定されていない。 それにも関わらず多くの実装で存在する。 RLIMIT_MSGQUEUE, RLIMIT_NICE, RLIMIT_RTPRIO, RLIMIT_RTTIME, RLIMIT_SIGPENDING は Linux 固 有のものである。
注意
fork(2) で作成された作成された子プロセスは、 親プロセスのリソース制限を継承する。 execve(2) の前後でリソース制限は保存される。 シェルのリソース制限は、シェルの組み込みコマンドである ulimit (csh(1) では limit ) を使っ て設定することができる。 このシェルのリソース制限は、コマンドを実行してシェルが生成するプ ロセス に引き継がれる。 Linux 2.6.24 以降では、 プロセスのリソース上限は /proc/[pid]/limits で知ることができる。 proc(5) 参照。 古いシステムでは、 setrlimit() と同様の目的を持つ関数 vlimit() が提供されていた。 後方互 換性のため、glibc でも vlimit() を提供している。 全ての新しいアプリケーションでは、 setrlimit() を使用すべきである。
バグ
以前の Linux カーネルでは、プロセスがソフトまたはハード RLIMIT_CPU リミットに達した場合に 送られる SIGXCPU と SIGKILL シグナルが、本来送られるべき時点の 1 (CPU) 秒後に送られてしま う。 これはカーネル 2.6.8 で修正された。 2.6.17 より前の 2.6.x カーネルでは、 RLIMIT_CPU リミットが 0 の場合、 (RLIM_INFINITY と同 じように) 「制限なし」と間違って解釈されていた。 Linux 2.6.17 以降では、リミットを 0 に設 定した場合にも 効果を持つようになっているが、実際にはリミットの値は 1 秒となる。 カーネル 2.6.12 には、 RLIMIT_RTPRIO が動作しないというバグがある。この問題はカーネル 2.6.13 で修正されている。 カーネル 2.6.12 では、 getpriority(2) と RLIMIT_NICE が返す優先度の範囲が一つずれてい た。このため、nice 値の実際の上限が 19 - rlim_cur になってしまうという影響があった。これは カーネル 2.6.13 で修正された。 Linux 2.6.12 以降では、 プロセスがその RLIMIT_CPU ソフトリミットに達し、 SIGXCPU に対して シグナルハンドラが設定されている場合、 シグナルハンドラを起動するだけでなく、 カーネルは 1 秒間ソフトリミットを増やす。 そのプロセスが CPU 時間を消費し続けている限り、 ハードリミッ トに達するまで、この動作が繰り返される。 ハードリミットに達すると、その時点でプロセスは kill される。 他の実装では、上記のような RLIMIT_CPU ソフトリミットの変更は行われず、 おそ らく Linux の動作は標準に準拠していない。 移植性が必要なアプリケーションではこの Linux 固 有の動作を前提にするのは避けるべきである。 Linux 固有の上限 RLIMIT_RTTIME でも、 ソフトリ ミットに達した場合に同じ動作となる。 2.4.22 より前のカーネルでは、 rlim->rlim_cur が rlim->rlim_max より大きかった場合、 setrlimit() での EINVAL エラーを検出できない。
例
以下のプログラムに prlimit() の使用例を示す。 #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include <stdio.h> #include <time.h> #include <stdlib.h> #include <unistd.h> #include <sys/resource.h> #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) int main(int argc, char *argv[]) { struct rlimit old, new; struct rlimit *newp; pid_t pid; if (!(argc == 2 || argc == 4)) { fprintf(stderr, "Usage: %s <pid> [<new-soft-limit> " "<new-hard-limit>]\n", argv[0]); exit(EXIT_FAILURE); } pid = atoi(argv[1]); /* PID of target process */ newp = NULL; if (argc == 4) { new.rlim_cur = atoi(argv[2]); new.rlim_max = atoi(argv[3]); newp = &new; } /* Set CPU time limit of target process; retrieve and display previous limit */ if (prlimit(pid, RLIMIT_CPU, newp, &old) == -1) errExit("prlimit-1"); printf("Previous limits: soft=%lld; hard=%lld\n", (long long) old.rlim_cur, (long long) old.rlim_max); /* Retrieve and display new CPU time limit */ if (prlimit(pid, RLIMIT_CPU, NULL, &old) == -1) errExit("prlimit-2"); printf("New limits: soft=%lld; hard=%lld\n", (long long) old.rlim_cur, (long long) old.rlim_max); exit(EXIT_FAILURE); }
関連項目
prlimit(1), dup(2), fcntl(2), fork(2), getrusage(2), mlock(2), mmap(2), open(2), quotactl(2), sbrk(2), shmctl(2), malloc(3), sigqueue(3), ulimit(3), core(5), capabilities(7), signal(7)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.54 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。