とりあえず kernel source 取得、って結構時間がかかっているな。とりあえず以下から目を通し始めています。
kernel/fork.c を出発点として cgroup がプロセス ID の割当てに絡んでいるあたりの確認をしている模様。alloc_pid という手続きから掘削が始まっています。
また、データ構造の確認、ということで
- alloc_pid で空間を確保している struct pid 型について
- alloc_pid に渡されている struct pid_namespace 型について
確認をしています。
clone 終了
GNU Global とか gtags とかが忘却の彼方で後天性記憶不全が進んでいることが分かり、かなりヘコんでいます。ともあれ
$ gtags -v
して emacs 起動。kernel/fork.c を開きます。
続行
ええと、alloc_pid 手続きを呼び出しているのは copy_process って手続きですね。そうか fork か。
pid = alloc_pid(p->nsproxy->pid_ns_for_children);
p って何だ、と思い逆向けにめくってみると以下な記述を発見。
retval = -ENOMEM;
p = dup_task_struct(current);
if (!p)
goto fork_out;
task_struct の複製を作っているあたり。この手続きの定義は以下でした。
static struct task_struct *dup_task_struct(struct task_struct *orig)
{
task_struct を戻すのは当然ですね。ちょっと alloc_pid に渡されているソレを手繰ってみようと思います。
struct task_struct 型は include/linux/sched.h で定義されてます。nsproxy という属性の定義は以下な部分でした。
/* namespaces */
struct nsproxy *nsproxy;
struct nsproxy 型を確認してみます。定義は include/linux/nsproxy.h でした。pid_ns_for_children という属性の型は何かというと
struct pid_namespace *pid_ns_for_children;
ということで当り前ですが struct pid_namespace 型でした。
fork する時に task_struct を dup するのだけれど、その時に pid namespace な親子関係が云々、という事なのかどうか。
alloc_pid に戻る
引数で渡された pid_namespace について親に向かった手繰っていきながら struct pid の members という属性に id および pid namespace を設定してますね。
ドキュメントには pidmap というものは pid namespace の_割り当て状況を記録するためのビットマップ_という記載があります。
成程
こうした仕組みを持っておけばコンテナの中の pid 1 とその外の pid 1 って形で重複した pid を割り当てることができる、ということなのか。
次行きます。
こんどは仮想記憶。ここでも始点が fork らしい。他にも
- page fault
- mmap
などが起点としてあり得るらしいです。つうか最初からいきなりアレゲなネタが出てますね。ということで do_fork から掘削開始な模様、というか copy_process からなのか。
子プロセスの struct task_struct を戻す、というあたりから仮想アドレス空間に関することも、との事でした。そして諸々を略して copy_mm 手続きから dup_mm へ。
retval = -ENOMEM;
mm = dup_mm(tsk);
if (!mm)
goto fail_nomem;
dup_mm の手続き定義なコメントが以下。
/*
* Allocate a new mm structure and copy contents from the
* mm structure of the passed in task structure.
*/
allocate_mm という手続きでおそらくは新しく struct mm_struct の領域を確保して current->mm からコピィをして云々、な模様。ドキュメントではここで struct mm_struct について確認をしています。include/linux/mm_types.h にて定義されています。
とりあえずドキュメントのメモを以下に列挙。
- 「プロセスアドレス空間内の様々な領域」を表現したものが vm_area_struct 構造体
- do_mmap の先頭あたりに出てくる anon_vma_fork という手続き
- anon は Annonymous Memory を指していると思われる
- Annonymous Memory とはスタックや .data などの「バッキングストア (元ネタとなるファイル) のないデータを格納するためのメモリ領域」
で、anon_vma_fork 起点で掘削が始まっています。
- anon_vma_fork
- anon_vma_clone
- struct anon_vma_chain とか struct anon_vma など
- anon_vma は private “related” vmas のリストの先頭
- struct anon_vma_chain は struct list_head な same_vma という属性を持っている
む、clone てリスト手繰って親のソレを参照してるだけなのか。
Annonymous Memory と物理ページ
そろそろ限界なカンジorz
struct page に Annonymous Memory がどう紐付けられているか、について。
- page->mapping の末端 2 bit で ANON, KSM, それ以外を区別している?
- linear_page_index という手続きで仮想アドレスを page->index に変換
- Annonymous Memory の場合、vm_pgoff に vma の先頭アドレスをページ単位に丸めた値が格納
page->index はオフセットというかインデクスなのか。確かに仮想アドレスから変換してる、というのは分かったような分からないような。
時間切れ
ネタ見つけた、なエントリの残りよっつも月曜とかで読めれば良いな。