LoginSignup
2
0

More than 5 years have passed since last update.

"ulimit -a"の値をNetBSDのカーネル側から調べてみる

Last updated at Posted at 2016-12-25

NetBSD Advent Calendar 2016、25日目の記事は11日目の記事で構築した、NetBSDカーネルのビルド・テスト環境を利用してカーネル内部の処理を追いかけてみようと思います。
本当はkgdbでカーネルデバッグ環境を作るネタを紹介したかったのですが、いまいちVirtualBox環境でのシリアルポート設定がうまく行えなかったため、今回はコードリーディングの形で処理の流れを把握してみます。

カーネルのソースコードはどこから追いかける?

カーネルのソースコードを読む場合、ついつい最新機能の処理部分に目が向いてしまいがちで、新機能を追いかけようとする→プロセス構造体等の基本的な構成の把握に時間がかかる、という落とし穴にハマることが良くあります。

カーネルのビルド・テスト環境が手軽に構築できるようになったので、まずはユーザランドでの動作を把握できるような基本的な機能はカーネル内でどういう処理・振る舞いになっているのか調べてみます。
(これを積み重ねて行けば新機能の処理とかも読み解きやすくなるかと)

ulimitの機能を調べてみる

というワケで、とりあえず今回はulimitによるプロセスのリソース制限まわりについて、カーネル内でどう扱われているかを追いかけてみます。

$ ulimit -a
time(cpu-seconds)    unlimited
file(blocks)         unlimited
coredump(blocks)     unlimited
data(kbytes)         262144
stack(kbytes)        4096
lockedmem(kbytes)    163233
memory(kbytes)       489700
nofiles(descriptors) 1024
processes            1024
threads              1024
vmemory(kbytes)      unlimited
sbsize(bytes)        unlimited

カーネルのリソース構造体

さっそくカーネルのソースコードを追いかけてみます。struct procのサブ構造体struct plimit *p_limitがリソース制限まわりの情報を保持している構造体のようです。

sys/proc.h:
187 /*
188  * Description of a process.
...
210 struct proc {
211         LIST_ENTRY(proc) p_list;        /* l: List of all processes */
...
220         /* Substructures: */
...
225         struct plimit   *p_limit;       /* :: Process limits */

struct plimitstruct rlimit[]という配列のメンバ変数を保持しており、struct rlimitrlimit_currlimit_maxというメンバ変数を持っています。

sys/resourcevar.h:
 69 /*
 70  * Process resource limits.  Since this structure is moderately large,
 71  * but changes infrequently, it is shared copy-on-write after forks.
 72  *
 73  * When a separate copy is created, then 'pl_writeable' is set to true,
 74  * and 'pl_sv_limit' is pointed to the old proc_t::p_limit structure.
 75  */
 76 struct plimit {
 77         struct rlimit   pl_rlimit[RLIM_NLIMITS];
 78         char *          pl_corename;
 79         size_t          pl_cnlen;
 80         u_int           pl_refcnt;
 81         bool            pl_writeable;
 82         kmutex_t        pl_lock;
 83         struct plimit * pl_sv_limit;
 84 };
sys/resource.h:
111 struct rlimit {
112         rlim_t  rlim_cur;               /* current (soft) limit */
113         rlim_t  rlim_max;               /* maximum value for rlim_cur */
114 };
115 

struct rlimit[]の配列インデックス値はマクロ定数で定義されており、どうやらこのインデックスで参照される値がumit -aコマンドで表示される値のようですね。

sys/resource.h:
 78 /*
 79  * Resource limits
 80  */
 81 #define RLIMIT_CPU      0               /* cpu time in milliseconds */
 82 #define RLIMIT_FSIZE    1               /* maximum file size */
 83 #define RLIMIT_DATA     2               /* data size */
 84 #define RLIMIT_STACK    3               /* stack size */
 85 #define RLIMIT_CORE     4               /* core file size */
 86 #define RLIMIT_RSS      5               /* resident set size */
 87 #define RLIMIT_MEMLOCK  6               /* locked-in-memory address space */
 88 #define RLIMIT_NPROC    7               /* number of processes */
 89 #define RLIMIT_NOFILE   8               /* number of open files */
 90 #define RLIMIT_SBSIZE   9               /* maximum size of all socket buffers */
 91 #define RLIMIT_AS       10              /* virtual process size (inclusive of mmap) */
 92 #define RLIMIT_VMEM     RLIMIT_AS       /* common alias */
 93 #define RLIMIT_NTHR     11              /* number of threads */
 94 
 95 #if defined(_NETBSD_SOURCE)
 96 #define RLIM_NLIMITS    12              /* number of resource limits */
 97 #endif
