当前位置:首页>Linux>ARM64 Linux 启动:从上电到 shell,每一行代码都在干什么

ARM64 Linux 启动:从上电到 shell,每一行代码都在干什么

  • 2026-06-28 08:43:12
ARM64 Linux 启动:从上电到 shell,每一行代码都在干什么
多年前曾经调一块RK3568板子,内核启动卡在"Starting kernel..."就不动了,重编内核,折腾了两天一无所获,连个panic都没来得及打。从那以后我就觉得,ARM64启动这东西,光知道流程图是不够的。你得知道u-boot _start跳到board_init_f之前到底干了什么,内核head.S里的primary_entry和老版本的_text有啥区别,start_kernel里那一百多个初始化函数谁是瓶颈——不然出了问题只能瞎猜。
这篇文章把ARM64嵌入式Linux的启动过程从源码层面拆开:u-boot怎么从裸板跑起来,Linux 5.10内核的head.S做了哪些大改,start_kernel的完整调用链是什么,根文件系统怎么从头做出来。全程带代码,不讲废话。

一、ARM64嵌入式Linux启动全景

x86 PC启动是BIOS/UEFI干完活交给GRUB,GRUB加载内核,流程相对统一。ARM64完全不一样——没有统一固件标准,每个SoC厂商的ROM代码都不一样,bootloader得自己配。
典型的ARM64嵌入式启动分5个阶段:
ROM Code:芯片出厂烧死在硅片里的代码,上电最先执行,负责从Boot介质加载下一阶段
U-Boot SPL/TPL:U-Boot的精简版,RAM还没初始化时用,负责DDR训练和初始化
U-Boot:完整的U-Boot,负责硬件初始化、加载内核和设备树到内存
Linux Kernel:从汇编入口primary_entry开始,到挂载根文件系统、启动init进程
用户空间(根文件系统):init进程拉起各种服务,最终到login shell
重点讲第3和第4阶段,因为这两个阶段出了问题最难定位——U-Boot有命令行可以调试,用户空间有日志可以看,唯独内核启动早期,串口还没初始化、MMU刚配好、中断还没开,出了错就是个死机,连个提示都没有。

二、U-Boot启动流程:从_start到board_init_f

2.1 U-Boot在ARM64上的入口

U-Boot的入口在arch/arm/cpu/armv8/start.S,标签名就是_start。上电后CPU跳到这里,此时MMU是关的、Cache是关的、中断是关的——裸机环境,啥都没有。
入口代码(基于U-Boot 2023.10):
/* arch/arm/cpu/armv8/start.S */.globl _start_start:#if defined(CONFIG_LINUX_KERNEL_IMAGE_HEADER)    /*     * 有些平台需要Linux内核镜像头部,U-Boot把自己伪装成     * 内核格式,让ROM Code能正常加载     */    b   reset          /* 跳过头部,到实际入口 */    .long   0          /* 偏移量占位 */    .quad   0          /* image_header占位 */    /* ... 共64字节头部 ... */#endif    b   reset
这里有个坑:如果你用的是RK或NXP的SoC,它们的ROM Code可能要求U-Boot带内核镜像头部。不带的话ROM Code拒绝加载,板子直接变砖——串口啥都不会输出。配置U-Boot时确认CONFIG_LINUX_KERNEL_IMAGE_HEADER是否需要勾选

2.2 reset标签:真正的初始化起点

