当前位置:首页>Linux>Linux Tasklet 深度剖析: 从设计思想到底层实现

Linux Tasklet 深度剖析: 从设计思想到底层实现

  • 2026-02-08 06:57:01
Linux Tasklet 深度剖析: 从设计思想到底层实现

Linux Tasklet 深度剖析: 从设计思想到底层实现

1. 引言: 为什么需要 Tasklet?

在深入技术细节之前, 让我们先思考一个根本问题: 为什么 Linux 内核需要 tasklet 这样的机制?

想象一下这样的场景: 你正在厨房做饭 (CPU 在执行主要任务) , 突然门铃响了 (硬件中断) . 你去开门并接收快递 (中断处理) , 但快递需要拆箱、整理物品 (耗时操作) . 明智的做法是先签收快递 (快速响应中断) , 然后回到厨房继续做饭, 等有空时再处理拆箱 (延迟处理耗时部分)

这个 "等有空时再处理" 的哲学, 正是 Linux 中断处理的核心思想. Linux 将中断处理分为两部分:

部分
名称
特点
类比
上半部
Top Half
紧急、快速、不可中断
快递签收
下半部
Bottom Half
延迟、可中断、较耗时
快递拆箱整理

Tasklet 正是众多 "下半部" 实现机制中的一种. 让我们通过一个Mermaid时序图来直观理解:

2. Tasklet 的设计哲学

2.1 核心设计原则

Tasklet 的设计体现了几个关键原则:

  1. 1. 串行化执行: 同一 tasklet 在多个 CPU 上不会并发执行
  2. 2. 原子性调度: tasklet 的调度是原子的, 避免竞争条件
  3. 3. 轻量级: 相比内核线程, tasklet 的开销极小
  4. 4. 确定性和可靠性: 设计简单, 行为可预测

2.2 与其他下半部机制的对比

理解 tasklet 最好的方式之一就是将其与其他机制对比:

表格形式对比更加清晰:

特性
软中断 (Softirq)
Tasklet
工作队列 (Workqueue)
线程化中断
执行上下文
中断上下文
中断上下文
进程上下文
进程上下文
可睡眠
并发性
完全并行
同类型串行
取决于实现
线程调度
性能开销
最低
很低
较高
最高
使用难度
困难
简单
中等
简单
适用场景
网络、块设备等高性能需求
通用设备驱动
需要睡眠的操作
实时性要求不高的驱动

3. Tasklet 的核心数据结构

3.1 基础结构体

让我们深入内核源码, 看看 tasklet 是如何定义的:

/* 位于 include/linux/interrupt.h */

struct tasklet_struct {

struct tasklet_struct *next;
      // 链表指针
    unsigned
 long state;              // 状态标志
    atomic_t
 count;                   // 引用计数器
    void
 (*func)(unsigned long);      // 实际的处理函数
    unsigned
 long data;               // 传递给函数的参数
};

这个看似简单的结构体, 却包含了 tasklet 的全部奥秘. 让我们逐一分析每个字段:

字段
类型
描述
nextstruct tasklet_struct *
指向下一个 tasklet, 用于链表管理
stateunsigned long
状态标志, 控制 tasklet 生命周期
countatomic_t
原子计数器, 为0时tasklet才可执行
funcvoid (*)(unsigned long)
实际要执行的回调函数
dataunsigned long
传递给回调函数的参数

3.2 状态标志详解

state 字段是理解 tasklet 行为的关键. 它使用位掩码表示不同的状态:

/* tasklet 状态标志 */
enum {

    TASKLET_STATE_SCHED,   /* Tasklet 已被调度, 等待执行 */
    TASKLET_STATE_RUN,     /* Tasklet 正在执行中 */
    TASKLET_STATE_PENDING  /* 已废弃, 旧版内核使用 */
};

我们可以通过一个状态转换图来理解 tasklet 的生命周期:

3.3 每个CPU的数据结构

Tasklet 的实现依赖于每个CPU的数据结构. 这是实现高效并行处理的关键:

/* 每个CPU的tasklet链表 */
struct tasklet_head {

struct tasklet_struct *head;

struct tasklet_struct **tail;

};

