国产精品久久久久影院,成人午夜福利视频,国产精品久久久久高潮,国产精品 欧美 亚洲 制服,国产精品白浆无码流出

【IMX6ULL學(xué)習(xí)筆記】八、Linux啟動(dòng)流程

發(fā)布者:WiseThinker最新更新時(shí)間:2025-03-03 來(lái)源: elecfans關(guān)鍵字:Linux  啟動(dòng)流程 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

一、鏈接腳本 vmlinux.lds

Linux 內(nèi)核的鏈接腳本文件 arch/arm/kernel/vmlinux.lds 中有如下代碼

image

ENTRY 指明了了 Linux 內(nèi)核入口,入口為 stext,stext 定義在文件 arch/arm/kernel/head.S 中。


二、Linux 內(nèi)核啟動(dòng)流程分析

1、Linux 內(nèi)核入口 stext

stext 是 Linux 內(nèi)核的入口地址,在文件 arch/arm/kernel/head.S 中有如下所示提示內(nèi)容:


/*

* Kernel startup entry point.

* ---------------------------

*

* This is normally called from the decompressor code. The requirements

* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,

* r1 = machine nr, r2 = atags or dtb pointer.

.....

Linux 內(nèi)核啟動(dòng)之前要求如下:

①、關(guān)閉 MMU。

②、關(guān)閉 D-cache。

③、I-Cache 無(wú)所謂。

④、r0=0。

⑤、r1=machine nr(也就是機(jī)器 ID)。

⑥、r2=atags 或者設(shè)備樹(shù)(dtb)首地址。


Linux 內(nèi)核的入口點(diǎn) stext 其實(shí)相當(dāng)于內(nèi)核的入口函數(shù),stext 函數(shù)內(nèi)容如下:


80 ENTRY(stext)

......

91     @ ensure svc mode and all interrupts masked

92     safe_svcmode_maskall r9

93

94     mrc p15, 0, r9, c0, c0 @ get processor id

95     bl __lookup_processor_type @ r5=procinfo r9=cpuid

96     movs r10, r5 @ invalid processor (r5=0)?

97     THUMB( it eq ) @ force fixup-able long branch encoding

98         beq __error_p @ yes, error 'p'

99

......

107

108 #ifndef CONFIG_XIP_KERNEL

......

113 #else

114     ldr r8, =PLAT_PHYS_OFFSET @ always constant in this case

115 #endif

116

117     /*

118     * r1 = machine no, r2 = atags or dtb,

119     * r8 = phys_offset, r9 = cpuid, r10 = procinfo

120     */

121     bl __vet_atags

......

128     bl __create_page_tables

129

130     /*

131     * The following calls CPU specific code in a position independent

132     * manner. See arch/arm/mm/proc-*.S for details. r10 = base of

133     * xxx_proc_info structure selected by __lookup_processor_type

134     * above. On return, the CPU will be ready for the MMU to be

135     * turned on, and r0 will hold the CPU control register value.

136     */

137     ldr r13, =__mmap_switched   @ address to jump to after

138                                 @ mmu has been enabled

139     adr lr, BSYM(1f) @ return (PIC) address

140     mov r8, r4 @ set TTBR1 to swapper_pg_dir

