构建根文件系统之busybox(一)浅析
生活随笔
收集整理的這篇文章主要介紹了
构建根文件系统之busybox(一)浅析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
- busybox(一)淺析
- 引入
- 讀取inittab
- 創建執行腳本鏈表
- 執行腳本
- 小結
busybox(一)淺析
源碼包在busybox-1.7.0.tar.bz2,一個命令對應著一個c文件,執行init命令,則是有init.c,有函數init_main
int init_main(int argc, char **argv);最終的目的是啟動客戶的應用程序,需要指定具體的環境
1. 配置文件讀取 2. 解析配置文件 3. 執行用戶程序help
相關的幫助可以搜索下/examples下的文件,比如搜索inittab,里面有相關說明
#define SYSINIT 0x001 //執行一次等待結束后從鏈表刪除 #define RESPAWN 0x002 //while循環執行 #define ASKFIRST 0x004 //while循環執行,會打印信息,等待回車 #define WAIT 0x008 //執行一次等待結束后從鏈表刪除,在SYSINIT后 #define ONCE 0x010 //與SYSINIT 區別在于不等待其執行結束 #define CTRLALTDEL 0x020 //輸入信號后執行 #define SHUTDOWN 0x040 //輸入信號后執行 #define RESTART 0x080 //輸入信號后執行流程圖
引入
從init_main函數入口分析,Linux 是按照run_init_process("/sbin/init");形式調用,沒有傳遞參數,所以執行else分支,解析配置表
if (argc > 1&& (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1')) ) {/* Start a shell on console */new_init_action(RESPAWN, bb_default_login_shell, ""); } else {/* Not in single user mode -- see what inittab says *//* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,* then parse_inittab() simply adds in some default* actions(i.e., runs INIT_SCRIPT and then starts a pair* of "askfirst" shells */parse_inittab(); }讀取inittab
parse_inittab();讀取inittab配置表,可以搜索下example下查看例子幫助,查閱如下格式
Format for each entry: <id>:<runlevels>:<action>:<process> <id>: WARNING: This field has a non-traditional meaning for BusyBox init! <runlevels>: The runlevels field is completely ignored. <action>: Valid actions include: sysinit, respawn, askfirst, wait, once,restart, ctrlaltdel, and shutdown. <process>: Specifies the process to be executed and it's command line.| id | 自動加上/dev/的前綴,用作終端,stdin,stdout,stderr:printf,scanf,err 可以省略 |
| runlevels | 可以忽略 |
| action | 指示何止執行 |
| process | 應用程序或者可執行腳本 |
最終執行new_init_action運行腳本程序
默認的配置表讀取
#define INITTAB "/etc/inittab" /* inittab file location */ static void parse_inittab(void) {file = fopen(INITTAB, "r"); }創建執行腳本鏈表
for (a = actions; a->name != 0; a++) {if (strcmp(a->name, action) == 0) {if (*id != '\0') {if (strncmp(id, "/dev/", 5) == 0) //這里為id加上/dev/的前綴id += 5;strcpy(tmpConsole, "/dev/");safe_strncpy(tmpConsole + 5, id,sizeof(tmpConsole) - 5);id = tmpConsole;}new_init_action(a->action, command, id);break;} }當不存在這個配置表的時候也會有一個默認配置文件,這里以默認的其中一個腳本解析
new_init_action(ASKFIRST, bb_default_login_shell, VC_2);# define VC_2 "/dev/tty2" #define ASKFIRST 0x004 const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; #define LIBBB_DEFAULT_LOGIN_SHELL "-/bin/sh"也就是最終執行
new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2"); ASKFIRST 執行的時機 -/bin/sh 腳本程序 /dev/tty2 id終端,加上了/dev/,符合上述描述分析下new_init_action函數內部,
由此,可以理解當配置文件不存在的時候,會去創建配置表
#define INITTAB "/etc/inittab" /* inittab file location */file = fopen(INITTAB, "r");if (file == NULL) {/* No inittab file -- set up some default behavior *//* Reboot on Ctrl-Alt-Del */new_init_action(CTRLALTDEL, "reboot", "");/* Umount all filesystems on halt/reboot */new_init_action(SHUTDOWN, "umount -a -r", "");/* Swapoff on halt/reboot */if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");/* Prepare to restart init when a HUP is received */new_init_action(RESTART, "init", "");/* Askfirst shell on tty1-4 */new_init_action(ASKFIRST, bb_default_login_shell, "");new_init_action(ASKFIRST, bb_default_login_shell, VC_2);new_init_action(ASKFIRST, bb_default_login_shell, VC_3);new_init_action(ASKFIRST, bb_default_login_shell, VC_4);/* sysinit */new_init_action(SYSINIT, INIT_SCRIPT, "");return;} >>>>>>>>>>>>>>>>>>>>>>>>>>>>>↓ 創建類似的inittatb ↓ >>>>>>>>>>>>>>>>>>>>>>>>>>>>>↓ ::CTRLALTDEL:reboot ::SHUTDOWN:umount -a -r ::RESTART:init ::ASKFIRST:-/bin/sh: tty2::ASKFIRST:-/bin/sh tty3::ASKFIRST:-/bin/sh tty4::ASKFIRST:-/bin/sh ::SYSINIT:/etc/init.d/rcS執行腳本
腳本有多種類型,不同類型執行方式與時機不同
#define SYSINIT 0x001 //執行一次等待結束后從鏈表刪除 #define RESPAWN 0x002 //while循環執行 #define ASKFIRST 0x004 //while循環執行,會打印信息,等待回車 #define WAIT 0x008 //執行一次等待結束后從鏈表刪除,在SYSINIT后 #define ONCE 0x010 //與SYSINIT 區別在于不等待其執行結束 #define CTRLALTDEL 0x020 //輸入信號后執行 #define SHUTDOWN 0x040 //輸入信號后執行 #define RESTART 0x080 //輸入信號后執行 run_actions(SYSINIT);waitfor(a, 0);//執行a,等待執行結束run(a);//執行創建process子進程waitpid(runpid, &status, 0);delete_init_action(a);//刪除鏈表/* Next run anything that wants to block */run_actions(WAIT);waitfor(a, 0);//執行a,等待執行結束run(a);//執行創建process子進程waitpid(runpid, &status, 0);delete_init_action(a);//刪除鏈表/* Next run anything to be run only once */run_actions(ONCE);run(a);delete_init_action(a);/* Now run the looping stuff for the rest of forever */while (1) {//重新運行pid已經退出的子進程run_actions(RESPAWN);if (a->pid == 0) { //默認pid為0a->pid = run(a);}run_actions(ASKFIRST);if (a->pid == 0) {a->pid = run(a);}//打印"\nPlease press Enter to activate this console. ";,//等待輸入回車//創建子進程wpid = wait(NULL);//等待子進程退出while (wpid > 0) {a->pid--;//推出后pid=0}}}小結
所以一個最小的根文件系統必備的一些資源
dev/console dev/null sbin/init-------------busybox提供,至少需要這個應用程序,這是linux啟動的第一個應用程序 etc/inittab-----------配置文件,定義了一些應用程序 配置文件制定的應用程序----配置文件指定的應用程序 C庫--------------------應用程序的C庫總結
以上是生活随笔為你收集整理的构建根文件系统之busybox(一)浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从0写bootloader
- 下一篇: 第005课_字符设备驱动