/* 每个CPU有两个tasklet链表 */

static
 DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
static
 DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);

这里有一个重要的设计细节: 两个优先级tasklet_vec 是普通优先级, tasklet_hi_vec 是高优先级. 这种设计允许紧急的 tasklet 优先执行

4. Tasklet 的实现机制深度解析

4.1 调度过程: tasklet_schedule()

让我们从调度开始, 理解 tasklet 的生命周期:

void tasklet_schedule(struct tasklet_struct *t)
{
    /* 1. 检查tasklet是否已被调度 */

    if
 (test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
        return
; /* 已经在调度队列中, 直接返回 */

    /* 2. 添加到当前CPU的链表中 */

    __tasklet_schedule(t);
}
EXPORT_SYMBOL(tasklet_schedule);

实际的调度函数 __tasklet_schedule() 更加精彩:

void __tasklet_schedule(struct tasklet_struct *t)
{
    unsigned
 long flags;

    /* 获取当前CPU的ID */

    local_irq_save(flags);  /* 保存中断状态并禁用本地中断 */

    /* 将tasklet添加到当前CPU的链表中 */

    t->next = NULL;
    *__this_cpu_read(tasklet_vec.tail) = t;
    __this_cpu_write(tasklet_vec.tail, &(t->next));

    /* 触发软中断 */

    raise_softirq_irqoff(TASKLET_SOFTIRQ);

    local_irq_restore(flags);  /* 恢复中断状态 */
}

这个过程可以用一个流程图清晰地表示:

4.2 执行过程: tasklet_action()

当软中断被触发后, 最终会调用 tasklet_action() 来执行 tasklet:

static __latent_entropy void tasklet_action(struct softirq_action *a)
{
struct tasklet_struct *list;


    /* 1. 禁用本地中断并获取当前CPU的tasklet链表 */

    local_irq_disable();
    list
 = __this_cpu_read(tasklet_vec.head);
    __this_cpu_write(tasklet_vec.head, NULL);
    __this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&empty_tasklet_vec.head));
    local_irq_enable();

    /* 2. 遍历链表执行所有tasklet */

    while
 (list) {
struct tasklet_struct *t =
 list;
        list
 = list->next;

        /* 3. 检查tasklet是否可执行 (count == 0)  */

        if
 (tasklet_trylock(t)) {
            /* 4. 确保它仍被调度 (可能被tasklet_kill取消)  */

            if
 (!atomic_read(&t->count)) {
                /* 5. 清除调度状态 */

                clear_bit(TASKLET_STATE_SCHED, &t->state);

                /* 6. 设置运行状态并执行 */

                set_bit(TASKLET_STATE_RUN, &t->state);

                /* 执行用户提供的处理函数 */

                t->func(t->data);

                /* 7. 清除运行状态 */

                clear_bit(TASKLET_STATE_RUN, &t->state);
            }
            tasklet_unlock(t);
        }

        /* 8. 重新检查链表, 处理新添加的tasklet */

        local_irq_disable();
        t->next = NULL;
        *__this_cpu_read(tasklet_vec.tail) = t;
        __this_cpu_write(tasklet_vec.tail, &(t->next));
        list
 = __this_cpu_read(tasklet_vec.head);
        if
 (!list)
            __this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&empty_tasklet_vec.head));
        __this_cpu_write(tasklet_vec.head, NULL);
        local_irq_enable();
    }
}

这个执行过程相当精巧, 有几个关键点需要注意:

  1. 1. 原子性操作: 使用 local_irq_disable/enable() 保护关键区域
  2. 2. 锁机制tasklet_trylock() 确保同一 tasklet 不会在多个CPU上并发执行
  3. 3. 重入处理: 在执行过程中可能新的 tasklet 被调度, 因此需要重新检查链表

4.3 禁止和启用: tasklet_disable() 和 tasklet_enable()

Tasklet 提供了简单的启用/禁用机制, 这是通过原子计数器实现的:

void tasklet_disable(struct tasklet_struct *t)
{
    /* 原子增加计数器 */

    atomic_inc
(&t->count);

    /*
     * 同步屏障: 确保在计数器增加后, 
     * 任何正在运行的tasklet都能看到这个变化
     */

    smp_mb__after_atomic();

    /*
     * 等待正在运行的tasklet完成
     * 这是一个忙等待, 但通常很快
     */

    while
 (test_bit(TASKLET_STATE_RUN, &(t->state)))
        cpu_relax();
}

void
 tasklet_enable(struct tasklet_struct *t)
{
    /*
     * 同步屏障: 确保在计数器减少前, 
     * 所有内存操作都已完成
     */

    smp_mb__before_atomic();

    /* 原子减少计数器 */

    atomic_dec
(&t->count);
}

这种设计的巧妙之处在于:

  • • 禁用时: 增加计数器并等待当前执行完成
  • • 启用时: 只需减少计数器, 不需要等待
  • • 执行时: 只有在 count == 0 时才会执行

4.4 整体架构图解

现在让我们用 Mermaid 图来展示 tasklet 的整体架构:

5. Tasklet 的典型使用场景和实例

5.1 何时使用 Tasklet?

Tasklet 特别适合以下场景:

  1. 1. 中断处理的后半部分: 当上半部需要快速返回时
  2. 2. 中小型数据处理: 数据量不大但需要及时处理的情况
  3. 3. 设备驱动中的异步操作: 如完成 DMA 后的数据处理
  4. 4. 定时器回调: 某些需要快速执行的定时任务

5.2 一个简单的字符设备驱动示例

让我们通过一个具体的例子来理解 tasklet 的用法. 假设我们有一个虚拟的字符设备, 当数据到达时触发中断, 我们使用 tasklet 来处理这些数据:

#include <linux/module.h>
#include <linux/init.h>

#include <linux/interrupt.h>

#include <linux/fs.h>

#include <linux/cdev.h>

#include <linux/uaccess.h>


/* 定义我们的设备结构 */

struct my_device {

struct cdev cdev;

    dev_t
 devno;
struct tasklet_struct my_tasklet;

    char
 buffer[256];
    int
 data_ready;
};

static
struct my_device my_dev;

/* Tasklet 处理函数 */

static
 void my_tasklet_handler(unsigned long data)
{
struct my_device *dev =
 (struct my_device *)data;

    printk(KERN_INFO "Tasklet 执行: 处理缓冲区数据\n");

    /* 这里应该处理设备数据 */

    /* 例如: 解析数据、唤醒等待进程等 */


    /* 标记数据已处理 */

    dev->data_ready = 0;
}

/* 模拟的中断处理程序 */

static
 irqreturn_t my_interrupt_handler(int irq, void *dev_id)
{
struct my_device *dev =
 (struct my_device *)dev_id;

    printk(KERN_INFO "中断上半部: 接收数据\n");

    /* 模拟从硬件读取数据 */

    snprintf
(dev->buffer, sizeof(dev->buffer),
             "数据来自中断, 时间戳: %lld"
, ktime_get_ns());
    dev->data_ready = 1;

    /* 调度 tasklet 进行后续处理 */

    tasklet_schedule(&dev->my_tasklet);

    return
 IRQ_HANDLED;
}

/* 文件操作: 读取函数 */

static
 ssize_t my_read(struct file *filp, char __user *buf,
                       size_t
 count, loff_t *f_pos)

{
struct my_device *dev =
 filp->private_data;
    int
 ret;

    /* 等待数据就绪 */

    while
 (!dev->data_ready) {
        if
 (filp->f_flags & O_NONBLOCK)
            return
 -EAGAIN;
        /* 在实际驱动中, 这里应该使用等待队列 */

        msleep(10);
    }

    /* 将数据复制到用户空间 */

    if
 (count > sizeof(dev->buffer))
        count = sizeof(dev->buffer);

    ret = copy_to_user(buf, dev->buffer, count);
    if
 (ret)
        return
 -EFAULT;

    dev->data_ready = 0;

    return
 count;
}

static
 conststruct file_operations my_fops = {
    .owner = THIS_MODULE,
    .read = my_read,
};

/* 模块初始化 */

static
 int __init my_module_init(void)
{
    int
 ret;

    printk(KERN_INFO "初始化 Tasklet 示例模块\n");

    /* 初始化 tasklet */

    tasklet_init(&my_dev.my_tasklet, my_tasklet_handler, 
                 (unsigned long)&my_dev);

    /* 分配设备号 */

    ret = alloc_chrdev_region(&my_dev.devno, 0, 1, "my_tasklet_dev");
    if
 (ret < 0) {
        printk(KERN_ERR "无法分配设备号\n");
        return
 ret;
    }

    /* 初始化字符设备 */

    cdev_init(&my_dev.cdev, &my_fops);
    my_dev.cdev.owner = THIS_MODULE;

    ret = cdev_add(&my_dev.cdev, my_dev.devno, 1);
    if
 (ret < 0) {
        printk(KERN_ERR "无法添加字符设备\n");
        unregister_chrdev_region(my_dev.devno, 1);
        return
 ret;
    }

    /* 注册中断处理程序 (这里使用虚拟中断号)  */

    ret = request_irq(100, my_interrupt_handler, 0,
                      "my_tasklet_irq"
, &my_dev);
    if
 (ret < 0) {
        printk(KERN_ERR "无法注册中断\n");
        cdev_del(&my_dev.cdev);
        unregister_chrdev_region(my_dev.devno, 1);
        return
 ret;
    }

    printk(KERN_INFO "模块初始化完成\n");
    return
 0;
}

/* 模块清理 */

static
 void __exit my_module_exit(void)
{
    /* 禁用 tasklet */

    tasklet_disable(&my_dev.my_tasklet);

    /* 等待 tasklet 完成 */

    tasklet_kill(&my_dev.my_tasklet);

    /* 释放中断 */

    free_irq(100, &my_dev);

    /* 删除字符设备 */

    cdev_del(&my_dev.cdev);
    unregister_chrdev_region(my_dev.devno, 1);

    printk(KERN_INFO "模块卸载完成\n");
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Kernel Expert");
MODULE_DESCRIPTION("Tasklet 使用示例");

5.3 执行流程分析

这个示例展示了典型的 tasklet 使用模式:

  1. 1. 中断到来my_interrupt_handler 被调用
  2. 2. 快速处理: 保存必要数据, 调度 tasklet
  3. 3. tasklet 调度tasklet_schedule 将 tasklet 加入队列
  4. 4. 异步执行: 在软中断上下文中执行 my_tasklet_handler
  5. 5. 完整处理: tasklet 处理耗时的数据操作

6. Tasklet 的高级主题和内部细节

6.1 锁机制和并发控制

Tasklet 的并发控制是其设计的精髓之一. 让我们深入理解其中的锁机制:

/* tasklet_trylock 的实现 */
static
 inline int tasklet_trylock(struct tasklet_struct *t)
{
    return
 !test_and_set_bit(TASKLET_STATE_RUN, &t->state);
}

/* tasklet_unlock 的实现 */

static
 inline void tasklet_unlock(struct tasklet_struct *t)
{
    smp_mb__before_atomic();
    clear_bit(TASKLET_STATE_RUN, &t->state);
}

关键点:

  • • test_and_set_bit: 原子操作, 同时测试和设置位
  • • 内存屏障: 确保操作的顺序性
  • • 自旋锁风格: 但不会真正自旋, 只是检查

6.2 Tasklet 的优先级系统

Linux 提供了两种优先级的 tasklet:

/* 高优先级 tasklet 的调度 */
void
 tasklet_hi_schedule(struct tasklet_struct *t)
{
    /* 实现与 tasklet_schedule 类似, 但使用高优先级链表 */

}

/* 高优先级 tasklet 的处理 */

static
 void tasklet_hi_action(struct softirq_action *a)
{
    /* 与 tasklet_action 类似, 但处理高优先级链表 */

}

优先级差异体现在软中断的编号上:

软中断类型
软中断编号
优先级
用途
HI_SOFTIRQ
0
最高
高优先级 tasklet
TIMER_SOFTIRQ
1
定时器
NET_TX_SOFTIRQ
2
网络发送
NET_RX_SOFTIRQ
3
网络接收
BLOCK_SOFTIRQ
4
块设备
IRQ_POLL_SOFTIRQ
5
IRQ 轮询
TASKLET_SOFTIRQ
6
普通 tasklet
SCHED_SOFTIRQ
7
调度器
HRTIMER_SOFTIRQ
8
高精度定时器
RCU_SOFTIRQ
9
最低
RCU回调

6.3 与其他机制的交互

Tasklet 不是孤立的, 它与内核的其他部分密切交互:

7. Tasklet 的调试和性能分析

7.1 调试工具和技术

调试 tasklet 问题需要专门的工具和技术:

7.1.1 Proc 文件系统接口

# 查看软中断统计信息
cat
 /proc/softirqs

输出示例:

                    CPU0       CPU1       CPU2       CPU3       
          HI:          5          2          3          1
       TIMER:     123456     123450     123445     123440
      NET_TX:        100         95         90         85
      NET_RX:       1000        995        990        985
       BLOCK:         50         45         40         35
    IRQ_POLL:          0          0          0          0
     TASKLET:        200        195        190        185
       SCHED:       5000       4995       4990       4985
     HRTIMER:         10          8          6          4
         RCU:      30000      29995      29990      29985

7.1.2 Ftrace 跟踪

# 启用 tasklet 跟踪
echo
 1 > /sys/kernel/debug/tracing/events/irq/tasklet_entry/enable
echo
 1 > /sys/kernel/debug/tracing/events/irq/tasklet_exit/enable

# 查看跟踪结果

cat
 /sys/kernel/debug/tracing/trace

7.1.3 动态打印调试

在驱动代码中添加调试信息:

#include <linux/dynamic_debug.h>

/* 控制动态打印 */

static
 void debug_tasklet(struct tasklet_struct *t, const char *action)
{
    pr_debug("Tasklet %ps %s on CPU %d, state: 0x%lx, count: %d\n",
             t->func, action, smp_processor_id(), t->state,
             atomic_read
(&t->count));
}

/* 在调度时调用 */

debug_tasklet(t, "scheduled");

7.2 常见问题和解决方案

问题现象
可能原因
解决方案
系统延迟增加
Tasklet 处理时间过长
1. 优化处理函数
2. 考虑使用工作队列
死锁
Tasklet 中使用了可能睡眠的函数
1. 检查所有函数调用
2. 使用工作队列替代
数据竞争
共享数据未正确保护
1. 使用原子操作
2. 使用自旋锁保护
Tasklet 不执行count
 不为零或未调度
1. 检查 tasklet_disable/enable 调用
2. 确认调度函数被调用
CPU 使用率过高
Tasklet 过于频繁调度
1. 合并处理请求
2. 增加调度延迟

7.3 性能优化技巧

  1. 1. 批量处理: 合并多个小任务为一个大任务
  2. 2. 延迟调度: 使用 tasklet_hi_schedule 提高优先级
  3. 3. CPU 亲和性: 绑定 tasklet 到特定 CPU
  4. 4. 监控统计: 使用 /proc/softirqs 监控性能

8. 实战案例分析: 网络驱动中的 Tasklet

让我们分析一个真实世界的例子: Linux 网络驱动中 tasklet 的使用

/* 简化版的网络驱动 tasklet 处理 */
struct nic_private {

struct net_device *dev;

struct tasklet_struct tx_tasklet;

struct tasklet_struct rx_tasklet;

struct sk_buff_head tx_queue;

struct sk_buff_head rx_queue;

};

/* 发送 tasklet 处理函数 */

static
 void tx_tasklet_handler(unsigned long data)
{
struct nic_private *priv =
 (struct nic_private *)data;
struct sk_buff *skb;


    /* 处理所有待发送的数据包 */

    while
 ((skb = skb_dequeue(&priv->tx_queue))) {
        if
 (nic_send_packet(priv, skb) < 0) {
            /* 发送失败, 重新排队 */

            skb_queue_head(&priv->tx_queue, skb);
            break
;
        }
        dev_kfree_skb(skb);
    }
}

/* 接收 tasklet 处理函数 */

static
 void rx_tasklet_handler(unsigned long data)
{
struct nic_private *priv =
 (struct nic_private *)data;
struct sk_buff *skb;


    /* 处理所有接收到的数据包 */

    while
 ((skb = skb_dequeue(&priv->rx_queue))) {
        /* 传递给网络协议栈 */

        netif_receive_skb(skb);
    }
}

/* 中断处理程序 */

static
 irqreturn_t nic_interrupt(int irq, void *dev_id)
{
struct nic_private *priv =
 dev_id;
    u32 status;

    /* 读取中断状态 */

    status = nic_read_status(priv);

    if
 (status & TX_COMPLETE) {
        /* 调度发送 tasklet */

        tasklet_schedule(&priv->tx_tasklet);
    }

    if
 (status & RX_READY) {
        /* 调度接收 tasklet */

        tasklet_hi_schedule(&priv->rx_tasklet); /* 使用高优先级 */
    }

    return
 IRQ_HANDLED;
}

这个例子展示了 tasklet 在网络驱动中的典型应用模式:

  1. 1. 中断处理尽可能快: 只读取状态和调度 tasklet
  2. 2. 批量处理: tasklet 处理队列中的所有数据包
  3. 3. 优先级区分: 接收使用高优先级, 发送使用普通优先级

9. 总结和最佳实践

9.1 Tasklet 的核心要点总结

让我们用一张表格总结 tasklet 的关键特性:

特性类别
具体内容
设计目标
快速中断处理的延迟部分
执行上下文
软中断/中断上下文
调度方式
每个CPU的链表, 原子操作
并发特性
同类型tasklet串行执行
同步原语
原子计数器和状态位
优先级
普通和高优先级两种
生命周期
调度 -> 执行 -> 完成
调试支持
proc接口、tracepoint、动态调试

9.2 最佳实践指南

根据多年的内核开发经验, 我总结了以下最佳实践:

  1. 1. 何时使用 Tasklet:
    • • 处理时间在微秒级别
    • • 不需要睡眠
    • • 需要低延迟响应
    • • 数据量适中
  2. 2. 何时避免 Tasklet:
    • • 处理时间超过100微秒
    • • 需要调用可能睡眠的函数
    • • 需要复杂的同步机制
    • • 实时性要求不高
  3. 3. 性能优化建议
    /* 不好的做法: 频繁调度小任务 */
    for
     (i = 0; i < 100; i++) {
        tasklet_schedule(&small_task);
    }

    /* 好的做法: 批量处理 */

    void
     process_batch(unsigned long data) {
        for
     (i = 0; i < 100; i++) {
            process_item(i);
        }
    }
  4. 4. 错误处理建议
    /* 总是检查tasklet状态 */
    if
     (!test_bit(TASKLET_STATE_SCHED, &t->state)) {
        /* 安全地调度 */

        tasklet_schedule(t);
    }

    /* 在模块退出时正确清理 */

    static
     void __exit my_exit(void) {
        tasklet_disable(&my_tasklet);
        tasklet_kill(&my_tasklet);  /* 等待完成 */
        /* 其他清理工作 */

    }

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-08 09:19:25 HTTP/2.0 GET : https://f.mffb.com.cn/a/464625.html
  2. 运行时间 : 0.086440s [ 吞吐率:11.57req/s ] 内存消耗:4,486.39kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=bbf6f09a1c89306400a46fe1492586ed
  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.000527s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000587s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000648s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000289s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000473s ]
  6. SELECT * FROM `set` [ RunTime:0.000204s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000524s ]
  8. SELECT * FROM `article` WHERE `id` = 464625 LIMIT 1 [ RunTime:0.002104s ]
  9. UPDATE `article` SET `lasttime` = 1770513566 WHERE `id` = 464625 [ RunTime:0.005328s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.002885s ]
  11. SELECT * FROM `article` WHERE `id` < 464625 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000427s ]
  12. SELECT * FROM `article` WHERE `id` > 464625 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000541s ]
  13. SELECT * FROM `article` WHERE `id` < 464625 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000779s ]
  14. SELECT * FROM `article` WHERE `id` < 464625 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000766s ]
  15. SELECT * FROM `article` WHERE `id` < 464625 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.005171s ]
0.088102s