0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

在rt-smart操作系統(tǒng)中elf加載運(yùn)行要經(jīng)過哪些步驟

RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 來(lái)源:RTThread物聯(lián)網(wǎng)操作系統(tǒng) ? 作者:我夏了夏天 ? 2022-11-02 09:57 ? 次閱讀

在用戶態(tài)應(yīng)用程序處理的任務(wù)中,elf 加載運(yùn)行是一個(gè)比較重要的步驟,下面就分析一下在 rt-smart 操作系統(tǒng)中,想要將一個(gè)應(yīng)用程序運(yùn)行起來(lái)要經(jīng)過哪些步驟。

ELF 格式介紹

ELF 代表 Executable and Linkable Format。它是一種對(duì)可執(zhí)行文件、目標(biāo)文件和庫(kù)使用的文件格式。它在 Linux 下成為標(biāo)準(zhǔn)格式已經(jīng)很長(zhǎng)時(shí)間,ELF 一個(gè)特別的優(yōu)點(diǎn)在于,同一文件格式可以用于內(nèi)核支持的幾乎所有體系結(jié)構(gòu)上。

RT-SMART 同樣也使用 ELF 作為可執(zhí)行文件的格式,下面簡(jiǎn)單介紹一下 ELF 文件格式。

ELF 文件布局和結(jié)構(gòu)

下圖為 ELF 文件的基本布局:

2d7fecde-59e4-11ed-a3b6-dac502259ad0.png

上圖展示了 elf 文件的重要組成部分:

elf 文件頭,除了用于標(biāo)識(shí)ELF文件的幾個(gè)字節(jié)之外,ELF頭還包含了有關(guān)文件類型和大小的有關(guān)信息,

及文件加載后程序執(zhí)行的入口點(diǎn)信息。

程序頭表(program header table)向系統(tǒng)提供了可執(zhí)行文件的數(shù)據(jù)在進(jìn)程虛擬地址空間中組織

方式的相關(guān)信息。它還表示了文件可能包含的段數(shù)目、段的位置和用途。

各個(gè)段保存了與文件相關(guān)的各種形式的數(shù)據(jù)。例如,符號(hào)表、實(shí)際的二進(jìn)制碼、固定值(如字

符串)或程序使用的數(shù)值常數(shù)。

節(jié)頭表(section header table)包含了與各段相關(guān)的附加信息。

使用 readelf 工具可以讀取該類型文件中的各種數(shù)據(jù)結(jié)構(gòu)。

關(guān)鍵數(shù)據(jù)結(jié)構(gòu)

想要理解應(yīng)用程序的加載運(yùn)行過程,就必須要先了解 ELF 文件中的關(guān)鍵數(shù)據(jù)結(jié)構(gòu),知道可以通過 ELF 文件獲取那些程序加載所必須的關(guān)鍵信息,例如文件類型、目標(biāo)體系架構(gòu)、版本號(hào)、程序入口點(diǎn)以及程序運(yùn)行所需要的數(shù)據(jù)段存儲(chǔ)在什么位置等等信息。這些信息都存放在 ELF 的相關(guān)數(shù)據(jù)結(jié)構(gòu)中,那么現(xiàn)在就先了解一下 ELF 文件的相關(guān)數(shù)據(jù)結(jié)構(gòu)吧。

下面是在 ELF 加載過程上下文數(shù)據(jù)結(jié)構(gòu),這個(gè)結(jié)構(gòu)中包括了 eheader、pheader 和 sheader 三個(gè) elf 的關(guān)鍵數(shù)據(jù)結(jié)構(gòu)。