$ ulimit -a 
number of threads               (-T) 1024
socket buffer size       (bytes, -b) unlimited
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) 262144
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) 163233
max memory size         (kbytes, -m) 489700
open files                      (-n) 1024
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 4096
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited

例として、ulimit -aコマンドのfile sizeはどう設定されているか見てみます。値として「無制限」を意味する値が設定されており、RLIMIT_FSIZEのインデックス値で参照できるstruct rlimit[]の値が設定されている箇所を調べれば良さそうです。

sys/resource.h:
 82 #define RLIMIT_FSIZE    1               /* maximum file size */

ソースコードを追いかけてみると、kern/kern_acct.c:acct_process()RLIM_INFINITYという値が設定されていました。いかにも「無制限」を意味するようなマクロ定数な感じがします。

kern/kern_acct.c:
399 /*
400  * Write out process accounting information, on process exit.
401  * Data to be written out is specified in Leffler, et al.
402  * and are enumerated below.  (They're also noted in the system
403  * "acct.h" header file.)
404  */
405 int
406 acct_process(struct lwp *l)
407 {
413         struct proc *p = l->l_proc;
...
434         /* Set current and max to avoid illegal values */
435         p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
436         p->p_rlimit[RLIMIT_FSIZE].rlim_max = RLIM_INFINITY;

RLIM_INFINITYのマクロ手数が定義されている箇所を見てみます。struct rlimit->rlim_curにはu_quad_tなサイズ(ビット長)の値が設定できること、msb(最上位ビット)以外がすべて1の場合は「無制限」を意味することがわかります。

sys/resource.h:
 99 #define RLIM_INFINITY   (~((u_quad_t)1 << 63))  /* no limit */
100 #define RLIM_SAVED_MAX  RLIM_INFINITY   /* unrepresentable hard limit */
101 #define RLIM_SAVED_CUR  RLIM_INFINITY   /* unrepresentable soft limit */

という感じで、いつも使う機能についてNetBSDカーネルのソースコードではどうデータが表現されているかを追いかけてみました。
(せっかくカーネルのビルド・テスト環境を用意したけどカーネルを動作させてみるとかしていないですね...)

まとめ

日常使うような機能について、NetBSDカーネル内部ではどのように値が保持・管理されているかをullimit -aコマンドを例にして調べてみました。
カーネルの新しい機能の調査も面白いですが、日々使う機能についてカーネル側での振る舞いを把握しておくとOSの理解やトラブルシューティングに役立つのではないでしょうか。

おわりに

今年もなんとか無事にNetBSD Advent Calendar 2016を完走することができました。
これもひとえに皆様のおかげです。私の投稿がだいぶ滞ってしまい、参加者の皆様にはご迷惑をおかけしてしまいました。

ONODERA Ryo様、Enomoto Yuuki様、Ebihara Jun様、Makoto Fujiwara様、oshimaya様、ISIHARA Takanori様(投稿日順です)ありがとうございました。
参加表明されていた方もありがとうございます(代理投稿したらどなたが参加表明されていたのかわからなくなってしまいました、すみません...)。

特にONODERA Ryo様にはご多忙にも関わらず数多くの投稿をいだたき、本当に助かりました。ありがとうございます。

今年は個人的にバタバタしてしまい、記事の投稿が遅くなってしまったのが反省点です。来年は11月頭くらいから準備しておくようにしようと思います。

ともかく、これで無事にNetBSD Advent Calendar 2016完走ですね。どうか来年もご参加いただければと思います。

(ちょっと早いですが)それではよいお年を!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0