构建根文件系统之启动第1个程序init
目錄
- 打開標準輸入/輸出/錯誤
- 執行init進程
- 小結測試
- init實現
- 總結
引入
在Kernel源碼分析中,了解到init_post是在掛載根文件系統之后執行應用程序
打開標準輸入/輸出/錯誤
Linux首先打開標準輸入scanf,標準輸出printf,標準錯誤err
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)printk(KERN_WARNING "Warning: unable to open an initial console.\n");(void) sys_dup(0); //這個是復制的意思 (void) sys_dup(0);這里的sys_dup(0)表示復制打開的第0個文件,也就是/dev/console,也就是說標準輸入scanf,標準輸出printf,標準錯誤err都定位到/dev/console這個文件,這個文件被稱為終端,他可以是串口或者液晶鍵盤組合等
執行init進程
接下來會處理U-boot傳遞進來的命令行參數
//run_init_process 一般會正確執行不會返回的程序 if (execute_command) {run_init_process(execute_command);printk(KERN_WARNING "Failed to execute %s. Attempting ""defaults...\n", 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.");我們搜索下execute_command,發現如下定義,很明顯和kernel源碼分析中的命令行參數類似
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);也是設置一個段屬性固定的結構體
#define __setup(str, fn) \__setup_param(str, fn, fn, 0)#define __setup_param(str, unique_id, fn, early) \static char __setup_str_##unique_id[] __initdata = str; \static struct obs_kernel_param __setup_##unique_id \__attribute_used__ \__attribute__((__section__(".init.setup"))) \__attribute__((aligned((sizeof(long))))) \= { __setup_str_##unique_id, fn, early }也就是構造了一個和root=/dev/mtdblock3類似的
static char __setup_str_init_dev_setup[] __initdata = "init="; static struct obs_kernel_param __setup_init_dev_setup __attribute_used____attribute__((__section__(".init.setup"))) __attribute__((aligned((sizeof(long))))) ={__setup_str_init_dev_setup,root_init_setup,init_dev_setup,0}這個結構體的原型如下 struct obs_kernel_param {const char *str;int (*setup_func)(char *);int early; };也就是說execute_command=/linuxrc,因為u-boot傳遞的參數是init=/linuxrc,程序會使用run_init_process(execute_command);來處理這個命令行
注意?函數run_init_process一般會正確執行不會返回的程序,也就是說如果能夠正確執行u-boot傳遞的參數,將不會執行以下
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.");小結測試
(一)
燒錄u-boot,燒錄Linux,擦除根文件系統nand erase root,也就是不放根文件系統,系統會有如下提示
VFS: Mounted root (yaffs filesystem). 掛接了根文件系統,但是flash是空的,默認識別為yaffs Freeing init memory: 140K Warning: unable to open an initial console. flash是空的,無法啟動應用程序 Failed to execute /linuxrc. Attempting defaults... 錯誤指示--命令行 Kernel panic - not syncing: No init found. Try passing init= option to kernel.因為格式化了flash,系統可以識別為任意的文件系統,默認識別為yaffs,但是由于沒有根文件系統,所以無法打開標準輸入輸出,按照代碼所寫的提示錯誤
printk(KERN_WARNING "Warning: unable to open an initial console.\n");同時也就無法打開init進程,提示
panic("No init found. Try passing init= option to kernel.");(二)
燒入根文件系統,在u-boot下輸入y,下載文件系統fs_mini.yaffs2,然后啟動.輸入ps看下啟動的應用程序
# psPID Uid VSZ Stat Command1 0 3092 S init2 0 SW< [kthreadd]3 0 SWN [ksoftirqd/0]4 0 SW< [watchdog/0]5 0 SW< [events/0]6 0 SW< [khelper]55 0 SW< [kblockd/0]56 0 SW< [ksuspend_usbd]59 0 SW< [khubd]61 0 SW< [kseriod]73 0 SW [pdflush]74 0 SW [pdflush]75 0 SW< [kswapd0]76 0 SW< [aio/0]710 0 SW< [mtdblockd]745 0 SW< [kmmcd]767 0 3096 S -sh769 0 3096 R ps這里init就是啟動的第一個進程sh也就是終端接收輸入以及打印的輸出
init實現
在嵌入式Linux中的一些基礎命令例如ls,cp等實際上也是一個個App,這些基本命令一般由busybox編譯得到一個名為busybox的應用程序.然后ls,cd,cp等命令一般是其鏈接.可以使用ls-l xxx來查看其鏈接屬性.可以先用which xxx查看其位置,然后看屬性
# ls -l /bin/ls lrwxrwxrwx 1 1000 1000 7 Jan 6 2010 /bin/ls -> busybox# ls bin lib mnt sbin usr dev linuxrc proc sys etc lost+found root tmp# busybox ls bin lib mnt sbin usr dev linuxrc proc sys etc lost+found root tmp其實,/sbin/init也是到busybox的鏈接
run_init_process("/sbin/init"); run_init_process("/etc/init"); run_init_process("/bin/init"); run_init_process("/bin/sh");# which init /sbin/init # ls -l /sbin/init lrwxrwxrwx 1 1000 1000 14 Jan 6 2010 /sbin/init -> ../bin/busybox總結
轉載:https://www.cnblogs.com/zongzi10010/p/10023703.html?
總結
以上是生活随笔為你收集整理的构建根文件系统之启动第1个程序init的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内核启动流程分析(四)源码浅析
- 下一篇: 构建根文件系统之busybox(二)编译