elf 頭表

 1typedefstruct
 2{
 3unsignedchare_ident[EI_NIDENT];/*前四個(gè)字節(jié)為0x7fELF,其他的字節(jié)位置都有特定的語(yǔ)義*/
 4Elf64_Halfe_type;/*用于區(qū)分ELF的文件類型,例如可重定位、可執(zhí)行、動(dòng)態(tài)庫(kù)、coredump文件*/
 5Elf64_Halfe_machine;/*指定了文件所需的體系結(jié)構(gòu)*/
 6Elf64_Worde_version;/*保存了版本信息,用于區(qū)分不同的ELF變體,目前該規(guī)范只定義了版本1*/
 7Elf64_Addre_entry;/*程序入口點(diǎn)*/
 8Elf64_Offe_phoff;/*程序頭表在二進(jìn)制文件中的偏移量*/
 9Elf64_Offe_shoff;/*節(jié)頭表所在的偏移量*/
10Elf64_Worde_flags;/*特定于處理器的標(biāo)志*/
11Elf64_Halfe_ehsize;/*指定了ELF頭的長(zhǎng)度,單位為字節(jié)*/
12Elf64_Halfe_phentsize;/*指定了程序頭表中一項(xiàng)的長(zhǎng)度,單位為字節(jié)(所有項(xiàng)的長(zhǎng)度都相同)*/
13Elf64_Halfe_phnum;/*指定了程序頭表中項(xiàng)的數(shù)目*/
14Elf64_Halfe_shentsize;/*指定節(jié)頭表中一項(xiàng)的長(zhǎng)度,單位為字節(jié)(所有項(xiàng)的長(zhǎng)度都相同)*/
15Elf64_Halfe_shnum;/*指定節(jié)頭表中項(xiàng)的數(shù)目*/
16Elf64_Halfe_shstrndx;/*包含各節(jié)名稱的字符串表在節(jié)頭表中的索引位置*/
17}Elf64_Ehdr;

程序頭表

 1typedefstruct
 2{
 3Elf64_Wordp_type;/*當(dāng)前項(xiàng)描述的段的種類,例如可裝載段、動(dòng)態(tài)鏈接、程序解釋等段類型*/
 4Elf64_Wordp_flags;/*保存了標(biāo)志信息,定義了該段的訪問權(quán)限,RWX*/
 5Elf64_Offp_offset;/*給出了所描述段在文件中的偏移量(從二進(jìn)制文件起始處開始計(jì)算,單位為字節(jié))*/
 6Elf64_Addrp_vaddr;/*給出了段的數(shù)據(jù)映射到虛擬地址空間中的位置(對(duì)于可裝載段類型)*/
 7Elf64_Addrp_paddr;/*只支持物理尋址,不支持虛擬尋址的系統(tǒng),將使用p_paddr保存信息*/
 8Elf64_Xwordp_filesz;/*指定了段在二進(jìn)制文件中的長(zhǎng)度*/
 9Elf64_Xwordp_memsz;/*制定了段在虛擬地址空間中的長(zhǎng)度(單位為字節(jié)),與文件中物理的長(zhǎng)度差值可通過階段數(shù)據(jù)或者填充0字節(jié)來(lái)補(bǔ)償*/
10Elf64_Xwordp_align;/*指定了段在內(nèi)存和二進(jìn)制文件中對(duì)其的方式(p_vaddr和p_offset地址必須是模p_align的,也就是p_align的倍數(shù)),例如p_align的值為0x1000=4096,這意味著段必須對(duì)其到4KB頁(yè)*/
11}Elf64_Phdr;

