色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

基于linux內核啟動程序

嵌入式小生 ? 來源:嵌入式小生 ? 作者:嵌入式小生 ? 2022-10-14 09:11 ? 次閱讀

linux內核啟動過程的后期,在kernel_init()函數代表的init線程中,會嘗試執行用戶空間的init進程:

a9272532-4b57-11ed-a3b6-dac502259ad0.png

從上述代碼可見,會嘗試執行/sbin/、/etc、/bin三個目錄中的init。從《busybox源碼分析筆記(一)》一文可以知道,在busybox編譯構建完成并安裝后,會生成對應的目錄(注:/etc目錄不存在)。在/sbin目錄中,則會存在一個init鏈接:

a955e37c-4b57-11ed-a3b6-dac502259ad0.png

查看其屬性,其本質則是鏈接到了../bin/busybox:

a975872c-4b57-11ed-a3b6-dac502259ad0.png

綜上所述,證明linux內核啟動后期,運行的第一個用戶空間程序是init,在busybox源碼中,init程序則由位于/init目錄中的init.c編譯構建而成,程序入口是:init_main(),小生在該函數中添加一行標識代碼:

a9913efe-4b57-11ed-a3b6-dac502259ad0.pnglinux內核運行后期的結果如下:

a9b277a4-4b57-11ed-a3b6-dac502259ad0.gif

可見,linux內核后期加載的就是busybox下的init程序。

init_main分析

貼上該函數的完整代碼,下文將分段描述:

intinit_main(intargcUNUSED_PARAM,char**argv)
{
structsigactionsa;

INIT_G();

/*SomeuserssendpoweroffsignalstoinitVERYearly.
*Tohandlethis,masksignalsearly.
*/
/*sigemptyset(&G.delayed_sigset);-donebyINIT_G()*/
sigaddset(&G.delayed_sigset,SIGINT);/*Ctrl-Alt-Del*/
sigaddset(&G.delayed_sigset,SIGQUIT);/*re-execanotherinit*/
#ifdefSIGPWR
sigaddset(&G.delayed_sigset,SIGPWR);/*halt*/
#endif
sigaddset(&G.delayed_sigset,SIGUSR1);/*halt*/
sigaddset(&G.delayed_sigset,SIGTERM);/*reboot*/
sigaddset(&G.delayed_sigset,SIGUSR2);/*poweroff*/
#ifENABLE_FEATURE_USE_INITTAB
sigaddset(&G.delayed_sigset,SIGHUP);/*reread/etc/inittab*/
#endif
sigaddset(&G.delayed_sigset,SIGCHLD);/*makesigtimedwait()exitonSIGCHLD*/
sigprocmask(SIG_BLOCK,&G.delayed_sigset,NULL);

#ifDEBUG_SEGV_HANDLER
memset(&sa,0,sizeof(sa));
sa.sa_sigaction=handle_sigsegv;
sa.sa_flags=SA_SIGINFO;
sigaction_set(SIGSEGV,&sa);
sigaction_set(SIGILL,&sa);
sigaction_set(SIGFPE,&sa);
sigaction_set(SIGBUS,&sa);
#endif

if(argv[1]&&strcmp(argv[1],"-q")==0){
returnkill(1,SIGHUP);
}

#if!DEBUG_INIT
/*ExpecttobeinvokedasinitwithPID=1orbeinvokedaslinuxrc*/
if(getpid()!=1
&&(!ENABLE_LINUXRC||applet_name[0]!='l')/*notlinuxrc?*/
){
bb_simple_error_msg_and_die("mustberunasPID1");
}

#ifdefRB_DISABLE_CAD
/*TurnoffrebootingviaCTL-ALT-DEL-wegeta
*SIGINTonCADsowecanshutthingsdowngracefully...*/
reboot(RB_DISABLE_CAD);/*misnomer*/
#endif
#endif

/*If,say,xmallocwouldeverdie,wedon'twanttooopskernel
*byexiting.
*NB:wesetdie_func*after*PID1checkandbb_show_usage.
*Otherwise,forexample,"initu"("pleaserexecyourself"
*commandforsysvinit)willshowhelptext(whichisn'ttoobad),
**andsleepforever*(whichisbad!)
*/
die_func=sleep_much;

/*Figureoutwherethedefaultconsoleshouldbe*/
console_init();
set_sane_term();
xchdir("/");
setsid();

/*Makesureenvironsissettosomethingsane*/
putenv((char*)"HOME=/");
putenv((char*)bb_PATH_root_path);
putenv((char*)"SHELL=/bin/sh");
putenv((char*)"USER=root");/*needed?why?*/

if(argv[1])
xsetenv("RUNLEVEL",argv[1]);

#if!ENABLE_FEATURE_INIT_QUIET
/*Helloworld*/
message(L_CONSOLE|L_LOG,"initstarted:%s",bb_banner);
#endif

/*Checkifwearesupposedtobeinsingleusermode*/
if(argv[1]
&&(strcmp(argv[1],"single")==0||strcmp(argv[1],"-s")==0||LONE_CHAR(argv[1],'1'))
){
/*???shouldn'twesetRUNLEVEL="b"here?*/
/*Startashellonconsole*/
new_init_action(RESPAWN,bb_default_login_shell,"");
}else{
/*Notinsingleusermode-seewhatinittabsays*/

/*NOTEthatifCONFIG_FEATURE_USE_INITTABisNOTdefined,
*thenparse_inittab()simplyaddsinsomedefault
*actions(i.e.,INIT_SCRIPTandapair
*of"askfirst"shells)*/
parse_inittab();
}

#ifENABLE_SELINUX
if(getenv("SELINUX_INIT")==NULL){
intenforce=0;

putenv((char*)"SELINUX_INIT=YES");
if(selinux_init_load_policy(&enforce)==0){
BB_EXECVP(argv[0],argv);
}elseif(enforce>0){
/*SELinuxinenforcingmodebutload_policyfailed*/
message(L_CONSOLE,"can'tloadSELinuxPolicy."
"Machineisinenforcingmode.Haltingnow.");
returnEXIT_FAILURE;
}
}
#endif

#ifENABLE_FEATURE_INIT_MODIFY_CMDLINE
/*Makethecommandlinejustsay"init"-that'sall,nothingelse*/
strncpy(argv[0],"init",strlen(argv[0]));
/*Wipeargv[1]-argv[N]sotheydon'tclutterthepslisting*/
while(*++argv)
nuke_str(*argv);
#endif

/*SetupSTOPsignalhandlers*/
/*StophandlermustallowonlySIGCONTinsideitself*/
memset(&sa,0,sizeof(sa));
sigfillset(&sa.sa_mask);
sigdelset(&sa.sa_mask,SIGCONT);
sa.sa_handler=stop_handler;
sa.sa_flags=SA_RESTART;
sigaction_set(SIGTSTP,&sa);/*pause*/
/*Doesnotworkasintended,atleastin2.6.20.
*SIGSTOPissimplyignoredbyinit
*(NB:behaviormightdifferunderstrace):
*/
sigaction_set(SIGSTOP,&sa);/*pause*/

/*Nowruneverythingthatneedstoberun*/
/*Firstrunthesysinitcommand*/
run_actions(SYSINIT);
check_delayed_sigs(&G.zero_ts);
/*Nextrunanythingthatwantstoblock*/
run_actions(WAIT);
check_delayed_sigs(&G.zero_ts);
/*Nextrunanythingtoberunonlyonce*/
run_actions(ONCE);

/*Nowruntheloopingstufffortherestofforever*/
while(1){
/*(Re)runtherespawn/askfirststuff*/
run_actions(RESPAWN|ASKFIRST);

/*Waitforanysignal(typicallyit'sSIGCHLD)*/
check_delayed_sigs(NULL);/*NULLtimespecmakesitwait*/

/*Waitforanychildprocess(es)toexit*/
while(1){
pid_twpid;
structinit_action*a;

wpid=waitpid(-1,NULL,WNOHANG);
if(wpid<=?0)
????break;

???a?=?mark_terminated(wpid);
???if?(a)?{
????message(L_LOG,?"process?'%s'?(pid?%u)?exited.?"
??????"Scheduling?for?restart.",
??????a->command,(unsigned)wpid);
}
}

/*Don'tconsumeallCPUtime-sleepabit*/
sleep1();
}/*while(1)*/
}

