/var/log/messages

debugging with sixth sense

Cgroup 関連の記事読んだ

とりあえず 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 はオフセットというかインデクスなのか。確かに仮想アドレスから変換してる、というのは分かったような分からないような。

時間切れ

ネタ見つけた、なエントリの残りよっつも月曜とかで読めれば良いな。

Comments