當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式客棧
[導(dǎo)讀][導(dǎo)讀] 前面的文章有提到linux啟動的第一個進(jìn)程為init,那么該進(jìn)程究竟是如何從內(nèi)核啟動入口一步一步運(yùn)行起來的,而該進(jìn)程又有些什么作用呢?做嵌入式Linux開發(fā),有必要對這些概念了解清楚。本文基于ARM體系的內(nèi)核啟動做出解析。 跳轉(zhuǎn)內(nèi)核前基本準(zhǔn)備 參考./Do

[導(dǎo)讀] 前面的文章有提到linux啟動的第一個進(jìn)程為init,那么該進(jìn)程究竟是如何從內(nèi)核啟動入口一步一步運(yùn)行起來的,而該進(jìn)程又有些什么作用呢?做嵌入式Linux開發(fā),有必要對這些概念了解清楚。本文基于ARM體系的內(nèi)核啟動做出解析。

跳轉(zhuǎn)內(nèi)核前基本準(zhǔn)備

參考./Documentation/arm64/booting.txt

Bootloader至少完成以下基本的初始化準(zhǔn)備:

  • 設(shè)置并初始化RAM(必須),引導(dǎo)加載程序應(yīng)找到并初始化內(nèi)核將用于系統(tǒng)中易失性數(shù)據(jù)存儲的所有RAM。它以機(jī)器相關(guān)的方式執(zhí)行此操作。(它可以使用內(nèi)部算法來自動定位和調(diào)整所有RAM的大小,或者可以使用機(jī)器中RAM的知識或引導(dǎo)加載程序設(shè)計(jì)者認(rèn)為合適的任何其他方法。)

  • 設(shè)置設(shè)備樹dtb(必須) , 設(shè)備樹blob(dtb)必須8字節(jié)對齊,并且大小不能超過2兆字節(jié)。由于dtb將使用最大2 MB的塊進(jìn)行映射以可緩存,因此它不能放置在必須使用任何特定屬性進(jìn)行映射的任何2M區(qū)域內(nèi)。注意:v4.2之前的版本還要求將DTB放置在512 MB區(qū)域內(nèi),從內(nèi)核映像下方的text_offset字節(jié)開始計(jì)算。

  • 解壓縮內(nèi)核映像(可選),AArch64內(nèi)核當(dāng)前不提供解壓縮器,因此如果使用壓縮的Image目標(biāo)(例如Image.gz),則需要由引導(dǎo)加載程序執(zhí)行解壓縮(gzip等)。對于未實(shí)現(xiàn)此要求的引導(dǎo)加載程序,可以使用未經(jīng)壓縮內(nèi)核編譯。

  • 調(diào)用內(nèi)核映像(必須)。壓縮內(nèi)核頭部如下:

    u32 code0;              /* 可執(zhí)行code   */
    u32 code1;             /* 可執(zhí)行code   */
    u64 text_offset;       /* 加載偏移,小端 */
    u64 image_size;        /* 有效映象尺寸,小端 */
    u64 flags;             /* 內(nèi)核標(biāo)志, 小端    */
    u64 res2  = 0;         /* 保留 */
    u64 res3  = 0;         /* 保留 */
    u64 res4  = 0;         /* 保留 */
    u32 magic = 0x644d5241/* 幻數(shù),小端, "ARM\x64"  */
    u32 res5;          /* 保留(用于PE COFF偏移量) */

