/sbin/initの疑問?
Rev.3を表示中。最新版はこちら。
カーネルの起動は、最低限のカーネルとモジュール群のcpioで作成されたintramfsファイルのカーネルが、ロードされ動作し、そこのinitスクリプトから必要なモジュールがロードされ、正規のルートファイルシステムがマウントされ(これも先のinitスクリプト内で)、正規のinitスクリプトが起動し、設定されてある各種初期設定ファイル(inittab/fsta/sytemctr等)に従って、実際の動作環境が構築される。みたいなようなのですが・・・?今まで、カーネルソースで記述されているinit()の/sbin/init,/etc/init,/bin/init,/bin/shは、真のルートファイルシステムのそれだろう。と思っていたのですが、そうでなく、intramfsファイルの物でないかと。思った次第です。
そこで、cpioでintramfsを展開して、シェルスクリプトのinitファイルを見てみると、確かに、ここで真のルートファイルシステムをマウントし、その/sbin/init,/etc/init,/bin/init,/bin/shを起動してるっぽいです。しかし、initは、/にあって、/sbin/,/etc/,/bin/にありません。
(grubメニューから、直接INIT=/initとしてカーネルを立ち上げると、起動しませんでした。)
たぶん、カーネルでrootfsとしてintramfsを展開する時に、/initが、/sbin/initとなる様にしてるんだろうと。でソースを見てみましたが、まったく分かりません。で、上の前提すら、正しいの? って。
[root@localhost initrmafs]# ls -l lrwxrwxrwx 1 root root 17 4月 23 02:41 bin -> run/initramfs/bin drwxr-xr-x 2 root root 4096 4月 23 02:41 dev lrwxrwxrwx 1 root root 17 4月 23 02:41 etc -> run/initramfs/etc -rwxr-xr-x 1 root root 12940 4月 23 02:41 init lrwxrwxrwx 1 root root 17 4月 23 02:41 lib -> run/initramfs/lib drwxr-xr-x 2 root root 4096 4月 23 02:41 proc drwxr-xr-x 2 root root 4096 4月 23 02:41 root drwxr-xr-x 5 root root 4096 4月 23 02:41 run lrwxrwxrwx 1 root root 18 4月 23 02:41 sbin -> run/initramfs/sbin drwxr-xr-x 2 root root 4096 4月 23 02:41 sys drwxr-xr-x 2 root root 4096 4月 23 02:41 sysroot lrwxrwxrwx 1 root root 17 4月 23 02:41 tmp -> run/initramfs/tmp lrwxrwxrwx 1 root root 17 4月 23 02:41 usr -> run/initramfs/usr lrwxrwxrwx 1 root root 17 4月 23 02:41 var -> run/initramfs/var [root@localhost initrmafs]# find ./ -name init ./initstart_kernel()から、vfs_caches_init()でrootfsファイルシステムを登録し、init_mount_tree()で/としてマウントします。(ただし、まだその実態はない。)
populate_rootfs()で、intramfsをunpack_to_rootfs()で展開します。たぶんこの時の展開先メモリーを、/のキャッシュページ内に展開するようになっているようです。
最後に、rest_init()からinit()がコールされ、/sbin/init,/etc/init,/bin/init,/bin/shの1つが起動するようになっています。(での疑問は、このinitはどこのinit?)
asmlinkage void __init start_kernel(void) { : vfs_caches_init(num_physpages); : populate_rootfs(); : rest_init(); } void __init vfs_caches_init(unsigned long mempages) { names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (!names_cachep) panic("Cannot create names SLAB cache"); filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, SLAB_HWCACHE_ALIGN, filp_ctor, filp_dtor); if(!filp_cachep) panic("Cannot create filp SLAB cache"); dcache_init(mempages); inode_init(mempages); files_init(mempages); mnt_init(mempages); bdev_cache_init(); chrdev_init(); } void __init mnt_init(unsigned long mempages) { : sysfs_init(); init_rootfs(); init_mount_tree(); } int __init init_rootfs(void) { return register_filesystem(&rootfs_fs_type); } static void __init init_mount_tree(void) { struct vfsmount *mnt; struct namespace *namespace; struct task_struct *g, *p; mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); : } void __init populate_rootfs(void) { char *err = unpack_to_rootfs(&__initramfs_start, &__initramfs_end - &__initramfs_start, 0); if (err) panic(err); } static void rest_init(void) { kernel_thread(init, NULL, CLONE_KERNEL); unlock_kernel(); cpu_idle(); } static int init(void * unused) { lock_kernel(); child_reaper = current; smp_prepare_cpus(max_cpus); do_pre_smp_initcalls(); smp_init(); do_basic_setup(); prepare_namespace(); free_initmem(); unlock_kernel(); system_running = 1; if (open("/dev/console", O_RDWR, 0) < 0) printk("Warning: unable to open an initial console.\n"); (void) dup(0); (void) dup(0); if (execute_command) run_init_process(execute_command); run_init_process("/sbin/init"); run_init_process("/etc/init"); run_init_process("/bin/init"); run_init_process("/bin/sh"); panic("No init found. Try passing init= option to kernel."); }ざくっとこんな流れなのですが、populate_rootfs()のunpack_to_rootfs()はcpioファーマットに従って、ひとつづつ処理しているようなのですが、雰囲気、/initを/sbin/initとしている箇所(たぶんシンボリックリンクを作成)が見受けられないのです。 そうなると、/sbin/initは、どのようにして起動しているの? と言うことで、ご存知の方又、後追いして頂いて、解った方がおられましたら、ご教授願えれば幸いです。なお、intrdの実装は、intramfsと違うようです。