当前位置:首页>Linux>linux内核——调度系统——代理执行 (SCHED_PROXY_EXEC)

linux内核——调度系统——代理执行 (SCHED_PROXY_EXEC)

  • 2026-06-14 15:11:00
linux内核——调度系统——代理执行 (SCHED_PROXY_EXEC)

代理执行 (SCHED_PROXY_EXEC) 解析

Android17-kernel-6.18 已经默认打开SCHED_PROXY_EXEC特性,且应用于mutexrwsem中,借此机会梳理一下SCHED_PROXY_EXEC特性


一、一句话概述

代理执行(Proxy Execution) 是 Linux 调度器的一项高级特性,它让持有互斥锁(mutex/rwsem)的低优先级任务,在被高优先级任务等待时,「借用」高优先级任务的调度身份去抢占 CPU 运行——从而从根本上解决优先级反转问题。


二、核心问题:什么是优先级反转?

2.1 直观场景

假设系统中有三个任务:

任务
优先级
状态
任务 H(高优先级)
等待 mutex(被 L 持有)
任务 M(中优先级)
就绪,可以运行
任务 L(低优先级)
持有 mutex,但被 M 抢占了

传统调度器的困境:

  • H 被阻塞在 mutex 上,无法运行
  • L 持有锁却因为优先级低无法获得 CPU(被 M 抢占),无法释放锁
  • M 这个「中间人」一直跑,让 H 永远等待

这就是经典的 优先级反转 问题。

2.2 传统方案:

2.2.1 优先级继承(PI)

传统的 RT mutex 采用 优先级继承

  • 当 H 等待 L 持有的锁时,L 临时获得 H 的高优先级
  • 这样 L 可以抢占 M,快速完成临界区并释放锁

PI 的局限:

  • PI 只影响优先级,不改变「谁在跑」这个根本问题

  • 对于普通 mutex(非 RT),内核默认不做 PI

  • PI 只能往上提,不能解决复杂的多级依赖链

2.2.2 其他优先级传递

各个厂商都有针对cfs任务、各类同步机制客制化的优先级传递方案来解决优先级逆置的问题,这里不多赘述。

2.3 代理执行的思路

既然 H 跑不了,那我就让 H 去替 L 跑!让 L 的身体执行 H 想要做的事情。

代理执行的核心洞察:调度上下文和运行上下文可以分离

  • 调度上下文(donor/捐献者)
    :H 任务告诉调度器它应该抢占谁、该运行在哪个 CPU
  • 执行上下文(curr/当前执行者)
    :L 任务实际在 CPU 上运行的代码

三、核心概念架构

3.1 rq (runqueue) 结构的分离

代理执行最关键的改变在 struct rq 中:

// 文件: kernel/sched/sched.h#ifdef CONFIG_SCHED_PROXY_EXEC    struct task_struct __rcu  *donor;  /* 调度上下文 - 谁在选择 */    struct task_struct __rcu  *curr;   /* 执行上下文 - 谁在跑 */#else    union {        struct task_struct __rcu *donor; /* 没有代理执行时,二者合一 */        struct task_struct __rcu *curr;    };#endif
概念
含义
类比
donor
调度上下文——任务选择的依据
谁拿到了方向盘(决定走哪条路)
curr
执行上下文——实际在 CPU 上跑的任务
谁踩了油门(实际开车的人)
无代理执行
二者是同一个任务
自己开车自己导航
有代理执行
二者可以是不同任务
「代驾」模式:donor 是车主选路线,curr 是代驾司机在开

3.2 blocked_on 链

代理执行的数据结构定义了一组「阻塞关系链」:

// 文件: include/linux/sched.h:enum blocked_on_type {    BO_T_NONE,   // 没有阻塞在任何锁上    BO_T_MUTEX,  // 阻塞在 mutex 上    BO_T_RWSEM,  // 阻塞在 rwsem 上};struct blocked_on_lock {    void *lock;                // 指向阻塞的锁对象    enum blocked_on_type type; // 锁的类型};

3.3 task_struct 中的代理执行字段

