【内核挂载根文件系统分析】
在init内核线程中:
static int init(void* unused)
{
structfiles_struct *files;
lock_kernel();
do_basic_setup();
prepare_namespace(); //准备命名空间
free_initmem();
unlock_kernel();
files= current->files;
if(unshare_files())
panic("unshare");
put_files_struct(files);
if(open("/dev/console", O_RDWR, 0)< 0)
printk("Warning:unable to open an initial console.\n");
……
}
void prepare_namespace(void)
{
……
mount_root(); //挂载根文件系统
……
}
static void __init mount_root(void)
{
……
devfs_make_root(root_device_name);
create_dev("/dev/root",ROOT_DEV, root_device_name);
……
mount_block_root("/dev/root",root_mountflags);
}
static void __init mount_block_root(char*name, int flags)
{
……
printk("VFS: Cannot open root device \"%s\" or %s\n",
root_device_name, kdevname (ROOT_DEV));
printk("Please append a correct \"root=\" boot option\n");
panic("VFS:Unable to mount root fs on %s",
kdevname(ROOT_DEV));
}
panic("VFS:Unable to mount root fs on %s", kdevname(ROOT_DEV));
out:
putname(fs_names);
sys_chdir("/root");
ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
printk("VFS: Mounted root (%s filesystem)%s.\n",
current->fs->pwdmnt->mnt_sb->s_type->name,
(current->fs->pwdmnt->mnt_sb->s_flags& MS_RDONLY) ? " readonly" : "");
/*44b0打印为:VFS: Mounted root (romfs filesystem) readonly.*/
}
注释:参数root_device_name是由启动参数传递过来的。
static int __init root_dev_setup(char*line)
{
inti;
charch;
ROOT_DEV= name_to_kdev_t(line);
memset(root_device_name, 0, sizeof root_device_name);
if(strncmp (line, "/dev/", 5) == 0)line += 5; //该函数得到的命令行为root=/dev/xxx
for(i = 0; i < sizeof root_device_name - 1; ++i)
{
ch = line[i];
if ( isspace (ch) || (ch == ',') || (ch =='\0') ) break;
root_device_name[i]= ch;
}
return1;
}
__setup("root=",root_dev_setup); //__setup为一个宏定义
#define __setup(str, fn) \
staticchar __setup_str_##fn[] __initdata = str; \
staticstruct kernel_param __setup_##fn __attribute__((unused)) __initsetup = {__setup_str_##fn, fn }
替换为:
#define __setup("root=", root_dev_setup) \
staticchar __setup_str_ root_dev_setup__initdata = "root=" \
staticstruct kernel_param __setup_ root_dev_setup __attribute__((unused)) __initsetup =
{__setup_str_root_dev_setup, root_dev_setup}
其中:
#define __initdata __attribute__ ((__section__ (".data.init")))
#define __initsetup __attribute__((unused,__section__ (".setup.init")))
在vmlinux.lds中:
……
__tagtable_begin= .;
*(.taglist)
__tagtable_end= .;
*(.data.init)
.= ALIGN(16);
__setup_start = .;
*(.setup.init)
__setup_end = .;
kernel_param结构体为:
struct kernel_param {
constchar *str;
int(*setup_func)(char *);
};
static int __init checksetup(char*line)
{
structkernel_param *p;
p= &__setup_start;
do{
intn = strlen(p->str);
if(!strncmp(line,p->str,n)) {
if(p->setup_func(line+n))
return1;
}
p++;
}while (p < &__setup_end);
return0;
}
static void __init parse_options(char*line)
{
……
if(checksetup(line)) // start_kernel中调用了parse_options(command_line);
continue;
……
}