跳過條件宏定義下的編譯分支,主要分析其通用的代碼部分:

(1)首先使用sigaddset()將信號添加到信號集合,添加的信號有:Ctrl-Alt-Del、SIGQUIT、SIGPWR、SIGUSR1、SIGTERM、SIGUSR2、SIGUSR2。

(2)然后找出系統默認的控制臺,并將路徑切換到/,接著重新創建一個新的會話:

console_init();
set_sane_term();
xchdir("/");
setsid();

(3)設置默認的環境變量:

putenv((char*)"HOME=/");
putenv((char*)bb_PATH_root_path);
putenv((char*)"SHELL=/bin/sh");
putenv((char*)"USER=root");/*needed?why?*/

(4)如果是單用戶模式,則會調用new_init_action(RESPAWN, bb_default_login_shell, "");在控制臺啟動一個shell;否則,則會調用parse_inittab()函數。

parse_inittab()函數定義如下:

staticvoidparse_inittab(void)
{
#ifENABLE_FEATURE_USE_INITTAB
char*token[4];
parser_t*parser=config_open2("/etc/inittab",fopen_for_read);

if(parser==NULL)
#endif
{
/*Noinittabfile-setupsomedefaultbehavior*/
/*Sysinit*/
new_init_action(SYSINIT,INIT_SCRIPT,"");
/*Askfirstshellontty1-4*/
new_init_action(ASKFIRST,bb_default_login_shell,"");
//TODO:VC_1insteadof""?""isconsole->cttyproblems->angryusers
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);
/*RebootonCtrl-Alt-Del*/
new_init_action(CTRLALTDEL,"reboot","");
/*Umountallfilesystemsonhalt/reboot*/
new_init_action(SHUTDOWN,"umount-a-r","");
/*Swapoffonhalt/reboot*/
new_init_action(SHUTDOWN,"swapoff-a","");
/*RestartinitwhenaQUITisreceived*/
new_init_action(RESTART,"init","");
return;
}

#ifENABLE_FEATURE_USE_INITTAB
/*optional_ttyaction:command
*Delimsarenottobecollapsedandneedexactly4tokens
*/
while(config_read(parser,token,4,0,"#:",
PARSE_NORMAL&~(PARSE_TRIM|PARSE_COLLAPSE))){
/*ordermustcorrespondtoSYSINIT..RESTARTconstants*/
staticconstcharactions[]ALIGN1=
"sysinit?""wait?""once?""respawn?""askfirst?"
"ctrlaltdel?""shutdown?""restart?";
intaction;
char*tty=token[0];

if(!token[3])/*lessthan4tokens*/
gotobad_entry;
action=index_in_strings(actions,token[2]);
if(action/dev/TTY*/
if(tty[0]){
tty=concat_path_file("/dev/",skip_dev_pfx(tty));
}
new_init_action(1<lineno);
}
config_close(parser);
#endif
}

如果定義了CONFIG_FEATURE_USE_INITTAB,則會使用/etc/inittab文件中的action;如果CONFIG_FEATURE_USE_INITTAB沒有定義,parse_inittab()則會簡單添加一些默認actions(例如,運行INIT_SCRIPT,然后啟動一個“askfirst”shell)。如果ENABLE_FEATURE_USE_INITTAB已定義,但是/etc/inittab文件缺失也會使用相同的默認行為集合。

(5)設置STOP信號處理程序:

memset(&sa,0,sizeof(sa));
sigfillset(&sa.sa_mask);
sigdelset(&sa.sa_mask,SIGCONT);
sa.sa_handler=stop_handler;
sa.sa_flags=SA_RESTART;
sigaction_set(SIGTSTP,&sa);/*pause*/

sigaction_set(SIGSTOP,&sa);/*pause*/

(6)接下來運行想要運行的命令,依次運行:SYSINIT、WAIT、ONCE:

run_actions(SYSINIT);
check_delayed_sigs(&G.zero_ts);

run_actions(WAIT);
check_delayed_sigs(&G.zero_ts);

run_actions(ONCE);

(7)在最后,則是一個while(1)的死循環,用于處理我們在命令行下輸入的命令:

while(1){
/*重新運行respawn/askfisrt*/
run_actions(RESPAWN|ASKFIRST);

/*等待信號*/
check_delayed_sigs(NULL);/*NULLtimespecmakesitwait*/

/*等待所有的子進程退出*/
while(1){
pid_twpid;
structinit_action*a;

wpid=waitpid(-1,NULL,WNOHANG);
if(wpid<=?0)
????break;

???a?=?mark_terminated(wpid);
???if?(a)?{
????message(L_LOG,?"process?'%s'?(pid?%u)?exited.?"
??????"Scheduling?for?restart.",
??????a->command,(unsigned)wpid);
}
}

/*短暫讓出CPU,不要消耗所有的CPU時間*/
sleep1();
}/*while(1)*/

補充

BusyBox的init不支持運行級別。runlevels字段在BusyBox init中將會被完全忽略。

所以如果想要使用運行級別的系統,需使用sysvinit作為啟動進程。

一、7個運行級別

(1)運行級別0:系統停機狀態,系統默認運行級別不能設為0,否則不能正常啟動。其實就是關機。

(2)運行級別1:單用戶工作狀態,root權限,用于系統維護,禁止遠程登陸。在忘記root密碼時一般用這個運行級別,進去修改root密碼。

(3)運行級別2:多用戶狀態(沒有NFS),沒有網絡連接。

(4)運行級別3:完全的多用戶狀態(有NFS),登陸后進入控制臺命令行模式。linux很常見的運行級別

(5)運行級別4:系統未使用,保留。

(6)運行級別5:X11控制臺,登陸后進入圖形GUI模式。就是圖形模式。

(7)運行級別6:系統正常關閉并重啟,默認運行級別不能設為6,否則不能正常啟動。

二、查看運行級別

1、runlevel命令:打印系統的上一個和當前運行級別:

aa1518dc-4b57-11ed-a3b6-dac502259ad0.png

N:“N”表示自系統啟動后運行級別尚未更改。從上圖可見,小生的Ubuntu系統的運行級別為5。

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4338

    瀏覽量

    62787
  • 代碼
    +關注

    關注

    30

    文章

    4805

    瀏覽量

    68777
  • LINUX內核
    +關注

    關注

    1

    文章

    316

    瀏覽量

    21685