// 文件: include/linux/sched.h:1276-1286struct task_struct {    // ===== 所有配置下都有 =====    struct task_struct   *blocked_donor;  // 正在给我们捐赠调度上下文的那个任务    struct blocked_on_lock blocked_on;    // 我们阻塞在哪个锁上    raw_spinlock_t        blocked_lock;   // 保护上述字段的自旋锁#ifdef CONFIG_SCHED_PROXY_EXEC    // ===== 仅代理执行开启时 =====    struct list_head      migration_node;    // 跨 CPU 迁移时使用的链表节点    struct list_head      blocked_head;      // 阻塞在我们身上的任务链表(我们是锁持有者)    struct list_head      blocked_node;      // 我们在别人 blocked_head 上的链表节点    struct list_head      blocked_activation_node; // 用于级联激活的链表节点    struct task_struct   *sleeping_owner;    // 当我们 sleep 时,持有我们 blocked_node 的 owner#endif};

3.4 关系的可视化

          blocked_donor 指向  ┌─────────────────────────────────┐  │                                 │  ▼                                 │┌──────────┐    blocked_on     ┌──────────┐│ Task H   │ ────────────────► │  mutex   ││ (高优先) │    等待这个锁      │          │└──────────┘                   │ owner    │                               │          │               blocked_head    ▼          │  ┌──────────┐  ◄─────────  ┌──────────┐  │  │ Task H   │              │ Task L   │──┘  │          │   H 挂在 L 的 │ (低优先) │ 持有锁  │(blocked  │  blocked_head│          │  │ _node)   │  链表上       └──────────┘  └──────────┘                   ▲                                 │ blocked_donor = H                        ┌────────┴──────┐                        │ 调度器视角:    │                        │ donor = H     │  ← 调度器按 H 的优先级排                        │ curr  = L     │  ← 但实际跑的是 L                        └───────────────┘

关键理解:

  • 在 runqueue 中,donor 指向 H(因为 H 的优先级高,调度器选择运行 H)
  • 但实际在 CPU 上执行的 curr 是 L
  • 当调度器发现 donor(H)是阻塞的,就追踪 blocked_on → mutex → owner(L),让 L 作为执行上下文去跑
  • L 跑完之后释放 mutex,H 被唤醒

四、核心算法:find_proxy_task()

