/sbin/initの疑問?


カーネルの起動は、最低限のモジュール群の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では起動せず、INIT=/sbin/initとすると起動しました。間違いなくinitスクリプトは/sbin/initに配置されていると言う事です。)

たぶん、カーネルでrootfsとしてintramfsを展開する時に、/initが、/sbin/initとなる様にしてるんだろうと。でソースを見てみましたが、まったく分かりません。で、上の前提すら、正しいの? って。

fedora16のinitramfsの内容
[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
./init
start_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と違うようです。


最終更新 2013/04/29 00:37:53 - north
(2013/04/25 20:17:47 作成)


検索

アクセス数
2678690
最近のコメント
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
Adsense
広告情報が設定されていません。