_start跳到reset,这里才是干正事的地方:
/* arch/arm/cpu/armv8/start.S */reset:    /* 关中断 */    msr daifset, #0xf    /* 根据当前异常级别做不同处理 */    mrs x0, CurrentEl    cmp x0, #0xC           /* EL3? */    b.eq 1f    cmp x0, #0x8           /* EL2? */    b.eq 2f    cmp x0, #0x4           /* EL1? */    b.eq 3f    b   reset_serror1:  /* EL3: 安全态,先切到EL2 */    mrs x0, scr_el3    orr x0, x0, #0x4       /* 设置EL2为非安全态 */    msr scr_el3, x0    msr sp_el2, x0    eret                    /* 返回到EL2 */2:  /* EL2: 设置异常向量表 */    adrp x0, vectors    add x0, x0, #:lo12:vectors    msr vbar_el2, x0    /* 关MMU和Cache */    mrs x0, sctlr_el2    bic x0, x0, #(1 << 0)     /* 关MMU */    bic x0, x0, #(1 << 2)     /* 关DCache */    bic x0, x0, #(1 << 12)    /* 关ICache */    msr sctlr_el2, x0    isb    /* 计数器频率设置(ARM64定时器) */    mrs x0, cntfrq_el0    cbz x0, 1f    ldr x1, =CONFIG_COUNTER_FREQUENCY    msr cntfrq_el0, x11:  /* 初始化栈 */    ldr x0, =CONFIG_SYS_INIT_SP_ADDR    mov sp, x0    /* 跳C语言入口 */    b   board_init_f
几个关键点:
异常级别判断:ARM64有EL0-EL3四个异常级别,U-Boot通常在EL2运行,但有些SoC的ROM Code把CPU带到EL3。reset里先判断当前级别,如果在EL3就切到EL2——因为U-Boot不需要安全态权限,而且后续内核期望在EL2或EL1启动
关MMU和Cache:上电后这些寄存器状态不确定,有的SoC ROM Code可能开了Cache,U-Boot必须先全关掉再自己重建
cntfrq_el0:ARM64通用定时器频率寄存器。如果ROM Code没设好,U-Boot得自己写,否则后续delay函数全乱套

2.3 board_init_f:C语言世界

跳到board_init_f后进入C代码,做两件事:早期硬件初始化,以及为U-Boot自身重定位做准备。
/* common/board_f.c */void board_init_f(ulong boot_flags){    gd->flags = boot_flags;    gd->have_console = 0;    /* 调用initcall链,逐个执行初始化函数 */    initcall_run_list(init_sequence_f);    /* 重定位U-Boot到RAM顶部 */    relocate_code(addr_sp, gd, relocaddr);}
init_sequence_f是一个函数指针数组,按顺序执行一系列初始化:串口、DRAM、计时器、环境变量……每个板子可以通过board_early_init_f等弱函数插入自己的初始化逻辑。
重定位(relocate)是U-Boot的一个设计亮点:U-Boot一开始从Flash直接XIP(eXecute In Place),运行速度很慢。等DRAM初始化好后,U-Boot把自己整个搬到RAM顶部运行,速度提升几十倍。

2.4 U-Boot常用命令速查

调板子时这些命令用得最多:
信息类

命令

干什么

示例

bdinfo

看板级信息:内存起止地址、波特率、bootargs

bdinfo

printenv

打印环境变量

printenv bootargs

version

U-Boot版本号

version

存储类

命令

干什么

示例

mmc info

SD/eMMC信息

mmc info

mmc read addr blk cnt

从eMMC读到内存

mmc read 0x40080000 0x1000 0x2000

sf probe

探测SPI Flash

sf probe 0

sf read addr off len

从SPI Flash读到内存

sf read 0x40080000 0x100000 0x800000

内存类

命令

干什么

示例

md addr len

看内存内容

md 0x40080000 100

mw addr val

写内存

mw 0x40080000 0x12345678

cp src dst len

内存拷贝

cp 0x40080000 0x50000000 0x1000

网络类

命令

干什么

示例

dhcp

DHCP获取IP

dhcp

tftpboot addr file

TFTP下载文件

tftpboot 0x40080000 Image

ping ip

测网络

ping 192.168.1.100

启动类

命令

干什么

示例

booti

启动ARM64 Image

booti 0x40080000 - 0x40200000

bootz

启动zImage

bootz 0x40080000 - 0x40200000

bootm

启动uImage

bootm 0x40080000

环境变量类

命令

干什么

示例

setenv

设置变量

setenv bootargs 'console=ttyAMA0,115200 root=/dev/mmcblk1p2 rootwait rw'

saveenv

保存到Flash

saveenv

editenv

编辑变量

editenv bootargs

ARM64必须用booti,不能用bootz。booti三个参数分别是:内核Image地址、initramfs地址(没有就填-)、设备树dtb地址。我见过有人把dtb地址填错位置,内核启动后设备树全是零,各种驱动加载失败,查了好久才定位到。

三、Linux 5.10内核启动:head.S的大改与源码逐行拆解

