《构建根文件系统(一)init_post内核启动第一个应用程序》
1.init_post启动应用程序
在内核经过一系列得初始化以及挂载了根文件系统后,最后就是运行第一个应用程序。
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING "Warning: unable to open an initial console.\n");
打开dev/console控制台设备(串口0),使用户能输入信息, /dev/console即成为kernel_init进程的标准输入源(文件描述符0),打开失败则打印Warning: unable to open an initial console.\n
因此当我们删除根文件系统里面得内容,然后再启动内核,就会打印上面得消息,因为找不到/dev/console
虽然根文件系统挂载上了,但是找不到里面得相关内容。
(void) sys_dup(0); (void) sys_dup(0);
sys_dup()的主要工作就是用来“复制”一个打开的文件号,使两个文件号都指向同一个文件。
所以这里复制了上面打开的/dev/console。这样就使得这个控制台有三个文件文件描述符:标准输入、标准输出、标准错误。
if (ramdisk_execute_command) { run_init_process(ramdisk_execute_command); printk(KERN_WARNING "Failed to execute %s\n", ramdisk_execute_command); }
通过对ramdisk_execute_command全局搜索发现,ramdisk_execute_command = str;
static int __init rdinit_setup(char *str) { unsigned int i; ramdisk_execute_command = str; /* See "auto" comment in init_setup */ for (i = 1; i < MAX_INIT_ARGS; i++) argv_init[i] = NULL; return 1; } __setup("rdinit=", rdinit_setup);
__setup的结构在之前已经解释过了,最后拆解完,会将rdinit=后面的字符串作为参数传递进去并赋给ramdisk_execute_command。
if (execute_command) { run_init_process(execute_command); printk(KERN_WARNING "Failed to execute %s. Attempting " "defaults...\n", execute_command); }
这个和上面的一样,查找后
static int __init init_setup(char *str) { unsigned int i; execute_command = str; /* * In case LILO is going to boot us with default command line, * it prepends "auto" before the whole cmdline which makes * the shell think it should execute a script with such name. * So we ignore all arguments entered _before_ init=... [MJ] */ for (i = 1; i < MAX_INIT_ARGS; i++) argv_init[i] = NULL; return 1; } __setup("init=", init_setup);
所以当我们在bootarg中设置了init=linuxrc的时候,就会将linuxrc以传址的方式传给execute_command。
然后运行run_init_process(“linuxrc”);程序就一去不复还的启动应用程序。
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.");
如果没有设置bootarg参数,init_post会启动默认的应用程序。"/sbin/init" "/etc/init" "/bin/init" "/bin/sh"。最后都没找到就会打印信息。