節(jié)頭表

 1typedefstruct
 2{
 3Elf64_Wordsh_name;/*指定了節(jié)的名稱,其值不是字符串本身,而是字符串表的一個(gè)索引*/
 4Elf64_Wordsh_type;/*指定了節(jié)的類型,例如不可用、保存程序相關(guān)信息、符號(hào)表、包含字符串表的節(jié)、重定位信息、散列表、動(dòng)態(tài)鏈接信息等類型*/
 5Elf64_Xwordsh_flags;/*節(jié)是否可寫(SHF_WRITE),是否將為其分配虛擬內(nèi)存(SHF_ALLOC),節(jié)是否包含可執(zhí)行的機(jī)器代碼(SHF_EXECINSTR)*/
 6Elf64_Addrsh_addr;/*指定節(jié)映射到虛擬地址空間中的位置*/
 7Elf64_Offsh_offset;/*指定了節(jié)在文件中的開始位置*/
 8Elf64_Xwordsh_size;/*指定了節(jié)的長(zhǎng)度,單位為字節(jié)*/
 9Elf64_Wordsh_link;/*引用另一個(gè)節(jié)頭表項(xiàng),可能根據(jù)節(jié)類型而進(jìn)行不同的解釋*/
10Elf64_Wordsh_info;/*與上一項(xiàng)聯(lián)用*/
11Elf64_Xwordsh_addralign;/*指定了節(jié)數(shù)據(jù)在內(nèi)存中對(duì)齊的方式*/
12Elf64_Xwordsh_entsize;/*指定了節(jié)中各數(shù)據(jù)項(xiàng)的長(zhǎng)度,前提是這些數(shù)據(jù)項(xiàng)的長(zhǎng)度都相同,例如字符串表*/
13}Elf64_Shdr;

在 rt-smart 實(shí)際編碼實(shí)現(xiàn)的過程中,為了方便數(shù)據(jù)傳遞,設(shè)計(jì)了一個(gè)包含上述三種數(shù)據(jù)類型的結(jié)構(gòu),利用該數(shù)據(jù)結(jié)構(gòu)可以使加載過程實(shí)現(xiàn)更加簡(jiǎn)潔易懂,如下所示:

 1structelf_load_context
 2{
 3intfd;/*應(yīng)用程序文件fd*/
 4intlen;/*用于臨時(shí)使用的len*/
 5uint8_t*load_addr;/*用于臨時(shí)使用的加載地址*/
 6structrt_lwp*lwp;/*進(jìn)程句柄*/
 7structprocess_aux*aux;/*進(jìn)程輔助信息句柄*/
 8rt_mmu_info*m_info;/*進(jìn)程mmu信息*/
 9Elf_Ehdreheader;/*elf頭表*/
10Elf_Phdrpheader;/*程序頭表*/
11Elf_Shdrsheader;/*節(jié)頭表*/
12structmap_rangeuser_area[2];/*在用戶空間需要映射的地址空間,0用于代碼段,1用于數(shù)據(jù)段*/
13};

ELF 標(biāo)準(zhǔn)節(jié)

ELF 標(biāo)準(zhǔn)定義了若干固定名稱的節(jié)。這些用于執(zhí)行大多數(shù)目標(biāo)文件所需的標(biāo)準(zhǔn)任務(wù)。所有名稱都從點(diǎn)開始,以便與用戶定義節(jié)或非標(biāo)準(zhǔn)節(jié)相區(qū)分,最重要的標(biāo)準(zhǔn)節(jié)如下所示:

2d99de00-59e4-11ed-a3b6-dac502259ad0.png

有了以上基礎(chǔ)概念,就可以來(lái)探索真正的代碼實(shí)現(xiàn)了。

探索程序加載代碼實(shí)現(xiàn)

執(zhí)行一個(gè)新的應(yīng)用程序功能由 lwp_execve 函數(shù)來(lái)實(shí)現(xiàn),該函數(shù)會(huì)初始化好一個(gè)進(jìn)程所需要的運(yùn)行環(huán)境,然后在該環(huán)境中啟動(dòng)第一個(gè)線程,也就是 main 線程。

暫且先不關(guān)注進(jìn)程 PID 申請(qǐng)以及的 mmu 表初始化等準(zhǔn)備工作,將注意力集中在 lwp_load 函數(shù)上。該函數(shù)將執(zhí)行如下操作:

打開 elf 文件,返回文件 fd

調(diào)用 load_elf 函數(shù)開始執(zhí)行應(yīng)用程序加載

在 load_elf 函數(shù)中,將執(zhí)行如下操作:

檢查 elf 頭,判斷其魔數(shù)、架構(gòu)類型、版本號(hào)等是否符合要求

判斷是靜態(tài)加載還是動(dòng)態(tài)加載

檢查程序入口地址是否為有效的用戶態(tài)地址

遍歷讀取程序頭表以及程序復(fù)制信息,將其加載到進(jìn)程的用戶空間里

遍歷讀取節(jié)頭表,根據(jù)節(jié)頭表中的信息,計(jì)算在用戶態(tài)需要需要分配多大的地址空間用于存放 text 段以及 data 段

根據(jù)上一步驟的計(jì)算,修改進(jìn)程的映射表,真正為數(shù)據(jù)段分配用戶態(tài)地址空間

遍歷節(jié)頭表,程序運(yùn)行所需要數(shù)據(jù)段加載到用戶地址空間中

通過上面的操作,ELF 文件中所有關(guān)于程序啟動(dòng)運(yùn)行所需的數(shù)據(jù)就都準(zhǔn)備好了,接下來(lái)就可以在此基礎(chǔ)上啟動(dòng)第一個(gè)線程,也就是 main 線程了。相關(guān)的代碼細(xì)節(jié)在這里就不做贅述了,源代碼中都添加了詳盡的注釋,可以自行查看。

總結(jié)

用戶態(tài)進(jìn)程代碼量較大,同時(shí)由于復(fù)雜度過高也不容易理解,現(xiàn)在代碼經(jīng)過完善,復(fù)雜度降低以后,可讀性方面有了巨大提升。想要深入了解用戶態(tài)的相關(guān)實(shí)現(xiàn),還需要至少了解另外三個(gè)主題:

進(jìn)程切換過程中底層架構(gòu)級(jí)別的匯編代碼

進(jìn)程資源管理相關(guān)內(nèi)容,例如 pid、tid 的分配,用戶態(tài)內(nèi)存空間映射等

SMP 多核調(diào)度原理與實(shí)現(xiàn)






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • ELF文件
    +關(guān)注

    關(guān)注

    0

    文章

    14

    瀏覽量

    7136
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21651
  • RTThread
    +關(guān)注

    關(guān)注

    8

    文章

    132

    瀏覽量

    40876

原文標(biāo)題:RT-Smart ELF 應(yīng)用程序加載運(yùn)行過程分析