Linux内核的启动流程在不同版本间变化很大。4.x时代的ARM64 head.S入口是_text,到5.10已经彻底重构成primary_entry,引入了KASLR、fixmap页表、更复杂的多核启动逻辑。如果还在看老版本的启动代码来盲猜5.10的板子启动流程,会踩很多坑。

3.1 Linux 5.10 head.S的架构变化

1. 入口点重命名和分拆
老版本只有一个_text标签做所有事。5.10把它拆成三层:
primary_entry:外部可见的主入口,链接脚本把内核Image的入口指向这里
__primary_entry:主CPU的入口,负责创建页表、开启MMU、跳转C代码
__secondary_entry:从CPU的入口,负责等主CPU初始化完成后被唤醒
2. KASLR支持
5.10中ARM64正式支持内核地址随机化(KASLR)。内核不再固定在PAGE_OFFSET运行,而是可以通过kaslr_seed在设备树的/chosen节点中传递随机种子,内核启动时自我重定位到一个随机地址。这导致head.S里的所有地址操作都必须用相对寻址(adrp),绝对地址全部失效。
3. fixmap页表
5.10在创建内核页表时引入了fixmap机制——先映射一小块"临时窗口"用于访问DTB和早期内存分配器,等正式页表建好后再切换。这比老版本直接映射整个内核空间要安全得多。

3.2 primary_entry:5.10内核的真正起点

基于Linux 5.10.209稳定版,逐段拆解arch/arm64/kernel/head.S:
/* * arch/arm64/kernel/head.S * Linux 5.10 ARM64内核入口 */    .section ".head.text""ax"SYM_CODE_START(primary_entry)    /*     * 内核镜像的前4字节     * ROM Code或U-Boot加载后跳到这里     * b指令相对跳转,与加载地址无关     */    b   __primary_entry    .long   0               /* 偏移量到pe_header */    .quad   PE_HEADER       /* PE/COFF头部偏移(EFI启动兼容) */SYM_CODE_END(primary_entry)
primary_entry就一条跳转指令。为什么要多包一层?因为ARM64 Image的头部格式有要求:前4字节必须是可执行指令,后面跟PE/COFF头部用于EFI启动。这个包装层让同一份内核镜像既支持U-Boot直接加载,也支持UEFI固件加载。

3.3 __primary_entry:主CPU真正的初始化

/* * __primary_entry - 主CPU入口 * x0 = dtb物理地址(U-Boot通过x0传入) */SYM_CODE_START(__primary_entry)    /* 保存dtb地址到x21     * ARM64调用约定:x0是内核入口的第一个参数     * U-Boot在booti时把dtb地址放到x0     * x21在head.S全程用于保存dtb地址,不能被覆盖     */    mov x21, x0    /* 保存当前物理地址到x24     * 后续KASLR重定位需要知道内核被加载到哪里     * adrp获取当前PC对应的页对齐物理地址     */    adrp    x24, __primary_entry    /*     * 检查异常级别,设置boot mode标志     * 内核期望在EL2启动(虚拟化支持更好)     * 如果在EL3则先降到EL2     */    bl  set_cpu_boot_mode_flag    /*     * 创建临时页表并启用MMU     * 5.10的核心变化:创建idmap、kernel image映射、fixmap     */    bl  __create_page_tables    /*     * 配置SCTLR_EL1为后续C代码做准备     */    ldr x0, =SCTLR_EL1_FLAGS    msr sctlr_el1, x0    isb    /*     * 设置异常返回地址为__mmap_switched     * eret后CPU会跳到这里,此时MMU已开     * 用eret而不是b来切换上下文     * 因为eret会自动清除特权级转换的状态     */    ldr x8, =__mmap_switched    adr_l   x9, __primary_switched#ifdef CONFIG_RANDOMIZE_BASE    adr_l   x9, __primary_switched + KASLR_OFFSET#endif    br  x8SYM_CODE_END(__primary_entry)
dtb地址保存到x21——ARM64 calling convention规定x0是第一个参数,U-Boot调booti时把dtb的物理地址放到x0。内核入口用x21保存这个值,因为x21是callee-saved寄存器,后续调用的函数不会覆盖它。如果你发现内核启动后设备树解析全错,第一个要查的就是x0/x21的值对不对。

