当前位置:首页>Linux>多核初始化与SMP同步机制:Linux与wandos的深度对比

多核初始化与SMP同步机制:Linux与wandos的深度对比

  • 2026-06-29 19:54:54
多核初始化与SMP同步机制:Linux与wandos的深度对比

引子:从一颗到多颗CPU

早期PC只有一颗CPU,所有指令串行执行。操作系统调度器的工作很简单——只要有一个任务在跑,别的任务就得等着。

但物理世界很快碰到了瓶颈:单核性能提升遇到了"功耗墙"——主频不能再高,散热压不住。要更强的算力,只剩一条路:在同一个系统里塞进多颗CPU

这就是 SMP(Symmetric Multi-Processing,对称多处理) 诞生的背景。多个CPU核心平等地共享同一块物理内存,每个核心都有自己的寄存器、L1/L2缓存,但共享内存总线和DRAM。Linux内核从2.0开始支持SMP, wandos 同样实现了这一机制。

本文基于 wandos 的 SMP 源码(arch/x86/smp.cppkernel/smp/smp_scheduler.cpp),深入解析多核系统从开机到调度的一切细节。


一、APIC体系:多核通信的基石

在单核时代,外设中断由 8259A PIC(可编程中断控制器)统一管理,一颗芯片串起15个IRQ。但多核时代,PIC 无法将中断精准投递给某个CPU核心——它只知道"有中断发生",不知道"哪颗CPU来处理"。

APIC(Advanced Programmable Interrupt Controller) 解决了这个问题,采用双层架构:

1.1 Local APIC(LAPIC)—— 每CPU一个

每个CPU核心内部集成一颗 LAPIC,负责:

  • 接收来自 IOAPIC 的外部中断
  • 接收来自其他CPU的 IPI(Inter-Processor Interrupt)
  • 管理本地中断(LINT,即Local Interrupt,如温度传感器、计时器等)

LAPIC 内部有一组寄存器,映射到 MMIO 地址 0xFEE00000(这是物理地址,在开启分页后通过恒等映射访问):

// apic.cpp
#define LAPIC_BASE 0xFEE00000
static inline uint32_t apic_read(uint32_t reg) {
    return *((volatile uint32_t*)(LAPIC_BASE + reg));
}

LAPIC ID 是每颗CPU的唯一标识,通过读取 LAPIC_ID 寄存器得到:

uint32_t apic_get_id() {
    return (apic_read(LAPIC_ID) >> 24) & 0xFF;
}

wandos 在 smp_init() 中,先获取 BSP 的 LAPIC ID 作为主标识,再向其他 AP 发送启动信号:

bsp_lapic_id = apic_get_id();
auto cpu_count = apic_get_cpu_count();
log_debug("系统总 CPU 数量: %d, BSP ID: %d\n", cpu_count, bsp_lapic_id);

1.2 IOAPIC —— 外设中断的路由器

与每核一个的 LAPIC 不同,系统只有 一颗 IOAPIC,负责将外设IRQ路由到正确的 LAPIC。IOAPIC 有24个重定向表项(Redirection Table Entry),每个对应一个IRQ线:

#define IOAPIC_BASE 0xFEC00000
#define IOAPIC_IOREGSEL 0x00
#define IOAPIC_IOWIN 0x10

IOAPIC 的中断重定向配置非常灵活——可以指定:

  • 目标中断向量(决定最终跳转到哪个中断处理程序)
  • 目标 LAPIC(哪个CPU处理)
  • 触发模式(边沿触发 vs 电平触发)
  • 投递模式(物理模式 vs 逻辑模式)

wandos 在初始化时把24个IRQ全部配置好:

void ioapic_set_irq(uint8_t irq, uint64_t value) {
    uint32_t ioredtbl = 0x10 + 2 * irq;
    ioapic_write(ioredtbl, (uint32_t)value);
    ioapic_write(ioredtbl + 1, (uint32_t)(value >> 32));
}

Linux 的 IOAPIC 初始化类似,在 setup_IO_APIC() 中构建重定向表,实现"外设 → IOAPIC → LAPIC → CPU"的中断投递链。


二、BSP与AP:谁是主人

SMP系统里,CPU 分为两类角色:

角色 全称 职责
BSP Bootstrap Processor 唯一由BIOS/UEFI引导的CPU,负责初始化系统、构建页表、加载内核、发送启动信号
AP Application Processor 被 BSP 唤醒的多核,负责执行应用代码

系统上电时,只有 BSP 活跃。其他 CPU 核心处于"未定义"状态——没有GDT、没有IDT、没有页表,甚至不知道自己是一颗CPU。BSP 的任务就是逐一唤醒它们。

wandos 的 smp_init() 清晰展示了这个过程:

void smp_init() {
    bsp_lapic_id = apic_get_id();
    auto cpu_count = apic_get_cpu_count();

    // 发送 INIT-SIPI-SIPI 序列启动 APs
    for(uint32_t i = 0; i < cpu_count; i++) {
        uint32_t target_id = i;
        if(target_id != bsp_lapic_id) {
            apic_send_init(target_id);              // 1. INIT:复位AP
            for(int j = 0; j < 1000000; j++)
                __asm__ volatile("pause");
            apic_send_sipi(0x8000, target_id);      // 2. SIPI:AP从0x8000开始执行
            for(int j = 0; j < 1000000; j++)
                __asm__ volatile("pause");
            apic_send_sipi(0x8000, target_id);      // 3. 再发一次SIPI,确保收到
            for(int j = 0; j < 1000000; j++)
                __asm__ volatile("pause");
        }
    }

    // 等待所有AP就绪
    while(cpu_ready_count < apic_get_cpu_count() - 1) {
        __asm__ volatile("pause");
    }
}

INIT-SIPI-SIPI 序列

这套序列背后的原理值得细说:

INIT IPI:向目标 AP 发送 Reset 信号。AP 会执行一次软件复位,清除内部部分状态,但不初始化段寄存器和页表。AP 随后进入"等待启动向量"状态。

SIPI(Startup IPI):携带一个物理地址(必须是4KB对齐的),AP 收到后将这个地址的向量值(vector << 12)作为入口地址,跳转执行。wandos 使用 0x8000,对应向量值 0x80 >> 12 = 0x02,实际上 AP 会从物理地址 0x8000(即 0x02 << 12)开始取指令。

为什么要发两次 SIPI?因为 AP 可能还没完全处理完第一次的 Reset 状态,第二发是"保险"。在真实硬件上,部分 AP 可能错过第一次 SIPI。

AP_entry:AP的C语言入口

AP 收到 SIPI 后,跳转到 ap_entry() 函数继续执行:

void ap_entry() {
    uint32_t current_cpu_id = apic_get_id();
    log_debug("ap_entry, CPU ID: %d\n", current_cpu_id);

    apic_init();                          // 初始化当前AP的LAPIC
    apic_init_timer(100);                // 设置100Hz本地定时器
    cpu_init_percpu();                    // 初始化Per-CPU数据区

    GDT::loadGDT();                        // 加载GDT(与BSP共享)
    GDT::loadTR(current_cpu_id);           // 加载当前CPU的TSS
    // 切换到与BSP相同的页目录
    kernel.kernel_mm().paging().loadPageDirectory(0x400000);
    kernel.kernel_mm().paging().enablePaging();

    // 加载BSP创建的第一个任务的上下文
    auto task = kernel.scheduler().get_current_task();
    asm volatile("mov %0, %%cr3" ::"r"(task->regs.cr3));
    asm volatile("mov %0, %%esp" ::"r"(task->stacks.esp0));

    // 原子增加就绪计数器
    __atomic_add_fetch(&cpu_ready_count, 1, __ATOMIC_SEQ_CST);
    log_debug("CPU %d 已就绪\n", current_cpu_id);

    asm volatile("sti");                  // 启用中断
    while(true) {
        asm volatile("hlt");              // 进入空闲循环,等调度
    }
}

注意几个细节:

  1. GDT和IDT共享:所有CPU使用同一套GDT和IDT。BSP初始化好了,AP 直接 loadGDT() 即可。
  2. Per-CPU 初始化cpu_init_percpu() 为当前CPU设置Per-CPU数据区的基址——每个CPU看到这个基址不同,因此访问到的 Per-CPU 变量也不同。
  3. 原子计数器cpu_ready_count__atomic_add_fetch 递增,使用 __ATOMIC_SEQ_CST 顺序一致性保证 BSP 能看到准确的AP就绪数量。
  4. idle任务:AP 最终进入 hlt(halt)指令组成的空闲循环,直到被定时器中断唤醒。

Linux 的 AP 启动流程与 wandos 完全一致:AP 在 smpboot.cstart_secondary() 中完成类似初始化后进入 cpu_idle(),该函数核心就是 while(!need_resched()) halt()


三、Per-CPU数据:给每个CPU一份专属变量

SMP系统里,调度器必须有独立的运行队列——如果所有CPU共享一个队列,加锁开销巨大,严重影响性能(想象一下8核CPU争抢一把锁)。每个CPU必须有自己专属的数据副本。

wandos 用模板实现了 Per-CPU 数据:

// percpu.h
template<typename T>
class PerCPU {
    T* data_[MAX_CPUS] = {nullptr};

    T* operator->() {
        return data_[get_cpu_id()];    // 当前CPU访问自己的副本
    }
    void set(uint32_t cpu, T *t) {
        data_[cpu] = t;                 // 写入指定CPU的副本
    }
    T* get_for_cpu(unsigned int cpu) {
        return data_[cpu];              // 获取指定CPU的副本
    }
};

get_cpu_id() 通过 LAPIC ID 实现,返回当前正在执行的CPU编号。

基于这个模板,调度器为每颗CPU维护独立的运行队列:

// smp_scheduler.h
class SMP_Scheduler {
    arch::PerCPU<RunQueue> scheduler_runqueue;    // 每CPU独立运行队列
    arch::PerCPU<Task> current_task;              // 每CPU当前任务
    arch::PerCPU<Task> idle_task;                 // 每CPU idle任务
};

struct RunQueue {
    SpinLock lock;
    uint32_t nr_running;
    struct list_head runnable_list;
};

调度器初始化时,对每颗CPU分配独立的堆(heap)上的 RunQueue 对象:

void SMP_Scheduler::init() {
    for (unsigned int cpu = 0; cpu < arch::apic_get_cpu_count(); cpu++) {
        scheduler_runqueue.set(cpu, new RunQueue());
        auto* rq = scheduler_runqueue.get_for_cpu(cpu);
        rq->lock = SPINLOCK_INIT;
        rq->nr_running = 0;
        INIT_LIST_HEAD(&rq->runnable_list);
        if(cpu != 0) {
            auto task = create_idle_task(ProcessManager::kernel_context, cpu);
            idle_task.set(cpu, task);
            current_task.set(cpu, task);
        }
    }
}

调度时,pick_next_task() 永远操作当前CPU的运行队列:

Task* SMP_Scheduler::pick_next_task() {
    RunQueue* rq = scheduler_runqueue.operator->();   // 当前CPU的队列
    spin_lock(&rq->lock);
    if (list_empty(&rq->runnable_list)) {
        spin_unlock(&rq->lock);
        return load_balance();   // 本地队列空,尝试偷任务
    }
    Task* next = list_entry(rq->runnable_list.next, Task, sched_list);
    list_del_init(&next->sched_list);
    rq->nr_running--;
    spin_unlock(&rq->lock);
    return next;
}

Linux 内核同样使用 Per-CPU 数据结构。在 kernel/sched/core.c 中,struct rq(运行队列)是完全 Per-CPU 的,通过 raw_rq() Per-CPU 变量访问。pick_next_task() 也遵循同样的"先本地、后偷取"策略。


四、自旋锁:SMP同步原语

多核系统里,数据竞争无处不在。当两个CPU同时往同一个运行队列里入队任务时,必须有同步机制。

wandos 实现了一个经典的自旋锁:

// spinlock.h
class SpinLock {
    volatile uint8_t locked;

    void acquire() {
        while(__atomic_test_and_set(&locked, __ATOMIC_ACQUIRE)) {
            asm volatile("pause");
        }
    }

    void release() {
        __atomic_clear(&locked, __ATOMIC_RELEASE);
    }

    // 保存中断状态的加锁版本
    void acquire_irqsave(uint32_t& flags) {
        asm volatile("pushf; pop %0" : "=r"(flags));
        asm volatile("cli");      // 关中断,防止死锁
        acquire();
    }
};

几个关键点:

__atomic_test_and_set:这是 GCC 内建的原子指令(底层是 x86xchg 指令),保证"读取-修改-写入"三步在硬件层面不可分割。没有这层原子性,两个CPU可能同时认为锁是"空闲"的,同时闯入临界区。

pause 指令:在锁竞争时,pause 提示CPU"我在忙等",让出执行端口的带宽,减少总线仲裁的无效流量。在 x86 上 spin-wait 循环必须用 pause,否则会影响 CPU 的乱序执行效率。

acquire / release 语义__ATOMIC_ACQUIRE 确保在获得锁之前,所有后续内存读写都在锁释放后才对其他线程可见;__ATOMIC_RELEASE 确保释放锁之前,所有本地修改都对获取锁的线程可见。这涉及编译器和CPU的内存屏障,是SMP代码中最容易出错的细节之一。

Linux 内核的 spinlock 在 kernel/locking/spinlock.c 中实现,逻辑完全一致:使用 xchg 指令做 test-and-set,配合 queued_spin_lock 的排队机制避免"锁总线"问题。


五、调度器:多核任务分配

wandos 的 SMP 调度器核心在 pick_next_task()load_balance() 两个函数。

5.1 入队与选核

当一个任务被创建或从阻塞中唤醒时,需要决定它进入哪个CPU的运行队列:

void SMP_Scheduler::enqueue_task(Task* p, int cpu_id) {
    RunQueue* rq = scheduler_runqueue.get_for_cpu(cpu_id);
    spin_lock(&rq->lock);
    list_add_tail(&p->sched_list, &rq->runnable_list);
    rq->nr_running++;
    spin_unlock(&rq->lock);
}

注意这里可以指定入队到某颗CPU——这对 CPU 亲和性(affinity)很重要。如果一个进程被绑定了特定的 CPU 掩码(mask),调度器必须遵守这个约束。

5.2 任务窃取(Load Balance)

当某颗CPU的本地运行队列空了(所有任务都在其他核上运行),调度器不会闲着,而是从最繁忙的CPU那里"偷"一个任务来:

Task* SMP_Scheduler::load_balance() {
    RunQueue* rq = scheduler_runqueue.operator->();  // 当前CPU队列
    spin_lock(&rq->lock);
    if (!list_empty(&rq->runnable_list)) {
        auto* stolen = list_entry(rq->runnable_list.next, Task, sched_list);
        list_del_init(&stolen->sched_list);
        rq->nr_running--;
        spin_unlock(&rq->lock);
        log_debug("stealing task %d from CPU %d\n",
                  stolen->task_id, arch::apic_get_id());
        return stolen;
    }
    spin_unlock(&rq->lock);
    return get_idle_task();   // 真的没活干,返回idle任务
}

wandos 的实现较为简单:当本地队列为空时,直接从当前CPU队列的头部(runnable_list.next)取一个任务。Linux 的 load_balance 远比这复杂:它会遍历所有CPU找出最繁忙的队列(find_busiest_cpu()),并一次最多搬移 sysctl_sched_nr_migrate 个任务。

5.3 CPU亲和性

调度器支持将进程绑定到特定CPU子集:

void SMP_Scheduler::set_affinity(Task* p, uint32_t cpu_mask) {
    if (!p) return;
    uint32_t valid_mask = (1 << MAX_CPUS) - 1;
    cpu_mask &= valid_mask;
    if (cpu_mask == 0) cpu_mask = valid_mask;   // 空掩码 = 所有CPU
    p->affinity = cpu_mask;
}

Linux 调度器严格遵守 cpus_allowed 掩码。如果一个进程被绑定到特定核心,调度器只会在这些核心上选择它。


六、多核与Linux内核:更大的图景

wandos 展示了一个SMP系统的核心要素,但Linux内核的SMP实现要复杂得多。几个关键扩展:

6.1 调度类与CFS

Linux 从 O(1) 调度器(2.6内核)演进到 CFS(Completely Fair Scheduler),用红黑树维护"虚拟运行时间",保证每个进程获得公平的CPU份额。CFS 是 SMP友好的——每个CPU有独立的 CFS 树,锁只保护树操作本身而非整个调度器。

6.2 内存屏障与MESI

在多核系统里,CPU 缓存一致性(CACHE COHERENCY)是核心挑战。x86 使用 MESI 协议(Modified/Exclusive/Shared/Invalid)维护缓存一致性。wandos 的原子操作只涉及单变量;如果涉及跨CPU的数据结构(如全局进程链表),必须配合 smp_call_function_all() 或真正的内存屏障指令(mfence/lfence/sfence)。

6.3 IPI 实际应用

APIC 不仅用于启动 CPU,还用于:

  • 调度器时钟中断(Reschedule IPI):强制目标CPU重新调度
  • TLB shootdown:当一个CPU修改了页表项,其他CPU的TLB中的旧条目需要失效
  • 停止/重启 CPU:用于热插拔或在特定场景下暂停某核

wandos 的 apic_send_sipi() 发送 IPI 时,用 ICR(Interrupt Command Register)的 delivery_status 位轮询确认发送完成:

while (apic_read(LAPIC_ICR0) & APIC_ICR_PENDING_MASK) {
    asm volatile("pause");
}

总结:多核系统的本质矛盾

SMP 系统看似简单——"多颗CPU共享内存"——但实现处处是陷阱:

层次 挑战 wandos 处理
CPU启动 AP没有初始化,如何唤醒 INIT-SIPI-SIPI序列
中断路由 外设中断如何精准投递 IOAPIC重定向表+LAPIC ID
数据竞争 多核同时修改同一结构 Per-CPU数据(消除竞争) + 自旋锁(保护共享数据)
缓存一致 修改对其他核可见 x86硬件保证(TSO)+ 内存屏障
负载均衡 空载核如何获得任务 任务窃取(load_balance)

Linux 内核用了20年把这些机制打磨到极致,而 wandos 用几百行代码完整实现了 SMP 的核心框架麻雀虽小,五脏俱全。下一篇文章我们将探讨 进程间通信(IPC)——管道、消息队列、共享内存——看看 Linux 和 wandos 如何在多核环境里安全地传递数据。


作者:Dean
相关项目:wandos
系列目录:从零写OS内核 — 目录

系列说明:本文为"从零写OS内核"系列第255篇,结合 Linux 原理与 wandos 源码(zhangfuwen/wandos)深入解析操作系统核心概念。wandos 当前覆盖:内存管理(buddy/slab/paging)、进程调度(scheduler/elf)、文件系统(VFS/ext2/memfs)、系统调用、中断与SMP。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 21:57:57 HTTP/2.0 GET : https://f.mffb.com.cn/a/493088.html
  2. 运行时间 : 0.109028s [ 吞吐率:9.17req/s ] 内存消耗:4,725.13kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=07f04e25fdfddf27ecc608d0ef63c878
  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.000574s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000843s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000317s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000329s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000492s ]
  6. SELECT * FROM `set` [ RunTime:0.000199s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000647s ]
  8. SELECT * FROM `article` WHERE `id` = 493088 LIMIT 1 [ RunTime:0.001651s ]
  9. UPDATE `article` SET `lasttime` = 1783087077 WHERE `id` = 493088 [ RunTime:0.010097s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000249s ]
  11. SELECT * FROM `article` WHERE `id` < 493088 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000870s ]
  12. SELECT * FROM `article` WHERE `id` > 493088 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000447s ]
  13. SELECT * FROM `article` WHERE `id` < 493088 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.004418s ]
  14. SELECT * FROM `article` WHERE `id` < 493088 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.008351s ]
  15. SELECT * FROM `article` WHERE `id` < 493088 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.011117s ]
0.110689s