プログラムを実行する際のリソース情報(とくにリソースの制限)を取得する必要がある場合がある.
limits.h
プライオリティの取得と設定
リソース使用量
リソースの制限とその設定
limits.h
imits.hやそこから読み込まれるヘッダにはcharのビット数やファイル名長の制限など,おおくの制限が定義されている.また,とくにファイル名長は,互換性を維持するためにpathconfやfpathconfという関数がある.
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
fprintf(stdout,"CHAR_BIT %d\n",CHAR_BIT);
fprintf(stdout,"SCHAR_MIN %d\n",SCHAR_MIN);
fprintf(stdout,"SCHAR_MAX %d\n",SCHAR_MAX);
fprintf(stdout,"NAME_MAX %d\n",NAME_MAX);
fprintf(stdout,"=========================================================\n");
fprintf(stdout,"CHAR_BIT from pathconf %d \n",pathconf("/",_PC_NAME_MAX));
exit(0);
}
これを実行すると,私の環境では以下のように出力された.
CHAR_BIT 8
SCHAR_MIN -128
SCHAR_MAX 127
NAME_MAX 255
=========================================================
CHAR_BIT from pathconf 255
あと
grep -rl " NAME_MAX " /usr/include/*
とすると
/usr/include/glib-1.2/glib.h
grep: 警告: /usr/include/gnome-xml/libxml: ディレクトリーが再帰的ループをしています
/usr/include/linux/limits.h
となった. NAME_MAXの値はglib.hとlinux/limits.hのどちらが使用されているのだろうか(値は同じだった).
プライオリティの取得と設定
プライオリティといえばniceだが(?),プログラム中で自分自身や自分の子プロセスのプライオリティを取得したり設定したりできる.getpriorityとsetpriorityである.
#include <sys/resource.h>
#include <stdio.h>
int main()
{
/* getpriorityの第一引数は第二引数の意味を示す.
以下はgetpid()の値がPRIO_PROCESS(プロセスID)であること意味している.
これは,例えば第二引数がプロセスグループとかユーザを意味したりするので必要である.*/
fprintf(stdout,"priority %d \n",getpriority(PRIO_PROCESS,getpid()));
fprintf(stdout,"set priority to 10\n");
/* プライオリティの設定.
コマンドniceから察するに(未確認)プライオリティの範囲は-20から19で,
負のプライオリティを設定するにはroot権限が必要になる. */
setpriority(PRIO_PROCESS,getpid(),10);
fprintf(stdout,"priority %d \n",getpriority(PRIO_PROCESS,getpid()));
exit(0);
}
以下実行結果.プライオリティのデフォルトは0である.
priority 0
set priority to 10
priority 10
リソース使用量
getrusageを使用するとリソースの使用量の情報を取得できる.この情報はrusage構造体を介して返される.rusage構造体は以下のように宣言されている(/usr/include/linux/resource.hより).
struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
long ru_maxrss; /* maximum resident set size */
long ru_ixrss; /* integral shared memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
long ru_minflt; /* page reclaims */
long ru_majflt; /* page faults */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* messages sent */
long ru_msgrcv; /* messages received */
long ru_nsignals; /* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary */
};
以下,getrusageのサンプルを示す.
/******** man getrusageの注意書きより **********************
今日では <sys/time.h> をインクルードする必要はないが、
インクルードしておけば移植性が増す。
(実際 struct timeval は<sys/time.h> で定義されている。)
**************************************************************/
#include <sys/resource.h>
#include <limits.h>
#include <stdio.h>
int main()
{
struct rusage *resource_data;
double i=0;
double j=0;
/* 何らかの処理を実行 */
for(i=0;i<1000000;i++){
j+=log(i*j);
fprintf(stdout,"%f\n",j);
}
/* ruage構造体の取得.第一引数はRUSAGE_SELF(該当プロセスのみ)か
RUSAGE_CHILDREN(子プロセスも含む)である.*/
getrusage(RUSAGE_SELF,resource_data);
/* rusage構造体から情報を出力 */
/* ru_utimeは使用したユーザ時間(timeval構造体).
以下/usr/include/linux/time.hより
struct timeval {
time_t tv_sec; seconds
suseconds_t tv_usec; microseconds
};
*/
fprintf(stdout,"user time used = %lds %ldus\n",
resource_data->ru_utime.tv_sec,resource_data->ru_utime.tv_usec);
/* ru_stimeは使用したシステム時間(timeval構造体) */
fprintf(stdout,"system time used = %lds %ldus\n",
resource_data->ru_stime.tv_sec,resource_data->ru_stime.tv_usec);
exit(0);
}
実行結果は以下のようになる(無論環境依存だが).
user time used = 3s 970000us
system time used = 1s 570000us
リソースの制限とその設定
リソースの制限にはソフト制限とハード制限がある.
ソフト制限 | 超えるべきでない値.超えるとライブラリ関数がエラーを返すことがある. |
ハード制限 | この制限を超えるとシステムがプロセスにシグナルを送りそのプロセスを殺そうとする |
ソフト制限はハード制限を超えない範囲で設定できる,ということである.さらに,ハード制限は引き下げることが可能である.また,root権限がある場合だけはハード制限を引きあげることができる.
リソースの制限はrlimit構造体で取得できる.以下,/usr/include/bits/resource.hより
struct rlimit
{
/* The current (soft) limit. */
rlim_t rlim_cur;
/* The hard limit. */
rlim_t rlim_max;
};
rlimit構造体はgetrlimit,setrlimitで取得,設定できる.それぞれの第一引数はどのリソースに対するrlimitかを示す.第一引数には以下のものを設定できる(/usr/include/bits/resource.hより).
enum __rlimit_resource
{
/* Per-process CPU limit, in seconds. */
RLIMIT_CPU = 0,
#define RLIMIT_CPU RLIMIT_CPU
/* Largest file that can be created, in bytes. */
RLIMIT_FSIZE = 1,
#define RLIMIT_FSIZE RLIMIT_FSIZE
/* Maximum size of data segment, in bytes. */
RLIMIT_DATA = 2,
#define RLIMIT_DATA RLIMIT_DATA
/* Maximum size of stack segment, in bytes. */
RLIMIT_STACK = 3,
#define RLIMIT_STACK RLIMIT_STACK
/* Largest core file that can be created, in bytes. */
RLIMIT_CORE = 4,
#define RLIMIT_CORE RLIMIT_CORE
/* Largest resident set size, in bytes.
This affects swapping; processes that are exceeding their
resident set size will be more likely to have physical memory
taken from them. */
RLIMIT_RSS = 5,
#define RLIMIT_RSS RLIMIT_RSS
/* Number of open files. */
RLIMIT_NOFILE = 7,
RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */
#define RLIMIT_NOFILE RLIMIT_NOFILE
#define RLIMIT_OFILE RLIMIT_OFILE
/* Address space limit. */
RLIMIT_AS = 9,
#define RLIMIT_AS RLIMIT_AS
/* Number of processes. */
RLIMIT_NPROC = 6,
#define RLIMIT_NPROC RLIMIT_NPROC
/* Locked-in-memory address space. */
RLIMIT_MEMLOCK = 8,
#define RLIMIT_MEMLOCK RLIMIT_MEMLOCK
/* Maximum number of file locks. */
RLIMIT_LOCKS = 10,
#define RLIMIT_LOCKS RLIMIT_LOCKS
RLIMIT_NLIMITS = 11,
RLIM_NLIMITS = RLIMIT_NLIMITS
#define RLIMIT_NLIMITS RLIMIT_NLIMITS
#define RLIM_NLIMITS RLIM_NLIMITS
};
getrlimitを使用するサンプルを以下に示す.
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
struct rlimit *resource;
if(getrlimit(RLIMIT_CPU,resource)==-1){
fprintf(stderr,"failed to getrlimit\n");
}
fprintf(stdout,"CPU Current/Max = %ld/%ld\n",
resource->rlim_cur,resource->rlim_max);
exit(0);
}
実行結果を以下に示す.
CPU Current/Max = -1/-1
???????あれ??????......bashのコマンドにulimitというのがある.
$ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
file size (blocks, -f) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 256
virtual memory (kbytes, -v) unlimited
なるほど,無制限の場合は-1なのか.結果的にとてもつまらないサンプルになってしまった.