/sbin/initの疑問?
Rev.6を表示中。最新版はこちら。
カーネルの起動は、最低限のモジュール群の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となる様にしてるんだろうと。でソースを見てみましたが、まったく分かりません。で、上の前提すら、正しいの? って。
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 ./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と違うようです。