收藏 人收藏

    評論

    相關推薦

    Linux編譯驅動、內核及應用程序分析

    作為一名嵌入式Linux新手,在學習的過程中會遇到很多問題。寫了一個驅動程序怎么編譯?怎么加載進內核?
    的頭像 發表于 01-17 13:46 ?6667次閱讀
    <b class='flag-5'>Linux</b>編譯驅動、<b class='flag-5'>內核</b>及應用<b class='flag-5'>程序</b>分析

    Linux內核啟動過程和Bootloader(總述)

    精簡講述linux內核啟動過程。[轉]1.Linux內核啟動過程概述 一個嵌入式
    發表于 08-18 17:35

    【OK210試用體驗】bootloader啟動linux內核

    的性能和穩定性。用戶空間的文件系統用來提供管理系統的各種配置,提供相應的應用程序、服務、數據交換等。文件系統作為一種載體,它是用來實現用戶與操作系統內核的交互。因此,一個可啟動linux
    發表于 01-10 15:57

    Linux內核編譯和啟動的相關資料分享

    Linux環境下,我們想運行一個應用程序,在shell交互環境下直接敲命令就可以了,操作系統給程序提供了運行環境和進程管理。那Linux操作系統本身是如何運行和
    發表于 12-20 06:28

    Android的Linux內核與驅動程序開發教程

    Android內核是基于Linux 2.6內核的,它是一個增強內核版本,除了修改部分Bug外,它提供了用于支持Android平臺的設備驅動,這里介紹了Android
    發表于 09-05 14:24 ?335次下載
    Android的<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>與驅動<b class='flag-5'>程序</b>開發教程

    linux內核啟動內核解壓過程分析

    linux啟動內核解壓過程分析,一份不錯的文檔,深入了解內核必備
    發表于 03-09 13:39 ?1次下載

    Linux內核文檔:ARM-啟動

    Linux內核文檔:ARM-啟動
    發表于 10-30 10:15 ?6次下載
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>文檔:ARM-<b class='flag-5'>啟動</b>

    linux內核啟動流程

    Linux啟動代碼真的挺大,從匯編到C,從Makefile到LDS文件,需要理解的東西很多。畢竟Linux內核是由很多人,花費了巨大的時間和精力寫出來的。而且直到現在,這個世界上仍然
    發表于 11-14 16:19 ?4359次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內核</b><b class='flag-5'>啟動</b>流程

    linux內核無法啟動

     Linux啟動過程中會出現一些故障,導致系統無法正常啟動,本文列舉了幾個應用單用戶模式、GRUB命令操作、Linux救援模式的典型故障修復案例幫助讀者了解此類問題的解決。
    發表于 11-14 17:26 ?3040次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內核</b>無法<b class='flag-5'>啟動</b>

    嵌入式Linux內核的驅動程序開發是怎樣的

    設備驅動程序linux內核的一部分,是操作系統內核和機器硬件之間的接口,它由一組函數和一些私有數據組成,是連接應用程序與具體硬件的橋梁。
    發表于 11-06 11:33 ?1519次閱讀
    嵌入式<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>的驅動<b class='flag-5'>程序</b>開發是怎樣的

    最硬核的Linux內核文章

    內核。 擁有超過1300萬行的代碼,Linux內核是世界上最大的開源項目之一,但是內核是什么,它用于什么? 02 什么是內核
    的頭像 發表于 10-19 17:46 ?2140次閱讀
    最硬核的<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>文章

    快速理解什么是Linux內核以及Linux內核的內容

    01 前言 本文主要講解什么是Linux內核,以及通過多張圖片展示Linux內核的作用與功能,以便于讀者能快速理解什么是Linux
    的頭像 發表于 10-21 12:02 ?4313次閱讀
    快速理解什么是<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>以及<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>的內容

    如何使用Linux內核實現USB驅動程序框架

    Linux內核提供了完整的USB驅動程序框架。USB總線采用樹形結構,在一條總線上只能有唯一的主機設備。 Linux內核從主機和設備兩個角度
    發表于 11-06 17:59 ?20次下載
    如何使用<b class='flag-5'>Linux</b><b class='flag-5'>內核</b>實現USB驅動<b class='flag-5'>程序</b>框架

    Linux內核啟動流程(下)

    本篇是通用內核啟動階段,一般是C語言實現。
    發表于 06-23 14:08 ?578次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b><b class='flag-5'>啟動</b>流程(下)

    linux驅動程序如何加載進內核

    ,需要了解Linux內核的基本概念和API。以下是一些關鍵概念: 1.1 內核模塊:Linux內核模塊是一種動態加載和卸載的代碼,可以在不重
    的頭像 發表于 08-30 15:02 ?523次閱讀
    主站蜘蛛池模板: 国产欧美国日产在线播放| 久色视频网| 欧美另类老女人| 99国产这里只有精品视频| 美女被爽cao免费漫画| 中国老太60old mantv| 久久99re2热在线播放7| 亚洲免费每日在线观看| 久久4k岛国高清一区二区| 一级做a爰片久久毛片一| 经典三级四虎在线观看| 一本道综合久久免费| 久久视频精品38在线播放| 最近的2019中文字幕国语HD| 美女隐私黄www视频| 久久黄色网| 三级电影免费看| 国产成人在线观看网站| 天天色天天干天天| 国产睡熟迷奷系列网站| 亚洲中文有码字幕日本| 美女胸禁止18以下看| seyeye在清在线| 体育生爆操| 黄色三级视频在线| 在线中文字幕视频| 欧美猛男gaygayxxgv| 国产精品69人妻无码久久久| 亚洲欧美国产双大乳头| 免费久久狼人香蕉网| 粉嫩极品国产在线观看| 亚洲精品久久久久AV无码林星阑 | 国产精品久久久久久亚洲影视| 亚洲AV 日韩 国产 有码| 久久精品视频在线看99| 啊…嗯啊好深男男高h文| 小向美奈子厨房magnet| 久久中文字幕亚洲| 东北老妇人70OLDMAN| 亚洲乱码中文字幕久久孕妇黑人| 男人和女人一级黄色大片|