3.4 __create_page_tables:5.10的三套页表映射

老版本只创建一个简单的恒等映射加内核映射,5.10引入了fixmap,分三步走:
/* * __create_page_tables - 创建早期页表 * * 创建三套映射: * 1. idmap: 恒等映射,物理地址=虚拟地址 *    用于MMU开启瞬间的过渡执行 * 2. kernel image: 内核镜像映射 *    将内核映射到最终的虚拟地址(PAGE_OFFSET + KASLR偏移) * 3. fixmap: 固定映射区域 *    用于早期访问DTB、earlycon、FDT等 */SYM_FUNC_START(__create_page_tables)    mov x28, lr    /* 获取页表所在内存 */    adrp    x0, idmap_pg_dir    adrp    x1, swapper_pg_dir    /* 清零页表内存 */    mov x2, #IDMAP_DIR_SIZE    add x2, x2, #SWAPPER_DIR_SIZE    bl  __clear_page_tables    /* 第一步:创建恒等映射(idmap)     * 将内核当前所在的物理地址区域映射到相同的虚拟地址     * 为什么需要这个?因为开启MMU的瞬间,PC还在物理地址上执行     * 必须保证当前执行代码在虚拟地址空间也能访问     * 否则MMU一开,CPU取指失败,直接挂     */    adrp    x0, idmap_pg_dir    mov x1, #IDMAP_BLOCK_SHIFT    mov x2, #IDMAP_BLOCK_SIZE    bl  map_memory    /* 第二步:创建内核镜像映射     * 将内核物理地址映射到PAGE_OFFSET + KASLR偏移的虚拟地址     * 没有KASLR时偏移为0,就是标准的PAGE_OFFSET     */    adrp    x0, swapper_pg_dir    mov x1, #SWAPPER_BLOCK_SHIFT    mov x2, #SWAPPER_BLOCK_SIZE    bl  map_memory    /* 第三步:创建fixmap映射     * fixmap是5.10引入的关键改进     * 在虚拟地址空间顶部固定位置映射几个页面     * 用于:     * - FIX_FDT: 访问设备树DTB     * - FIX_EARLYCON: 早期串口输出     * - FIX_PGD: 临时页表页面     *     * 早期代码不能直接用内核虚拟地址访问DTB     * (因为dtb可能不在内核映射范围内)     * fixmap提供了"窗口"来访问这些不在映射范围内的内存     */    adrp    x0, swapper_pg_dir    mov x1, #SWAPPER_BLOCK_SHIFT    ldr x2, =FIXADDR_START    bl  map_fixmap    ret x28SYM_FUNC_END(__create_page_tables)
恒等映射是生死线。MMU开启的那一刻,CPU的PC寄存器还指向物理地址。如果这个物理地址没有同时映射到虚拟地址空间的相同位置,CPU取下一条指令时MMU做地址翻译会miss,触发translation fault,CPU直接异常——你连个串口输出都看不到,板子静悄悄地死了。
fixmap是5.10的精髓。没有fixmap的老版本中,内核直接用物理地址访问DTB。5.10更严谨:先在fixmap里映射DTB所在的那一页,然后通过fixmap的虚拟地址窗口来解析设备树。好处是DTB可以在内存的任何位置,不要求它在内核镜像附近。

3.5 KASLR在5.10中的实现