文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RT-Thread Smart 入門指南

    Cortex-A 系列芯片,MIPS 芯片,帶 MMU 的 RISC-V 芯片等。rt-smart RT-Thread 操作系統(tǒng)的基礎(chǔ)上啟用獨(dú)立、完整的進(jìn)程方式,同時(shí)以混合微內(nèi)核
    發(fā)表于 03-29 06:40

    RT-Smart的資料合集

    可知,RT-Smart 32 位內(nèi)核運(yùn)行在地址空間的高地址,而用戶程序代碼運(yùn)行在低地址。2、RT-Smart物理頁(yè)內(nèi)存管理詳解伙伴系統(tǒng)
    發(fā)表于 03-22 15:06

    [IMX6ULL]RT-Smart系統(tǒng)下的軟件移植筆記推薦

    ,面向帶 MMU,中高端應(yīng)用的芯片,例如 ARM Cortex-A 系列芯片,MIPS 芯片,帶 MMU 的 RISC-V 芯片等。rt-smart RT-Thread 操作系統(tǒng)
    發(fā)表于 03-25 16:25

    快速上手RT-Thread Smart入門指南

    ,帶 MMU 的 RISC-V 芯片等。rt-smart RT-Thread 操作系統(tǒng)的基礎(chǔ)上啟用獨(dú)立、完整的進(jìn)程方式,同時(shí)以混合微內(nèi)核模式執(zhí)行。
    發(fā)表于 04-01 17:38

    分析一下rt-smart操作系統(tǒng)中將一個(gè)應(yīng)用程序運(yùn)行起來(lái)經(jīng)過哪些步驟

    1、RT-Smart ELF 應(yīng)用程序加載運(yùn)行在用戶態(tài)應(yīng)用程序處理的任務(wù)elf 加載運(yùn)行是一
    發(fā)表于 04-13 17:17

    rt-smart操作系統(tǒng)中將ELF應(yīng)用程序運(yùn)行起來(lái)經(jīng)過哪些步驟

    1、RT-Smart ELF應(yīng)用程序加載運(yùn)行在用戶態(tài)應(yīng)用程序處理的任務(wù),elf 加載運(yùn)行是一個(gè)
    發(fā)表于 06-13 18:18

    D1哪吒開發(fā)板rt-smart內(nèi)核固件的燒寫與運(yùn)行步驟

    NandFlash 加載運(yùn)行,需要借助bootloader,如 U-Boot借助全志的 tina Linux,把 Linux 內(nèi)核文件替換為 rt-smart內(nèi)核文件,運(yùn)行 rt-smart
    發(fā)表于 06-17 11:06

    基于RT-Thread操作系統(tǒng)衍生rt-smart實(shí)時(shí)操作系統(tǒng)簡(jiǎn)介

    執(zhí)行。rt-smart 是一款高性能混合微內(nèi)核操作系統(tǒng)傳統(tǒng)嵌入式操作系統(tǒng)劃分,rt-smart
    發(fā)表于 06-22 17:56

    開機(jī)體驗(yàn)rt-smart:webserver網(wǎng)關(guān)

    ,ART-Pi Smart 開發(fā)板會(huì)通過 u-boot 自動(dòng)加載 emmc rt-smart 內(nèi)核固件文件(/kernel/rtthread.bin)到內(nèi)存去
    發(fā)表于 06-30 11:17

    rt-smart和master分支有哪些不同呢

    還是共用一套代碼。2.rt-smart是針對(duì)帶有mmu的操作系統(tǒng),采用微內(nèi)核的設(shè)計(jì)思想,目前發(fā)現(xiàn)源碼里面大量的層次結(jié)構(gòu)還是沿用之前的master分支,哪里采用了微內(nèi)核呢?3.帶有mmu的ARM A系列
    發(fā)表于 10-14 10:52

    睿賽德科技微內(nèi)核操作系統(tǒng)rt-smart已支持Arm Mali GPU

    睿賽德科技今日宣布,其微內(nèi)核操作系統(tǒng) RT-Thread Smart(簡(jiǎn)稱:rt-smart)已支持Arm Mali GPU,為實(shí)時(shí)操作系統(tǒng)
    的頭像 發(fā)表于 09-29 10:42 ?2079次閱讀

    RT-Smart ELF應(yīng)用程序加載運(yùn)行過程分析

    在用戶態(tài)應(yīng)用程序處理的任務(wù),elf 加載運(yùn)行是一個(gè)比較重要的步驟,下面就分析一下 rt-smart
    的頭像 發(fā)表于 11-02 09:57 ?967次閱讀

    優(yōu)雅的D1S上運(yùn)行RT-Smart

    合并到 RT-Smart 主倉(cāng)庫(kù),于是我來(lái)展示一下 D1S 運(yùn)行 RT-Smart步驟,供大家參考~ 做嵌入式開發(fā)的人對(duì) RT-Thre
    的頭像 發(fā)表于 11-16 20:15 ?2893次閱讀

    絲滑的RT-Smart用戶態(tài)運(yùn)行LVGL

    /rt-thread.git 更詳細(xì)環(huán)境配置請(qǐng)移步到— RT-Thread-優(yōu)雅のD1S上運(yùn)行RT-Smart 「Rb君」,公眾號(hào):RTT
    的頭像 發(fā)表于 11-22 20:20 ?1271次閱讀

    零基礎(chǔ)上手rt-smart適配bsp

    RT-Thread Smart(簡(jiǎn)稱rt-smart)是基于RT-Thread操作系統(tǒng)衍生,面向帶MMU(Memory Management
    的頭像 發(fā)表于 08-08 10:34 ?1111次閱讀
    零基礎(chǔ)上手<b class='flag-5'>rt-smart</b>適配bsp