Linuxのinit_taskに設定されるmnt_nsはコンパイル時には設定されていなくて実行時に決定されてます。で、それがどこで設定されているのかのメモです。
まず、nsproxy.cでinit_taskはこのように作られていて、mnt_nsはNULLが初期値になっている。
31 struct nsproxy init_nsproxy = { 32 .count = ATOMIC_INIT(1), 33 .uts_ns = &init_uts_ns, 34 #if defined(CONFIG_POSIX_MQUEUE) || defined(CONFIG_SYSVIPC) 35 .ipc_ns = &init_ipc_ns, 36 #endif 37 .mnt_ns = NULL, 38 .pid_ns_for_children = &init_pid_ns, 39 #ifdef CONFIG_NET 40 .net_ns = &init_net, 41 #endif 42 };
結論から先にだすと実際に設定をしているのはfs/namespace.cのinit_mount_tree()。 ここまでのフローはというと、このような感じ。
-> start_kernel() @init/main.c -> vfs_caches_init() @fs/dcache.c -> mnt_init() @fs/namespace.c -> init_mount_tree() @fs/namespace.c
init_mount_tree()が大体のことを実行するけど、ここから呼ばれる関数で名前空間関連のところはcreate_mnt_ns()とalloc_mnt_ns()。alloc_mnt_ns()のほうはmnt_namespace構造体のインスタンスと作って変数を初期化したりという程度でこれといった処理は無いです。 create_mnt_ns()はalloc_mnt_ns()を呼んでmnt_namespace構造体を初期化したあとに↓の処理をして新しく作成したマウント名前空間のroot(/)に現在のルートファイルシステムを設定してます。
2812 struct mount *mnt = real_mount(m); 2813 mnt->mnt_ns = new_ns; 2814 new_ns->root = mnt; 2815 list_add(&mnt->mnt_list, &new_ns->list);
ここで使っているmはcreate_mnt_ns()の引数でvfsmount構造体です。これはinit_mount_tree()で以下のように取得しています。
3041 type = get_fs_type("rootfs"); 3042 if (!type) 3043 panic("Can't find rootfs type"); 3044 mnt = vfs_kern_mount(type, 0, "rootfs", NULL);
それで、init_mount_tree()はどんな処理をしているかというと、create_mnt_ns()を呼ぶ前までの処理は上に示したルートファイルシステムを取得するくらいです。そして、create_mnt_ns()を呼びmnt_namspace構造体の初期化や、ルートファイルシステムの割当をしてます。あとはcreate_mnt_ns()から戻ったあとにinit_taskのnsproxy->mnt_nsにcreate_mnt_ns()で設定したmnt_namsapsce構造体のインスタンスを設定して完了です。
3049 ns = create_mnt_ns(mnt); 3050 if (IS_ERR(ns)) 3051 panic("Can't allocate initial namespace"); 3052 3053 init_task.nsproxy->mnt_ns = ns;
これでinitの処理が終わってpid1が立ち上がってしまえば、あとはfork(1)などの時にこのmnt_nsが共有されたり分離されたりとなります。
自作エミュレータで学ぶx86アーキテクチャ-コンピュータが動く仕組みを徹底理解!
- 作者: 内田公太,上川大介
- 出版社/メーカー: マイナビ
- 発売日: 2015/08/28
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る