進(jìn)入內(nèi)核之前,必須滿足以下條件:

  • 禁止所有具有DMA功能的設(shè)備,以免內(nèi)存被虛假錯誤的網(wǎng)絡(luò)數(shù)據(jù)包或磁盤數(shù)據(jù)損壞。

  • 主CPU通用寄存器設(shè)置:

    • x0 =系統(tǒng)RAM中設(shè)備樹Blob(dtb)的物理地址。

    • x1/x2/x3 = 0(保留供將來使用)

  • CPU模式

    • 所有形式的中斷都必須在PSTATE.DAIF中屏蔽(調(diào)試,SError,IRQ和FIQ)。

    • CPU必須位于EL2(推薦使用,以便可以訪問虛擬化擴(kuò)展)或非安全EL1中。

  • Caches, MMUs

    • MMU必須關(guān)閉。

    • 指令緩存可以打開或關(guān)閉。

    • 與加載的內(nèi)核映像相對應(yīng)的地址范圍必須清除到PoC。如果存在系統(tǒng)緩存或啟用了緩存的其他相關(guān)主服務(wù)器,則通常需要通過VA而不是通過設(shè)置/方式操作來維護(hù)緩存。

    • 遵循VA對架構(gòu)化緩存維護(hù)的系統(tǒng)緩存。必須配置并啟用操作。

    • 不遵循VA對架構(gòu)化混存維護(hù)的系統(tǒng)緩存,必須配置和禁用操作(不推薦)。

  • 架構(gòu)定時(shí)器

    • 必須在所有CPU上以定時(shí)器頻率設(shè)置CNTFRQ,并且必須以一致的值設(shè)置CNTVOFF。如果在EL1處進(jìn)入內(nèi)核,則CNTHCTL_EL2必須在可用時(shí)設(shè)置EL1PCTEN(位0)。

  • 連貫性

    • 內(nèi)核啟動時(shí),所有要由內(nèi)核引導(dǎo)的CPU都必須屬于同一一致性域。需要初始化定義的實(shí)現(xiàn),才能在每個CPU上接收維護(hù)操作。

  • 系統(tǒng)寄存器

    • 所有將在其中輸入內(nèi)核映像的異常級別的可寫體系結(jié)構(gòu)系統(tǒng)寄存器都必須由更高級別的異常級別的軟件初始化,以防止在UNKNOWN狀態(tài)下執(zhí)行。

    • 對CPU模式,高速緩存,MMU,架構(gòu)計(jì)時(shí)器,一致性和系統(tǒng)寄存器的要求適用于所有CPU。所有CPU必須以相同的異常級別進(jìn)入內(nèi)核。

  • 主CPU必須直接跳轉(zhuǎn)到內(nèi)核映像的第一條指令。此CPU傳遞的設(shè)備樹Blob必須為每個cpu節(jié)點(diǎn)包含一個“啟用方法”屬性。支持的啟用方法如下所述。引導(dǎo)加載程序?qū)⑸蛇@些設(shè)備樹屬性,并將其插入內(nèi)核入口之前的blob中。

  • 具有“旋轉(zhuǎn)表”啟用方法的CPU在其cpu節(jié)點(diǎn)中必須具有“ cpu-release-addr”屬性。此屬性標(biāo)識自然對齊的64位零初始化內(nèi)存位置。

  • 具有“ psci”啟用方法的CPU應(yīng)該保留在內(nèi)核之外(即,在內(nèi)存節(jié)點(diǎn)中描述給內(nèi)核的內(nèi)存區(qū)域之外,或者在內(nèi)核中通過/ memreserve /描述給內(nèi)核描述的內(nèi)存保留區(qū)域之外)。設(shè)備樹)。內(nèi)核將按照ARM文檔編號ARM DEN 0022A(“ ARM處理器上的電源狀態(tài)協(xié)調(diào)接口系統(tǒng)軟件”)中的說明發(fā)出CPU_ON調(diào)用,以將CPU帶入內(nèi)核。設(shè)備樹應(yīng)包含一個“ psci”節(jié)點(diǎn),參考/bindings/arm/psci.txt.

  • 第二CPU通用寄存器設(shè)置的x0/x1/x2/x3都為0,保留。

內(nèi)核啟動init總過程

內(nèi)核啟動有兩種方式,壓縮格式或不壓縮格式,壓縮模式所不同的就是其入口位于arch/ /boot/compressed/head.S,為與該路徑下的代碼主要負(fù)責(zé)執(zhí)行執(zhí)行前期的初始化為解壓內(nèi)核做準(zhǔn)備。當(dāng)完成解壓內(nèi)核后,就跳轉(zhuǎn)到./arm/kernel/head.S開始啟動內(nèi)核。

本文僅分析不壓縮方式啟動內(nèi)核,通過分析內(nèi)核代碼,整理出內(nèi)核啟動過程的部分順序如下:


內(nèi)核的啟動與U-Boot一樣,前面一段是匯編代碼,然后跳轉(zhuǎn)到C代碼。匯編的入口在

./arm/kernel/head.S中,符號名為__HEAD,該文件包含了head-common.S。