ARM64的KASLR(Kernel Address Space Layout Randomization)从4.6开始引入,到5.10已经成熟。核心思路:内核不再固定加载到PAGE_OFFSET,而是在启动时根据随机种子偏移一段距离。
/* * arch/arm64/kernel/kaslr.c * Linux 5.10 KASLR实现 * * 随机种子来源: * 1. 设备树 /chosen/kaslr-seed 属性 * 2. EFI的random seed * 3. 硬件RNG(如果支持) */u16 __initdata memstart_offset_seed;static int __initkaslr_init(void){    u64 seed;    /* 从设备树获取kaslr-seed */    if (!fdt_get_kaslr_seed(&seed)) {        /* 没有种子,KASLR不生效 */        return 0;    }    /*     * 偏移量必须是2MB对齐(ARM64的block size)     * 范围:0 ~ KASLR_RANGE_MAX(通常几GB)     */    kaslr_offset = (seed % KASLR_RANGE_MAX) & ~(SZ_2M - 1);    return 0;}
在设备树中配置KASLR种子:
/ {    chosen {        /*         * kaslr-seed: 64位随机种子         * U-Boot可以在启动时用硬件RNG填充这个值         * 没有这个属性则KASLR不生效         */        kaslr-seed = <0x12345678 0x9abcdef0>;    };};
KASLR对调试的影响:开了KASLR后,内核的虚拟地址每次启动都变,gdb调试时addr2line和vmlinux的符号地址对不上。调试时可以在bootargs里加nokaslr关闭随机化。另一个坑是:KASLR要求内核镜像必须用adrp/adr等PC相对寻址,如果驱动里有硬编码的绝对地址,开了KASLR必崩。

3.6 __mmap_switched:切换到C语言世界

MMU开启后,__mmap_switched负责最后的环境准备:
/* * __mmap_switched - MMU已开,切换到C运行环境 */SYM_CODE_START(__mmap_switched)    /* 清空BSS段     * C代码期望BSS段全零,这里保证这一点     */    adr_l   x0, __bss_start    mov x1, xzr    adr_l   x2, __bss_stop    sub x2, x2, x0    bl  __pi_memset    /* 保存dtb地址到全局变量,C代码后续使用 */    adr_l   x0, __fdt_pointer    str x21, [x0]    /* 保存KASLR偏移量 */    adr_l   x0, kaslr_offset    str x24, [x0]    /* 跳转到start_kernel,正式进入C语言世界 */    b   start_kernelSYM_CODE_END(__mmap_switched)
到这里,汇编部分全部结束。dtb地址从x21存到了全局变量__fdt_pointer,KASLR偏移从x24存到了kaslr_offset,BSS段清零完成——C代码可以放心跑了。

四、Linux 5.10 start_kernel:一百多个初始化函数的完整调用链

start_kernel是内核C代码的入口,在init/main.c(5.10中约在第879行)。这个函数一口气调了上百个初始化函数,是整个内核启动中最长的函数。不用全记住,但要搞清楚哪几个是关键瓶颈。
/* init/main.c, line 879, Linux 5.10 */asmlinkage __visible void __init __no_sanitize_address start_kernel(void){    char *command_line;    char *after_dashes;    /* 第1步:打印内核版本 */    pr_notice("%s", linux_banner);    /* 第2步:架构相关最早期的初始化 */    setup_arch(&command_line);    /* ARM64上这个函数做了非常多的事:     * - 解析设备树(unflatten_device_tree)     * - 初始化内存布局(memblock)     * - 设置内核虚拟地址映射     * - 检测CPU特性(elf_hwcap)     */    /* 第3步:打印命令行参数 */    pr_notice("Command line: %s\n", saved_command_line);    /* 第4步:设置各种核心子系统 */    setup_nr_cpu_ids();          /* CPU数量 */    setup_per_cpu_areas();       /* per-cpu变量区 */    smp_prepare_boot_cpu();      /* SMP启动准备 */    /* 第5步:引导时钟 */    boot_cpu_init();    /* 第6步:内存管理初始化 */    mm_core_init();              /* 核心内存分配器 */    setup_per_cpu_pageset();     /* per-cpu页缓存 */    mem_init();                  /* buddy分配器 */    kmem_cache_init_late();      /* slab分配器 */    /* 第7步:进程调度器 */    sched_init();                /* CFS调度器初始化 */    /* 第8步:RCU读拷贝更新 */    rcu_init();                  /* 关键!很多后续初始化依赖RCU */    /* 第9步:中断和时钟 */    init_IRQ();                  /* 中断控制器(GIC)初始化 */    tick_init();                 /* 时钟事件设备 */    timer_init();                /* ARM64 arch_timer */    /* 第10步:驱动模型 */    driver_init();               /* 设备模型核心:kobject、class、platform bus */    /* 第11步:设备树驱动匹配 */    of_platform_populate(NULL, of_default_bus_match_table, NULLNULL);    /* 第12步:挂载根文件系统 */    vfs_caches_init();    rest_init();                 /* 创建kernel_init线程,最终挂载rootfs */}
5.10相比老版本的关键变化
mm_core_init()替代了旧的mm_init(),更早初始化memblock
rcu_init()位置提前了,因为太多子系统依赖RCU
设备树解析从setup_arch()里拆出了更多子函数
rest_init()最终创建kernel_init线程,由它来挂载根文件系统