141     ldr r12, [r10, #PROCINFO_INITFUNC]

142     add r12, r12, r10

143     ret r12

144 1:  b __enable_mmu

145 ENDPROC(stext)

第 92 行:調(diào)用函數(shù) safe_svcmode_maskall 確保 CPU 處于 SVC 模式,并關(guān)閉所有中斷,定義arch/arm/include/asm/assembler.h 中。


第 94 行:讀處理器 ID,ID 值保存在 r9 寄存器中。


第 95 行:調(diào)用函數(shù)__lookup_processor_type 檢查當(dāng)前系統(tǒng)是否支持此 CPU,如果支持就獲取 procinfo 信息。 procinfo 是 proc_info_list 類型的結(jié)構(gòu)體,在 arch/arm/include/asm/procinfo.h 中的定義如下:


struct proc_info_list {

    unsigned int

    cpu_val;

    unsigned int cpu_mask;

    unsigned long __cpu_mm_mmu_flags; /* used by head.S */

    unsigned long __cpu_io_mmu_flags; /* used by head.S */

    unsigned long __cpu_flush; /* used by head.S */

    const char

    *arch_name;

    const char

    *elf_name;

    unsigned int elf_hwcap;

    const char

    *cpu_name;

    struct processor *proc;

    struct cpu_tlb_fns *tlb;

    struct cpu_user_fns *user;

    struct cpu_cache_fns *cache;

};

Linux 內(nèi)核將每種處理器都抽象為一個(gè) proc_info_list 結(jié)構(gòu)體,每種處理器都對(duì)應(yīng)一個(gè)procinfo。因此可以通過(guò)處理器 ID 來(lái)找到對(duì)應(yīng)的 procinfo 結(jié)構(gòu),__lookup_processor_type 函數(shù)找到對(duì)應(yīng)處理器的 procinfo 以后會(huì)將其保存到 r5 寄存器中。


第 121 行:調(diào)用函數(shù)__vet_atags 驗(yàn)證 atags 或設(shè)備樹(shù)(dtb)的合法性。函數(shù)__vet_atags 定義在文件 arch/arm/kernel/head-common.S 中。


第 128 行:調(diào)用函數(shù)__create_page_tables 創(chuàng)建頁(yè)表。


第 137 行:將函數(shù)__mmap_switched 的地址保存到 r13 寄存器中。定義在文件 arch/arm/kernel/head-common.S中,函數(shù)__mmap_switched 最終會(huì)調(diào)用 start_kernel 函數(shù)。


第 144 行:調(diào)用__enable_mmu函數(shù)使能 MMU ,__enable_mmu 定義在文件 arch/arm/kernel/head.S 中。__enable_mmu 會(huì)通過(guò)調(diào)用__turn_mmu_on來(lái)打開(kāi) MMU,__turn_mmu_on 最后會(huì)執(zhí)行 r13 里面保存的__mmap_switched 函數(shù)。


2、__mmap_switched 函數(shù)

__mmap_switched 函數(shù)定義在文件 arch/arm/kernel/head-common.S 中,最終調(diào)用 start_kernel 來(lái)啟動(dòng) Linux 內(nèi)核。


3、start_kernel 函數(shù)

start_kernel 函數(shù)定義在文件 init/main.c 中。start_kernel 里面調(diào)用了大量的函數(shù)來(lái)啟動(dòng) Linux 內(nèi)核,最后調(diào)用了 rest_init。


4、rest_init 函數(shù)

rest_init 函數(shù)定義在文件 init/main.c 中,函數(shù)內(nèi)容如下:


383 static noinline void __init_refok rest_init(void)

384 {

385     int pid;

386

387     rcu_scheduler_starting();

388     smpboot_thread_init();

389     /*

390     * We need to spawn init first so that it obtains pid 1, however

391     * the init task will end up wanting to create kthreads, which,

392     * if we schedule it before we create kthreadd, will OOPS.

393     */

394     kernel_thread(kernel_init, NULL, CLONE_FS);

395     numa_default_policy();

396     pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

397     rcu_read_lock();

398     kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);

399     rcu_read_unlock();

400     complete(&kthreadd_done);

401

402     /*

403     * The boot idle thread must execute schedule()

404     * at least once to get things moving:

405     */

406     init_idle_bootup_task(current);

407     schedule_preempt_disabled();

408     /* Call into cpu_idle with preempt disabled */

409     cpu_startup_entry(CPUHP_ONLINE);

410 }

第 387 行:調(diào)用函數(shù) rcu_scheduler_starting,啟動(dòng) RCU 鎖調(diào)度器


第 394 行:調(diào)用函數(shù) kernel_thread 創(chuàng)建 kernel_init 進(jìn)程,也就是 init 內(nèi)核進(jìn)程。init 進(jìn)程的 PID 為 1。


第 396 行:調(diào)用函數(shù) kernel_thread 創(chuàng)建 kthreadd 內(nèi)核進(jìn)程,此內(nèi)核進(jìn)程的 PID 為 2。kthreadd 進(jìn)程負(fù)責(zé)所有內(nèi)核進(jìn)程的調(diào)度和管理。


第 409 行:最后調(diào)用函數(shù) cpu_startup_entry 來(lái)進(jìn)入 idle 進(jìn)程。


在 Linux 終端中輸入“ps -A”就可以打印出當(dāng)前系統(tǒng)中的所有進(jìn)程


5、init 進(jìn)程

kernel_init 函數(shù)就是 init 進(jìn)程具體做的工作,定義在文件 init/main.c 中,函數(shù)內(nèi)容如下:


928 static int __ref kernel_init(void *unused)