所以從啟動用戶首進(jìn)程init而言,我將其分成大致分為四大步:

  • head.S ,初始化通用部分環(huán)境,與芯片無關(guān)

  • start_kernel, head.S完成后,調(diào)準(zhǔn)到start_kernel,進(jìn)入C函數(shù)執(zhí)行,該函數(shù)為于./init/main.c中

  • rest_init,創(chuàng)建init進(jìn)程,以及kthredd進(jìn)程,其中Init進(jìn)程號為1,kthredd為內(nèi)核進(jìn)程。

  • 啟動調(diào)度器,執(zhí)行kernel_init,該函數(shù)將調(diào)用根文件系統(tǒng)中的init執(zhí)行文件,至此用戶空間的init進(jìn)程就啟動起來了。

head.S/head-common.S作用

剖析匯編代碼比較枯燥,這里就不進(jìn)行描述了。僅就其作用進(jìn)行總結(jié):

  • 檢查架構(gòu),處理器和機(jī)器類型。

  • 配置MMU,創(chuàng)建頁表?xiàng)l目并啟用虛擬內(nèi)存。

  • 在init / main.c中調(diào)用start_kernel函數(shù)。

  • 所有架構(gòu)的代碼相同。這也是為什么采用匯編代碼的原因,規(guī)避針對不同芯片管理大量重復(fù)代碼。

start_kernel階段

該函數(shù)主要完成以下以下工作:

  • lockdep 死鎖檢測模塊初始化,

  • RCU機(jī)制初始化:RCU(Read-Copy Update),顧名思義就是讀-拷貝修改,它是基于其原理命名的。對于被RCU保護(hù)的共享數(shù)據(jù)結(jié)構(gòu),讀者不需要獲得任何鎖就可以訪問它,但寫者在訪問它時(shí)首先拷貝一個副本,然后對副本進(jìn)行修改,最后使用一個回調(diào)(callback)機(jī)制在適當(dāng)?shù)臅r(shí)機(jī)把指向原來數(shù)據(jù)的指針重新指向新的被修改的數(shù)據(jù)。這個時(shí)機(jī)就是所有引用該數(shù)據(jù)的CPU都退出對共享數(shù)據(jù)的操作。

  • SMP初始化,對稱多處理"(Symmetrical Multi-Processing)簡稱SMP,完成CPU ID的創(chuàng)建。

  • debug_objects_early_init,負(fù)責(zé)調(diào)試對象初始化,以便于內(nèi)核調(diào)試

  • lockdep死鎖檢測模塊初始化,lockdep的工作方式是在內(nèi)核中的鎖定調(diào)用包起來。每次采用或釋放特定類型的鎖時(shí),都會記錄該事實(shí)以及輔助詳細(xì)信息,例如處理器當(dāng)時(shí)是否正在處理中斷。Lockdep還記錄了使用新鎖時(shí)還持有哪些其他鎖;這是lockdep能夠執(zhí)行的許多檢查的關(guān)鍵。

  • 調(diào)用setup_arch(&command_line),該函數(shù)位于arch/

    /kernel/setup.c,用于解析從bootloader傳入的引導(dǎo)命令行。
  • 初始化控制臺,以打印啟動日志。

  • 初始化其他各子系統(tǒng),如VFS,trace,內(nèi)存管理子系統(tǒng),F(xiàn)ORK子系統(tǒng),cgroup,acpi,proc文件系統(tǒng),內(nèi)核服務(wù),緩存等等。

  • ……

  • 調(diào)用rest_init,以創(chuàng)建init進(jìn)程以及內(nèi)核進(jìn)程,并啟動內(nèi)核調(diào)度器。

rest_init階段

代碼如下,其注釋如下,主要作用就是先創(chuàng)建init進(jìn)程使其進(jìn)程號為1,這是第一個用戶空間進(jìn)程,該進(jìn)程執(zhí)行后在衍生出一系列的應(yīng)用進(jìn)程。具體取決于啟動腳本或者Init的具體實(shí)現(xiàn)。然后創(chuàng)建內(nèi)核進(jìn)程kthreadd,該進(jìn)程用于管理內(nèi)核進(jìn)程。該進(jìn)程進(jìn)程號為2。所有內(nèi)核進(jìn)程都是kthreadd的后代, kthreadd枚舉其他內(nèi)核線程;它提供了接口例程,內(nèi)核服務(wù)可以在運(yùn)行時(shí)動態(tài)生成其他內(nèi)核進(jìn)程。通過kthread_create_list維護(hù)其他內(nèi)核進(jìn)程??梢允褂胮s -ef命令從命令行查看內(nèi)核線程-它們顯示在[方括號]中:

static noinline void __init_refok rest_init(void)
{
    int pid;

    rcu_scheduler_starting();
    smpboot_thread_init();

    /*創(chuàng)建init進(jìn)程,第一個用戶空間進(jìn)程我們
    *需要首先生成init,以便它獲得pid 1,但是
    *init任務(wù)最終將要創(chuàng)建kthread,如果在創(chuàng)建
    *kthreadd之前對其進(jìn)行調(diào)度,則OOPS。*/

    kernel_thread(kernel_init, NULL, CLONE_FS);
    numa_default_policy();

    /*創(chuàng)建kthreadd用于管理內(nèi)核線程*/
    pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

    /*RCU 鎖*/
    rcu_read_lock();
    kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
    rcu_read_unlock();
    /*讓內(nèi)核進(jìn)程kthreadd處于就緒態(tài)TASK_NORMAL*/
    complete(&kthreadd_done);

    /* 啟動調(diào)度器      */
    init_idle_bootup_task(current);
    schedule_preempt_disabled();
    /* 禁用搶占的情況下調(diào)用cpu_idle */
    cpu_startup_entry(CPUHP_ONLINE);
}

kernel_init階段

當(dāng)內(nèi)核調(diào)度器運(yùn)行后,就會執(zhí)行kernel_init函數(shù):

static int __ref kernel_init(void *unused)
{
    int ret;

    kernel_init_freeable();
    /* 同步完成所有初始化操作 */
    async_synchronize_full();
#ifndef CONFIG_INITCALLS_THREAD
    free_initmem();
#endif
    mark_readonly();
    system_state = SYSTEM_RUNNING;
    numa_default_policy();

    flush_delayed_fput();

    /*如果使能了ramdisk執(zhí)行命令啟動init*/
    if (ramdisk_execute_command) {
        ret = run_init_process(ramdisk_execute_command);
        if (!ret)
            return 0;
        pr_err("Failed to execute %s (error %d)\n",
               ramdisk_execute_command, ret);
    }

    /* 如果execute_command使能,則按命令啟動init*/
    if (execute_command) {
        ret = run_init_process(execute_command);
        if (!ret)
            return 0;
        panic("Requested init %s failed (error %d).",
              execute_command, ret);
    }

    /*如果前面兩項(xiàng)都沒有使能,則依次在根文件系統(tǒng)下尋找并啟動Init*/
    if (!try_to_run_init_process("/sbin/init") ||
        !try_to_run_init_process("/etc/init") ||
        !try_to_run_init_process("/bin/init") ||
        !try_to_run_init_process("/bin/sh"))
        return 0;

    panic("No working init found.  Try passing init= option to kernel. "
          "See Linux Documentation/init.txt for guidance.");
}

從而init用戶進(jìn)程就啟動起來了,至于最終執(zhí)行的是哪一個Init可執(zhí)行文件,取決于系統(tǒng)移植的配置,如前文描述,常見的有busybox init,systemV init,systemD init等等。

niprogram-servicetype="">點(diǎn)擊留言/查看留言

END

果喜歡右下點(diǎn)個在看,也會讓我倍感鼓舞

往期精彩推薦




▲深度解析U-Boot網(wǎng)絡(luò)實(shí)現(xiàn)(長篇好文)
讀U-Boot源碼-C語言編程大法總結(jié)篇一
讀U-Boot源碼-C語言編程技巧總結(jié)篇二
基于Buildroot的Linux系統(tǒng)構(gòu)建之根文件系統(tǒng)
手把手教系列之移動平均濾波器C實(shí)現(xiàn)
手把手教系列之IIR數(shù)字濾波器設(shè)計(jì)實(shí)現(xiàn)

關(guān)注置頂:掃描左下二維碼關(guān)注公眾號加星

討論加群:掃描右下二維碼添加,發(fā)送“加群”

關(guān)注

加群

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點(diǎn),不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