4.2 setup_arch()里的设备树解析(5.10版)

setup_arch()是ARM64内核中最重要的架构初始化函数,在arch/arm64/kernel/setup.c(5.10第226行):
/* arch/arm64/kernel/setup.c, line 226 */void __initsetup_arch(char **cmdline_p){    /* 1. 早期设备树扫描 — 只读关键信息 */    setup_machine_fdt(__fdt_pointer);    /* 上面这个函数做了一件很关键的事:     * 把U-Boot传过来的dtb物理地址(存在__fdt_pointer中)     * 通过fixmap映射到虚拟地址空间,然后扫描/compatible、/memory等节点     * 此时正式页表还没建好,所以只能用fixmap窗口     */    /* 2. 解析内核命令行 */    *cmdline_p = boot_command_line;    parse_early_param();    /* 3. 内存布局初始化 */    arm64_memblock_init();    /* memblock是内核早期的简单内存分配器     * 在buddy分配器初始化之前,所有内存申请都靠它     * 这里把设备树里的/memory节点信息注册到memblock     * 同时把内核镜像、dtb、initramfs等区域标记为reserved     */    /* 4. 解析CPU特性 */    cpu_read_bootcpu_ops();    init_cpu_features(&arm64_features);    /* 5. 后续初始化 */    paging_init();        /* 建立正式的内核页表,替换head.S的临时页表 */    arm64_numa_init();    /* NUMA支持(如果启用) */    zone_sizes_init();    /* 内存zone初始化(DMA/NORMAL/HIGHMEM) */}

4.3 unflatten_device_tree:设备树展开

设备树在内存中有两种形态:
扁平形态(FDT):U-Boot传过来的原始dtb二进制,紧凑存储,只能顺序扫描
展开形态(unflattened):内核解析后转换成的树形数据结构,可以随机访问
转换在drivers/of/fdt.c中完成(5.10第1245行):
/* drivers/of/fdt.c, line 1245 */void __init unflatten_device_tree(void){    /* 1. 分配内存,将FDT展开为struct device_node树 */    __unflatten_device_tree(initial_boot_params, NULL, &of_root,                            early_init_dt_alloc_memory_arch, false);    /* 2. 获取/choosen节点信息:bootargs、initrd、kaslr-seed等 */    of_alias_scan(early_init_dt_alloc_memory_arch);    /* 3. 此后设备树不再是二进制blob     * 变成了内核里的struct device_node链表     * 驱动可以通过of_find_node_by_path()等API随机访问     */}
这个转换发生得很早,在setup_arch() -> paging_init()之后。一旦展开,内核就不再需要fixmap来访问DTB了——设备树信息已经变成了内核数据结构。

4.4 rest_init()和kernel_init:从内核空间到用户空间

start_kernel最后调用rest_init(),它创建两个内核线程:
/* init/main.c, line 679, Linux 5.10 */noinline void __ref rest_init(void){    /* 创建kernel_init线程(PID=1),即未来的init进程 */    pid = kernel_thread(kernel_init, NULLCLONE_FS);    /* 创建kthreadd线程(PID=2),内核线程管理器 */    pid = kernel_thread(kthreadd, NULLCLONE_FS | CLONE_FILES);    /* 当前CPU0进入idle循环 */    cpu_startup_entry(CPUHP_ONLINE);}
kernel_init线程最终完成根文件系统挂载和init进程启动:
/* init/main.c, line 1413, Linux 5.10 */static int __refkernel_init(void *unused){    /* 1. 等待设备驱动初始化完成 */    kernel_init_freeable();    /* 2. 尝试执行init程序 */    if (ramdisk_execute_command) {        if (run_init_process(ramdisk_execute_command))            pr_err("Failed to execute %s\n", ramdisk_execute_command);    }    if (execute_command) {        if (run_init_process(execute_command))            pr_err("Failed to execute %s\n", execute_command);    }    /* 3. 按顺序尝试4个默认init路径 */    if (!run_init_process("/sbin/init") ||        !run_init_process("/etc/init") ||        !run_init_process("/bin/init") ||        !run_init_process("/bin/sh"))        return 0;    /* 全部失败,panic */    panic("No working init found.  Try passing init= option to kernel.");}
注意5.10的一个改动:错误信息从"No init found"变成了"No working init found",加了"working"这个词——因为init文件可能存在但不可执行,或者动态库缺失导致执行失败,这些情况不算"找不到",算"不能用"。

五、设备树在启动中的完整角色

ARM64架构完全依赖设备树描述硬件信息,整个启动过程中设备树参与了三个阶段:
阶段1:U-Boot传dtb
U-Boot把dtb文件从存储设备加载到内存,通过booti命令的第三个参数指定dtb地址,U-Boot在跳转内核前把dtb地址放到x0寄存器。
阶段2:内核early FDT扫描
setup_arch() -> setup_machine_fdt()阶段,通过fixmap映射读取FDT,提取/memory、/chosen等关键信息。此时还是扁平二进制格式,只能顺序读取。
阶段3:展开并驱动匹配
unflatten_device_tree()把FDT转为struct device_node树。此后of_platform_populate()遍历设备树所有节点,通过of_match_table匹配驱动,完成设备-驱动绑定。
根文件系统分区信息通过/chosen节点传递:
/ {    chosen {        stdout-path = "serial0:115200n8";        bootargs = "console=ttyAMA0,115200 root=/dev/mmcblk1p2 rootwait rw";        linux,initrd-start = <0x84000000>;        linux,initrd-end = <0x85000000>;    };};

六、手动制作根文件系统

根文件系统是内核挂载的第一个文件系统,包含系统运行必需的命令、库、配置文件。

6.1 目录结构

/├── bin/          基础命令(ls、cp、mv等)├── sbin/         # 系统管理命令(ifconfig、mount等)├── etc/          # 配置文件(inittab、fstab、init.d等)├── dev/          # 设备文件(tty、mmcblk等)├── proc/         # procfs挂载点├── sys/          # sysfs挂载点├── tmp/          # 临时文件├── root/         # root家目录├── lib/          # 动态链接库├── usr/          # 用户程序├── mnt/          # 外部存储挂载点└── linuxrc       # init进程入口

6.2 方式1:BusyBox做最小系统

BusyBox把几百个Linux命令打包成一个二进制,做嵌入式最小根文件系统的首选。
下载编译:
wget https://busybox.net/downloads/busybox-1.36.0.tar.bz2tar xjf busybox-1.36.0.tar.bz2cd busybox-1.36.0make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfigmake ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig勾选 Settings -> Build static binary (no shared libs)# 静态编译省去拷贝动态库的麻烦make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- install# 产物在_install目录
补全目录和配置:
cd _installmkdir -p dev etc proc sys tmp mnt root etc/init.d/etc/inittab — init进程的配置cat > etc/inittab << EOF::sysinit:/etc/init.d/rcSttyAMA0::askfirst:-/bin/sh::ctrlaltdel:/sbin/reboot::shutdown:/sbin/swapoff -a::shutdown:/bin/umount -a -rEOF# /etc/init.d/rcS — 启动脚本cat > etc/init.d/rcS << EOF#!/bin/shmount -t proc proc /procmount -t sysfs sysfs /sysmount -t tmpfs tmpfs /tmpmdev -sifconfig lo upEOFchmod +x etc/init.d/rcS# /etc/fstabcat > etc/fstab << EOFproc            /proc           proc    defaults        0       0sysfs           /sys            sysfs   defaults        0       0tmpfs           /tmp            tmpfs   defaults        0       0EOF# 设备节点sudo mknod dev/console c 5 1sudo mknod dev/null c 1 3
打包ext4镜像:
dd if=/dev/zero of=rootfs.ext4 bs=1M count=128mkfs.ext4 rootfs.ext4mkdir rootfs_mountsudo mount rootfs.ext4 rootfs_mountsudo cp -rf _install/* rootfs_mount/sudo umount rootfs_mount

6.3 方式2:Buildroot做完整系统

BusyBox做出来的系统太精简,连个ssh都没有。需要更完整的功能就用Buildroot,它一键编译交叉工具链、U-Boot、内核、根文件系统。
git clone https://git.buildroot.net/buildrootcd buildrootmake qemu_aarch64_virt_defconfigmake menuconfigTarget options -> ARM64# Filesystem images -> ext2/3/4 root filesystem# Target packages -> 按需选(nginx、openssh、python3等)make -j$(nproc)
输出产物在output/images/,rootfs.ext4即根文件系统镜像

6.4 根文件系统踩坑清单

"Kernel panic - not syncing: No init found":检查/sbin/init是否存在、权限是否755、bootargs中init=参数是否正确。BusyBox默认装的是/linuxrc,有些内核配置找不到就panic
"VFS: Cannot open root device":两件事——确认内核编译了根分区的存储驱动(MMC驱动是CONFIG_MMC_SDHCI),确认bootargs的root=写对了
动态链接程序报"No such file or directory":文件明明在,但运行报错。大概率是缺动态链接器或共享库。用aarch64-linux-gnu-readelf -d your_program查看依赖,把缺的.so拷到/lib

启动问题排查速查

这些问题我基本都踩过,排了无数小时的坑总结出来的:

现象

查什么

怎么解

U-Boot启动后串口无输出

串口基地址、波特率、时钟频率

检查CONFIG_DEBUG_UART_BASECONFIG_BAUDRATE,拿示波器看TX引脚有没有波形

U-Boot加载内核失败

存储设备状态、镜像地址、镜像完整性

md看内存里内核头部magic是否正确(ARM64 Image头部是0x644d5241即"ARM\x64"),不对应就重烧

"Starting kernel..."后卡死

bootargs的console参数、串口驱动

确保console=ttyAMA0,115200,内核配了CONFIG_SERIAL_AMBA_PL011。还有一个可能:dtb地址错了

内核panic:No init found

init程序存在性、权限、动态库

init=/bin/sh跳过正常init直接进shell调试,先确认根文件系统能挂上

进shell后无法输入

/dev/console设备节点

手动创建:mknod /dev/console c 5 1,权限600

设备树解析后驱动全挂

dtb地址、dtb完整性

在U-Boot里fdt addr 0x40200000 && fdt print先验证dtb能不能正常解析

八、总结

ARM64嵌入式Linux启动,三个阶段各有各的难:
U-Boot:硬件初始化是黑盒,不同SoC差异大,关键是搞清楚异常级别切换和内存重定位
内核head.S:5.10大改了入口结构和页表创建方式,KASLR和fixmap是两个必须理解的新机制
根文件系统:BusyBox做最小系统、Buildroot做完整系统,踩坑都在动态库和设备节点上
调试启动问题有个通用思路:从后往前排除先确认根文件系统镜像没问题(loop挂载看内容),再确认内核能找到root分区(加init=/bin/sh),再确认U-Boot传参正确(printenv检查bootargs和dtb地址),最后才去看硬件问题。大部分启动卡死都不是硬件的锅。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 05:22:43 HTTP/2.0 GET : https://f.mffb.com.cn/a/500810.html
  2. 运行时间 : 0.103474s [ 吞吐率:9.66req/s ] 内存消耗:4,925.80kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=53b36fb74c791cc9cb13f30122499454
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000404s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000551s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000322s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.002549s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000557s ]
  6. SELECT * FROM `set` [ RunTime:0.000206s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000628s ]
  8. SELECT * FROM `article` WHERE `id` = 500810 LIMIT 1 [ RunTime:0.000674s ]
  9. UPDATE `article` SET `lasttime` = 1783027363 WHERE `id` = 500810 [ RunTime:0.016351s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000690s ]
  11. SELECT * FROM `article` WHERE `id` < 500810 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000913s ]
  12. SELECT * FROM `article` WHERE `id` > 500810 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.004466s ]
  13. SELECT * FROM `article` WHERE `id` < 500810 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.001088s ]
  14. SELECT * FROM `article` WHERE `id` < 500810 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001902s ]
  15. SELECT * FROM `article` WHERE `id` < 500810 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001475s ]
0.105020s