929 {

930   int ret;

931

932   kernel_init_freeable(); /* init 進(jìn)程的一些其他初始化工作 */

933   /* need to finish all async __init code before freeing the memory */

934   async_synchronize_full(); /* 等待所有的異步調(diào)用執(zhí)行完成 */

935   free_initmem(); /* 釋放 init 段內(nèi)存 */

936   mark_rodata_ro();

937   system_state = SYSTEM_RUNNING; /* 標(biāo)記系統(tǒng)正在運(yùn)行 */

938   numa_default_policy();

939

940   flush_delayed_fput();

941

942   if (ramdisk_execute_command) {

943     ret = run_init_process(ramdisk_execute_command);

944     if (!ret)

945       return 0;

946     pr_err('Failed to execute %s (error %d)n',

947     ramdisk_execute_command, ret);

948   }

949

950   /*

951   * We try each of these until one succeeds.

952   *

953   * The Bourne shell can be used instead of init if we are

954   * trying to recover a really broken machine.

955   */

956   if (execute_command) {

957     ret = run_init_process(execute_command);

958     if (!ret)

959     return 0;

960     panic('Requested init %s failed (error %d).',

961     execute_command, ret);

962   }

963   if (!try_to_run_init_process('/sbin/init') ||

964       !try_to_run_init_process('/etc/init') ||

965       !try_to_run_init_process('/bin/init') ||

966       !try_to_run_init_process('/bin/sh'))

967     return 0;

968

969   panic('No working init found. Try passing init= option to kernel. '

970         'See Linux Documentation/init.txt for guidance.');

971 }

第 932 行:kernel_init_freeable 用于完成 init 進(jìn)程的一些初始化工作。


第 940 行:ramdisk_execute_command 是一個(gè)全局的 char 指針變量,此變量值為“/init”,也就是根目錄下的 init 程序。ramdisk_execute_command 也可以通過(guò) uboot 傳遞,在 bootargs 中使用“rdinit=xxx”即可,xxx 為具體的 init 程序名字。


第 943 行:如果存在“/init”程序就通過(guò)函數(shù) run_init_process 運(yùn)行此程序。


第 956 行:如果 ramdisk_execute_command 為空就看 execute_command 是否為空,不管如何一定要在根文件系統(tǒng)中找到一個(gè) init 程序。execute_command 的值是通過(guò) uboot 傳遞,在 bootargs 中用“init=xxxx”就可以了,比如 “init=/linuxrc” 表示根文件系統(tǒng)中的 linuxrc 為要執(zhí)行的用戶空間init程序。


第 963~966 行:如果 ramdisk_execute_command 和 execute_command 都為空,那么就依次查找“/sbin/init”、“/etc/init”、“/bin/init”和“/bin/sh”,這四個(gè)相當(dāng)于備用 init 程序,如果這四個(gè)也不存在,那么 Linux 啟動(dòng)失??!


第 969 行:如果以上步驟都沒(méi)有找到用戶空間的 init 程序,那么就提示錯(cuò)誤發(fā)生!


kernel_init_freeable 定義在文件 init/main.c 中,縮減后內(nèi)容如下:


973 static noinline void __init kernel_init_freeable(void)