文件: `kernel/sched/core.c

这是代理执行的灵魂函数。每当 __schedule() 选出了下一个要运行的任务 next,如果 next 是阻塞的(task_is_blocked(next)),就调用 find_proxy_task() 来找到真正应该跑的任务。

4.1 算法流程图

find_proxy_task() 是一个沿着 blocked_on 链向前追踪的循环算法。每轮循环处理链上的一个节点,根据节点状态分支不同的处理路径。

4.1.0 总览:从 __schedule() 到最终执行上下文

__schedule()                        ┌─ 代理执行关闭: 到此为止    │                               │   直接运行 donor    ├► pick_next_task(rq) ─► donor  │    ├► rq_set_donor(rq, donor)      │    │                               │    ├► task_is_blocked(donor) ?     │    │   ├─ NO ──────────────────────┘    │   └─ YES ──► find_proxy_task(rq, donor)    │                 │    │                 ├── [入口] for(p=donor; task_is_blocked(p); p=owner)    │                 │         ↓    │                 │    ① 原子快照 blocked_on (copy + locked read)    │                 │         ↓    │    ╔═══════ [判断分叉: 7种场景] ═══════╗    │    ║                                     │    ║  A: blocked_on.lock == NULL  ──► return NULL (链变了, retry)    │    ║  B: PROXY_WAKING             ──► proxy_force_return 回迁    │    ║  C: 取锁后链又变了             ──► return NULL (重试)    │    ║  D: owner 不存在(NULL)        ──► 清除 blocked_on 或 回迁    │    ║  E: owner 不在 rq 上(sleep)   ──► 挂到 owner 身上等一起醒    │    ║  F: owner 在另一个 CPU        ──► proxy_migrate_task 跨核迁移    │    ║  G: owner 正在迁移中          ──► proxy_resched_idle 避让    │    ║  H: owner == p (并发竞态)     ──► proxy_resched_idle 避让    │    ╚═════════════════════════════════╝    │                 ↓ [正常路径]    │         owner->blocked_donor = p  ← 建立代理关系    │         p = owner  继续下一轮循环    │                 ↓    │    [循环出口]  switch(action):    │      MIGRATE     → proxy_migrate_task → return NULL (重试)    │      NEEDS_RETURN → proxy_force_return → return NULL (重试)    │      FOUND       → return owner (执行上下文!)  ★ 终局    │    └► rq->curr = 返回的执行上下文

三种返回值含义:

返回值
含义
__schedule()
 做什么
合法的 task_struct*
找到了执行上下文
切换到该任务运行
NULL
条件不满足,需要重试
goto pick_again
 重新选任务
rq->idle
暂时让给 idle
goto keep_resched
 等待下次调度

4.2 子算法详解

4.2.1 proxy_migrate_task() - 跨CPU迁移

// 文件: kernel/sched/core.c// 当 blocked_on 链跨越了 CPU 时使用staticvoidproxy_migrate_task(struct rq *rq, struct rq_flags *rf,                               struct task_struct *p, int target_cpu)

触发条件:  blocked_on 链的 owner 在另一个 CPU 上:pick到的blocked的任务的owner已经在其他cpu上了,迁走blocked_on 链的所有任务到owner cpu上,防止再pick到。 (题外话:这里的设计对于SCHED_EXT有点不友善? SCHED_EXT基于全局DSQ分发,而proxy exec 默认是从percpu的视角考虑pick_task的)核心逻辑:

  1. 先将当前 rq 的 donor 切为 idle(proxy_resched_idle
  2. 沿着 blocked_donor 链,把所有阻塞任务从当前 rq 上 deactivate
  3. 释放当前 rq 锁
  4. 获取目标 CPU 的 rq 锁
  5. 在目标 rq 上重新 activate 这些任务
  6. 重新获取原 rq 锁,回到 __schedule() 重新选择

设计理念: 调度上下文可以忽略 CPU 亲和性,但执行上下文必须尊重亲和性。所以要把调度上下文「搬」到执行上下文所在的 CPU。

4.2.2 proxy_force_return() - 强制返回迁移

// 文件: kernel/sched/core.c// 当任务被标记为 PROXY_WAKING 时使用staticvoidproxy_force_return(struct rq *rq, struct rq_flags *rf,                               struct task_struct *p)

触发条件: 在放锁路径会给current->blocked_donor设置 PROXY_WAKING,blocked_donor可能被跨cpu迁移至current所在的cpu,因此现在需要被「回迁」到它原本应该运行的 CPU。

PROXY_WAKING 的含义:

#define PROXY_WAKING ((struct mutex *)(-1L))

这是一个特殊的「哨兵值」,放在 blocked_on.lock 中,表示「不要直接运行我,先把我送回老家」。它不等于任何真实 mutex 的地址(-1 不是合法指针),所以可以安全地用作特殊标记。

流程:

  1. 释放原 rq 锁
  2. 重新获取 task_rq_lock(带 pi_lock)
  3. 检查中间是否有变化(任务可能已经被其他人处理了)
  4. 在正确的 rq 上 deactivate 任务
  5. 调用 select_task_rq() 选择正确的目标 CPU
  6. 在目标 rq 上 activate 任务
  7. 重新获取原 rq 锁返回

4.2.3 Sleeping Owner 机制

// 文件: kernel/sched/core.cstaticvoidproxy_enqueue_on_owner(struct rq *rq, struct task_struct *owner,                                   struct task_struct *p)

触发条件: blocked_on 链的锁持有者(owner)当前不在 runqueue 上(sleeping),  owner 可能sleep阻塞等待在其他不支持代理执行的同步机制。

核心做法:

  1. 不着急叫醒 sleeping 的 owner
  2. 把等待者 p 挂到 owner->blocked_head 链表上
  3. 让 p 也进入 blocked 状态
  4. 当 owner 未来被唤醒时,activate_blocked_waiters() 会顺便把 p 也一起激活

这是一个巧妙的「延迟批量激活」策略——避免为每个等待者单独处理,而是跟着 owner 一起唤醒。

4.2.4 activate_blocked_waiters() - 级联激活

// 文件: kernel/sched/core.cstaticvoidactivate_blocked_waiters(struct rq *target_rq,                                     struct task_struct *owner,                                     int wake_flags)

触发时机: 当一个锁持有者被唤醒时(在 ttwu_do_activate() 中调用)。

核心逻辑(「公平份额」机制):

  1. 把 owner->blocked_head 上挂的所有等待任务都摘下来
  2. 依次激活这些任务
  3. 关键:
     被激活的任务自己也可能是某个锁的持有者,它们自己的 blocked_head 上也挂着任务
  4. 所以需要继续检查 p->blocked_head,如果非空,把 p 也加入处理队列
  5. 这是一个 BFS 广度优先 的级联激活过程
owner 被唤醒  │  ├► 激活 owner->blocked_head 上的 T1  │     │  │     └► T1 自己也有 blocked_head → 加入处理队列  │           │  │           ├► 激活 T1->blocked_head 上的 T2  │           └► 激活 T1->blocked_head 上的 T3  │  ├► 激活 owner->blocked_head 上的 T4  │  └► ...

4.2.5 proxy_resched_idle() - 切回 idle 重试

// 文件: kernel/sched/core.c:7223-7229static inline struct task_struct *proxy_resched_idle(struct rq *rq){    put_prev_set_next_task(rq, rq->donor, rq->idle);    rq_set_donor(rq, rq->idle);    set_tsk_need_resched(rq->idle);    return rq->idle;}

用途: 当 find_proxy_task() 遇到暂时无法处理的情况(如 owner 正在迁移、owner == p 竞态),不强行处理,而是切到 idle 然后重新调度,给系统一个「喘息」的机会。


五、锁子系统的集成

5.0 核心问题:锁和调度器怎么联动?

回顾代理执行的核心设计:调度器通过 blocked_on 链来追踪「谁在等谁」,然后让锁持有者「替」等待者执行。但这个 blocked_on 信息是谁设置的?答案是:锁子系统自己

每次一个任务尝试获取锁失败时,它主动告诉调度器:「嘿,我阻塞在我这把 mutex 上了,owner 是张三,帮我找张三去跑!」


5.1 Mutex 与代理执行

5.1.1 数据结构回顾

Mutex 内部用 atomic_long_t owner 存储锁持有者,低 3 位是标志位:

标志位
含义
MUTEX_FLAG_WAITERS
 (0x01)
有任务在等待队列上
MUTEX_FLAG_HANDOFF
 (0x02)
需要将锁转交给等待者
MUTEX_FLAG_PICKUP
 (0x04)
HANDOFF 已做,等待等待者来取锁
// 文件: kernel/locking/mutex.h// 通过掩码 ~MUTEX_FLAGS 从 atomic_long 中提取出 task_struct 指针static inline struct task_struct *__mutex_owner(struct mutex *lock){    if (!lock)        return NULL;    return (struct task_struct *)(atomic_long_read(&lock->owner) & ~MUTEX_FLAGS);}

5.1.2 Mutex Lock 路径:如何通知调度器

当高优先级任务 H 尝试获取 mutex 而失败时,__mutex_lock_common() 慢路径被调用。以下是关键代码流程(kernel/locking/mutex.c):

mutex_lock(lock)    │    ├► 快速路径: __mutex_trylock_fast(lock) → 成功则返回    │    └► 慢速路径: __mutex_lock_slowpath(lock)         → __mutex_lock_common(lock, ...)              │              ├► 乐观自旋: mutex_optimistic_spin()              │    在释放 CPU 前先自旋等一会(万一 owner 很快释放呢)              │              ├► 获取 wait_lock 自旋锁              │              ├► 将自己加入 wait_list 等待队列              │              ├► ★★★ 关键步骤 ★★★              │    raw_spin_lock(&current->blocked_lock);              │    __set_task_blocked_on(current, lock, BO_T_MUTEX);              │    set_current_state(TASK_UNINTERRUPTIBLE);              │    ↑              │    |-- 告诉调度器: "我现在阻塞在 lock 这个 mutex 上"              │    |   类型是 BO_T_MUTEX              │    |   blocked_lock 保护这个信息不被并发访问破坏              │              ├► 等待循环:              │    for (;;) {              │        if (__mutex_trylock(lock))  // 尝试抢锁              │            break;              │              │        释放 blocked_lock              │        释放 wait_lock              │              │        schedule_preempt_disabled();  // ★ 让出CPU给调度器              │        // 调度器此时通过 find_proxy_task()              │        // 发现 H 的 blocked_on → 该mutex → owner L              │        // 然后让 L 去跑!              │              │        重新获取锁:              │        raw_spin_lock(&wait_lock);              │        raw_spin_lock(&current->blocked_lock);              │        __set_task_blocked_on(current, lock, BO_T_MUTEX);              │        // ↑ 重新设置 blocked_on (可能被清过)              │              │        if (__mutex_trylock_or_handoff(lock, first))              │            break;              │              │        // 如果是第一个等待者,可以乐观自旋              │        if (first) {              │            __clear_task_blocked_on(current, lock);              │            // ↑ 暂时清除 blocked_on,不让调度器误判我们不可选              │            opt = mutex_optimistic_spin(lock, &waiter);              │            __set_task_blocked_on(current, lock, BO_T_MUTEX);              │            // ↑ 自旋完了重新设置              │        }              │    }              │              └► 获取到锁:                   __clear_task_blocked_on(current, lock);  // ★ 清除 blocked_on                   __set_current_state(TASK_RUNNING);

5.1.3 Mutex Unlock 路径:「谁来接手这把锁?」

这是代理执行最精妙的部分。释放锁时,mutex 不再简单地唤醒等待队列的第一个人,而是先看 「调度器选了谁作为最高优先级的等待者」kernel/locking/mutex.c):

mutex_unlock(lock)    │    ├► 快速路径: __mutex_unlock_fast(lock)    │    没有等待者 → 直接清零 owner → 返回    │    └► 慢速路径: __mutex_unlock_slowpath(lock)         │         ├► ★ 步骤1: 判断是否需要 HANDOFF         │    for (;;) {         │        if (sched_proxy_exec() && current->blocked_donor) {         │            // ★ 关键:如果当前任务有 blocked_donor         │            // (即: 有一个高优先任务正在替我们「导航」)         │            // 强制进入 HANDOFF 流程         │            owner = MUTEX_FLAG_HANDOFF;         │            break;         │        }         │        if (owner & MUTEX_FLAG_HANDOFF) break;         │        // 尝试原子释放...         │    }         │         ├► 获取 wait_lock 和 blocked_lock         │         ├► ★ 步骤2: 优先唤醒 blocked_donor (代理执行核心!)         │    if (sched_proxy_exec()) {         │        raw_spin_lock(&current->blocked_lock);         │         │        donor = current->blocked_donor;         │        // donor 就是那个「替我们导航」的高优先级任务         │         │        if (donor) {         │            // 检查 donor 确实是在等这把锁         │            next_lock = __get_task_blocked_on(donor);         │            if (next_lock == lock) {         │                // ★ 好!donor 确实等了这把锁,让它接手         │                next = donor;         │                __set_task_blocked_on_waking(donor, next_lock);         │                // ↑ 设置 PROXY_WAKING 标记         │                // donor 醒来时会先被送回它该去的CPU         │                wake_q_add(&wake_q, donor);         │                current->blocked_donor = NULL;         │                // ↑ 断开代理关系         │            }         │        }         │    }         │         │    // 如果没有 blocked_donor,才走传统等待队列         │    if (!next && !list_empty(&lock->wait_list)) {         │        waiter = list_first_entry(&lock->wait_list, ...);         │        next = waiter->task;         │        __set_task_blocked_on_waking(next, lock);         │        wake_q_add(&wake_q, next);         │    }         │         ├► 如果需要 HANDOFF,使用 __mutex_handoff() 原子转移 owner         │         └► raw_spin_unlock_irqrestore_wake(&lock->wait_lock, &wake_q);              // 批量唤醒 wake_q 中的任务

5.2 RWSEM 与代理执行

5.2.1 与 Mutex 的关键差异

RWSEM (读写信号量) 的代理执行集成比 mutex 简单,核心差异在于:

方面
Mutex
RWSEM
阻塞条件
总有明确的 task_struct owner
仅当 writer 持有时
有明确 owner
读者阻塞
-
读者间可并发,不需代理执行
blocked_on 设置时机
获取锁失败即设置
仅当 rwsem 被 writer 持有时设置
unlock 端
优先唤醒 blocked_donor
不优先唤醒 blocked_donor
HANDOFF 机制
有 PICKUP/HANDOFF 标志位
有独立 HANDOFF 标志位但无 PICKUP

RWSEM 只支持 writer owner 代理执行。 读者持有时没有明确的单一 owner,所以不触发代理执行。

5.2.2 Reader Lock 路径的代理执行

// 文件: kernel/locking/rwsem.c (read lock 等待循环)for (;;) {    // ... 检查 wakeup ...    if (atomic_long_read(&sem->count) & RWSEM_WRITER_MASK) {        // ★ 只有当 rwsem 被 writer 持有时才设置 blocked_on        raw_spin_lock_irq(&current->blocked_lock);        __set_task_blocked_on(current, sem, BO_T_RWSEM);        raw_spin_unlock_irq(&current->blocked_lock);        blocked_on_set = true;    }    schedule_preempt_disabled();  // 让调度器介入    // ...    if (blocked_on_set) {        clear_task_blocked_on(current, sem);        blocked_on_set = false;    }}

关键设计: 每次 schedule() 前检查 RWSEM_WRITER_MASK。如果 writer 已经释放了(count 中没有 writer bit),就不设 blocked_on。这保证了只有实际的 writer-owner 阻塞场景才触发代理执行,读者间的正常并发不受影响。

5.2.3 Writer Lock 路径的代理执行

// 文件: kernel/locking/rwsem.c (write lock 等待循环)if (atomic_long_read(&sem->count) & RWSEM_WRITER_MASK) {    raw_spin_lock_irq(&current->blocked_lock);    __set_task_blocked_on(current, sem, BO_T_RWSEM);    blocked_on_set = true;    raw_spin_unlock_irq(&current->blocked_lock);}schedule_preempt_disabled();set_current_state(state);if (blocked_on_set) {    clear_task_blocked_on(current, sem);    blocked_on_set = false;}

Writer 和 reader 的逻辑一致——schedule() 前设置 blocked_on,醒来后清除。

5.2.4 Owner 解析:rwsem_writer_owner()

// 文件: kernel/locking/rwsem.cstruct task_struct *rwsem_writer_owner(struct rw_semaphore *sem){    struct task_struct *owner;    long count, flags;    count = atomic_long_read(&sem->count);    owner = rwsem_owner_flags(sem, &flags);    if (!(count & RWSEM_WRITER_MASK) || (flags & (RWSEM_READER_OWNED |        RWSEM_NONSPINNABLE)))        return NULL;    return owner;}

三个拒绝条件:

  1. RWSEM_WRITER_MASK
     未设置 → 没有 writer,返回 NULL
  2. RWSEM_READER_OWNED
     已设置 → 是读者持有,返回 NULL
  3. RWSEM_NONSPINNABLE
     已设置 → 不可自旋的读者持有,返回 NULL

当 __blocked_on_owner() 被 find_proxy_task() 调用时,如果返回 NULL,说明 owner 不存在/不是 writer,则触发 action = NEEDS_RETURN——把等待者送回它自己的 CPU。


六、总结

代理执行的本质

代理执行把「调度器选谁」和「CPU 上谁在跑」这两个概念解耦。当一个高优先级任务因锁而阻塞时,调度器让锁持有者「代它跑」,从而消除优先级反转的根本原因——不是提升持有者的优先级,而是直接让持有者以等待者的调度身份去执行。

关键数据流

高优先级任务 H 阻塞在 mutex 上        ↓    H->blocked_on = { mutex, BO_T_MUTEX }        ↓__schedule() → pick_next_task() → 选中 H(因为它优先级高)        ↓task_is_blocked(H) == true        ↓find_proxy_task(H):    H->blocked_on → mutex → owner = L(锁持有者)        ↓    L 就是执行上下文(curr)        ↓    H = donor(调度上下文),L = curr(执行上下文)        ↓    L 运行、释放锁 → wake H        ↓    H 拿回自己的调度上下文,正常调度

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-02 23:30:21 HTTP/2.0 GET : https://f.mffb.com.cn/a/497716.html
  2. 运行时间 : 0.823094s [ 吞吐率:1.21req/s ] 内存消耗:5,012.30kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=935bc2e8eb5bb0fef40648729073a7cd
  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.000629s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000841s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.003607s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.005268s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000543s ]
  6. SELECT * FROM `set` [ RunTime:0.018400s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000903s ]
  8. SELECT * FROM `article` WHERE `id` = 497716 LIMIT 1 [ RunTime:0.088746s ]
  9. UPDATE `article` SET `lasttime` = 1783006221 WHERE `id` = 497716 [ RunTime:0.007824s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.009092s ]
  11. SELECT * FROM `article` WHERE `id` < 497716 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.084844s ]
  12. SELECT * FROM `article` WHERE `id` > 497716 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.040496s ]
  13. SELECT * FROM `article` WHERE `id` < 497716 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.108129s ]
  14. SELECT * FROM `article` WHERE `id` < 497716 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.217519s ]
  15. SELECT * FROM `article` WHERE `id` < 497716 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.160321s ]
0.824695s