974 {

975     /*

976     * Wait until kthreadd is all set-up.

977     */

978     wait_for_completion(&kthreadd_done);/* 等待 kthreadd 進(jìn)程準(zhǔn)備就緒 */

......

998

999     smp_init(); /* SMP 初始化 */

1000     sched_init_smp(); /* 多核(SMP)調(diào)度初始化 */

1001

1002     do_basic_setup(); /* 設(shè)備初始化都在此函數(shù)中完成 */

1003

1004     /* Open the /dev/console on the rootfs, this should never fail */

1005     if (sys_open((const char __user *) '/dev/console', O_RDWR, 0) < 0)

1006         pr_err('Warning: unable to open an initial console.n');

1007

1008     (void) sys_dup(0);

1009     (void) sys_dup(0);

1010     /*

1011     * check if there is an early userspace init. If yes, let it do

1012     * all the work

1013     */

1014

1015     if (!ramdisk_execute_command)

1016         ramdisk_execute_command = '/init';

1017

1018     if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {

1019         ramdisk_execute_command = NULL;

1020         prepare_namespace();

1021     }

1022

1023     /*

1024     * Ok, we have completed the initial bootup, and

1025     * we're essentially up and running. Get rid of the

[1] [2]
關(guān)鍵字:Linux  啟動(dòng)流程 引用地址:【IMX6ULL學(xué)習(xí)筆記】八、Linux啟動(dòng)流程

上一篇:【IMX6ULL學(xué)習(xí)筆記】九、Linux內(nèi)核移植
下一篇:【IMX6ULL學(xué)習(xí)筆記】七、Linux 頂層Makefile

推薦閱讀最新更新時(shí)間:2025-07-02 12:07

【ARM】S3C6410芯片的啟動(dòng)流程
S3C6410芯片的啟動(dòng)流程 (1) 上電后首先運(yùn)行iRom(BL0)內(nèi)的代碼,主要完成時(shí)鐘和看門狗等外圍器件的初始化。 (2) 拷貝SD卡或者NnadFlash中的前4k(BL1)代碼到片內(nèi)ram(墊腳石)去運(yùn)行,主要工作是配置主存儲(chǔ)器SDRAM。并將剩余的BL1和BL2加載到SDRAM上。 (3) 完成后將程序的入口跳轉(zhuǎn)到SDRAM中的BL2繼續(xù)運(yùn)行。并將存儲(chǔ)設(shè)備上的OS加載到SDRAM運(yùn)行。 (4) 將程序的入口跳轉(zhuǎn)到拷貝到SDRAM上的OS的入口進(jìn)行運(yùn)行。
[單片機(jī)]
【ARM】S3C6410芯片的<font color='red'>啟動(dòng)</font><font color='red'>流程</font>
深入解讀STM32啟動(dòng)詳細(xì)流程分析-上
問(wèn)題提出 大家不妨設(shè)想一下,cpu 的工作是什么,cpu 是沒(méi)有主觀意識(shí)的,它只會(huì)按照特定的指令執(zhí)行相應(yīng)的操作,用專業(yè)術(shù)語(yǔ)來(lái)說(shuō)就是:取指 - 譯碼 - 執(zhí)行,譯碼和執(zhí)行肯定是在 cpu 內(nèi)部進(jìn)行操作的,并且前提是已經(jīng)取到了指令。那現(xiàn)在問(wèn)題來(lái)了,指令在哪? cpu上電復(fù)位后執(zhí)行的第一步操作就是取指令 問(wèn)題1:指令存儲(chǔ)在何處 我們?cè)陔娔X上編寫(xiě)的程序最終是要燒寫(xiě)到芯片內(nèi)部的 FLASH中(此處特指STM32)。 問(wèn)題2:如何將可執(zhí)行文件燒寫(xiě)至 FLASH 上 STM32 的啟動(dòng)方式有很多種,從主存 FLASH 啟動(dòng),從 system memory 啟動(dòng),從 SRAM 中啟動(dòng)。 問(wèn)題3:從 SRAM 中啟動(dòng),為什么需要重新設(shè)置中斷向量
[單片機(jī)]
深入解讀STM32<font color='red'>啟動(dòng)</font>詳細(xì)<font color='red'>流程</font>分析-上
IMX6ULL學(xué)習(xí)筆記】十一、LED字符設(shè)備
一、地址映射 MMU 全稱叫做 Memory Manage Unit,也就是內(nèi)存管理單元。MMU 主要完成的功能如下: ①、完成虛擬空間到物理空間的映射。 ②、內(nèi)存保護(hù),設(shè)置存儲(chǔ)器的訪問(wèn)權(quán)限,設(shè)置虛擬存儲(chǔ)空間的緩沖特性。 Linux 內(nèi)核啟動(dòng)的時(shí)候會(huì)初始化 MMU,設(shè)置好內(nèi)存映射,設(shè)置好以后 CPU 訪問(wèn)的都是虛擬地址。就不能直接操作 內(nèi)存/寄存器 地址,因此必須得到寄存器物理地址在 Linux 系統(tǒng)里面對(duì)應(yīng)的虛擬地址。物理內(nèi)存和虛擬內(nèi)存之間的轉(zhuǎn)換,需要用到兩個(gè)函數(shù):ioremap 和 iounmap。 1、ioremap 函數(shù) ioremap 函數(shù)用于獲取指定物理地址空間對(duì)應(yīng)的虛擬地址空間,定義在 arch/arm/in
[單片機(jī)]
IMX6ULL學(xué)習(xí)筆記(7)——通過(guò)SD卡啟動(dòng)U-Boot
一、簡(jiǎn)介 在 Ubuntu 下可以更精細(xì)地操作 SD/TF 卡:可以把 sdcoard.img 整個(gè)燒寫(xiě)到卡上,也可以單獨(dú)燒寫(xiě) U-Boot 到卡上,甚至掛接卡上的文件系統(tǒng)后單獨(dú)更新里面的文件。 常用于做 U-Boot 測(cè)試。 1.1 dd命令 主用功能是用于拷貝文件,也就是用指定大小的塊去拷貝一個(gè)文件,并在拷貝的同時(shí)進(jìn)行指定的轉(zhuǎn)換(默認(rèn)從標(biāo)準(zhǔn)輸入拷貝到標(biāo)準(zhǔn)輸出,這意味dd可以在管道中使用)。這個(gè)拷貝過(guò)程簡(jiǎn)單理解就是讀取,轉(zhuǎn)換并輸出數(shù)據(jù)。 用法: dd 二、識(shí)別SD卡 首先 SD 卡插入讀卡器,再把讀卡器插入電腦。 VMWare 有時(shí)候會(huì)自動(dòng)彈出對(duì)話框,選擇 連接到虛擬機(jī) 即可。 如果沒(méi)有對(duì)話框,可以通過(guò)
[單片機(jī)]
Linux系統(tǒng)編程篇丨迅為IMX6ULL-對(duì)應(yīng)視頻講解
本章內(nèi)容對(duì)應(yīng)視頻講解鏈接(在線觀看): 什么是 Linux 系統(tǒng)編程呢?Linux 系統(tǒng)編程也叫 Linux 下的高級(jí)編程。是介于應(yīng)用層和驅(qū)動(dòng)層之間的。內(nèi)核向用戶提供的接口。本章講述編寫(xiě) Linux 系統(tǒng)應(yīng)用層軟件常用的一些技術(shù),包括文件 IO,標(biāo)準(zhǔn) IO,進(jìn)程線程操作。這些運(yùn)行在系統(tǒng)應(yīng)用層的程序直接與內(nèi)核和系統(tǒng)核心庫(kù)進(jìn)行交互,只能在 Linux 上運(yùn)行,不能跨 平臺(tái),也就是不能運(yùn)行在其他操作系統(tǒng)上(比如 windows)。Linux 根據(jù) UNIX 發(fā)展而來(lái),屬于類 UNIX 操作系統(tǒng),擁有 UNIX 特點(diǎn),但是 Linux 作為開(kāi)源軟件更專注實(shí)用功能,支持更多的系統(tǒng)調(diào)用,從而擁有更多的新特性。 學(xué)習(xí)系統(tǒng)編程可以使用 man
[單片機(jī)]
<font color='red'>Linux</font>系統(tǒng)編程篇丨迅為IMX6ULL-對(duì)應(yīng)視頻講解
Linux內(nèi)核啟動(dòng)參數(shù)
一、系統(tǒng)啟動(dòng)流程 bootloader(uboot)——linux Kernel(uImage)——Rootfs(Init)——Application 二、啟動(dòng)環(huán)境配置 uboot環(huán)境變量:printenv setenv saveenv tftpboot nand read/write baudrate 115200 bootdelay bootcmd bootargs... 內(nèi)核啟動(dòng)參數(shù):bootargs ' name = value ...' bootargs root=/dev/nfs nfsroot=10.66.10.10:home/binge/rootfs ip=10.66.10.12 init=/li
[單片機(jī)]
Linux 藍(lán)牙系列 -- ARM-Linux藍(lán)牙工具的移植
一 內(nèi)核修改 ------------------------------------------------------------ 將內(nèi)核的藍(lán)牙做成模塊形式。 并配置如下, Bluetooth subsystem support --- L2CAP protocol support SCO links support RFCOMM protocol support RFCOMM TTY support BNEP protocol support HIDP protocol support (NEW) Bluetooth d
[單片機(jī)]
linux之rootfs (UBIFS)
以下切換到root用戶進(jìn)行操作(在其他用戶模式下編譯出來(lái)的rootfs登錄時(shí)不是以root登錄,好像是比較麻煩,簡(jiǎn)單起見(jiàn)先) 修改Makefile: CROSS_COMPILE = /opt/arm-2010q1/bin/arm-none-linux-gnueabi- ARCH = arm 保存退出后: make menuconfig 1.18.1已經(jīng)把make install目錄默認(rèn)改成./_install了。而且也不打算改成靜態(tài)庫(kù),所以沒(méi)啥好改的,看一看保存退出后: make (生成busybox) make install (生成文件到_install目錄) 然后修改_install/bi
[單片機(jī)]
小廣播
設(shè)計(jì)資源 培訓(xùn) 開(kāi)發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號(hào)

 
EEWorld服務(wù)號(hào)

 
汽車開(kāi)發(fā)圈

 
機(jī)器人開(kāi)發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號(hào) 京ICP備10001474號(hào)-1 電信業(yè)務(wù)審批[2006]字第258號(hào)函 京公網(wǎng)安備 11010802033920號(hào) Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved