当前位置:首页>Linux>Linux中断处理-request_irq与顶半部底半部

Linux中断处理-request_irq与顶半部底半部

  • 2026-07-06 16:49:54
Linux中断处理-request_irq与顶半部底半部

上一篇我们用输入子系统 + 定时器轮询实现了一个 GPIO 按键驱动。evtest 能看到按键事件了,但你知道它的代价吗?——每 20ms 一次定时器中断,CPU 每秒要醒 50 次去读一个可能根本没按的 GPIO。 一款手机如果有 10 个这样的轮询驱动,光"空转"就能吃掉不少电量。今天,我们用 Linux 中断框架 把按键驱动改成中断驱动——按键不按,CPU 完全不理;按键一按,硬件通知 CPU,驱动立刻响应。


unsetunset一、轮询 vs 中断:一张图说明白unsetunset

中断的本质:由硬件主动通知 CPU,而不是 CPU 反复去问硬件。

在 Linux 驱动开发中,理解中断处理是绕不开的核心技能。下文从最简单的 request_irq 开始,逐步展开顶半部/底半部的设计原理,最后改写出中断版按键驱动。


unsetunset二、基础:gpio_to_irq + request_irqunsetunset

2.1 从 GPIO 编号获取中断号

#include<linux/interrupt.h>#include<linux/gpio.h>int irq;/* 第一步:GPIO 编号 → IRQ 编号 */irq = gpio_to_irq(gpio);if (irq < 0) {    pr_err("gpio_to_irq failed\n");return irq;}

每个 GPIO 控制器内部都连接着一根中断线。gpio_to_irq 做的事情就是查表——GPIO0_C0 对应的硬件中断号是多少。这个号是芯片原厂的 GPIO 驱动(如 pinctrl-rockchip.c)在初始化时注册的,你不需要知道它具体是几。

2.2 注册中断处理函数

#include<linux/interrupt.h>irqreturn_tmy_irq_handler(int irq, void *dev_id){    pr_info("key pressed! irq=%d\n", irq);return IRQ_HANDLED;    /* 告诉内核:中断已处理 */}/* 在 probe 中注册 */ret = request_irq(irq,                    /* 中断号 */                  my_irq_handler,         /* 中断处理函数 */                  IRQF_TRIGGER_FALLING,   /* 触发方式:下降沿 */"gpio_key",             /* 名称(出现在 /proc/interrupts) */                  dev);                   /* 传给处理函数的 dev_id */if (ret) {    pr_err("request_irq failed, ret=%d\n", ret);return ret;}

四个关键参数:

参数
含义
我们填什么
irq
中断号
gpio_to_irq(gpio)
 的返回值
handler
中断处理函数
my_irq_handler
flags
触发条件
IRQF_TRIGGER_FALLING
 / RISING / HIGH / LOW
dev_id
传递给 handler 的私有指针
设备结构体指针

2.3 触发方式的四种选择

IRQF_TRIGGER_RISING   → 上升沿触发(低电平 → 高电平的瞬间)IRQF_TRIGGER_FALLING  → 下降沿触发(高电平 → 低电平的瞬间)IRQF_TRIGGER_HIGH     → 高电平触发(持续高电平期间反复触发)IRQF_TRIGGER_LOW      → 低电平触发(持续低电平期间反复触发)

按键用边沿触发(RISING 或 FALLING,不要用电平触发。如果用电平触发,按键按着不放时中断会反复触发,CPU 被中断轰炸。

如果你的 GPIO 是上升沿有效(按下 = 高电平),用 IRQF_TRIGGER_RISING;如果是下降沿有效,用 IRQF_TRIGGER_FALLING双边沿触发IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)可以同时捕获按下和释放。


unsetunset三、中断处理函数的铁律:不能休眠unsetunset

3.1 中断上下文是什么?

当 my_irq_handler 被调用时,代码运行在中断上下文(interrupt context)中。和进程上下文最大的区别:

进程上下文
中断上下文
能访问 current
✅ 有
❌ 没有(不关联任何进程)
能休眠(msleep/mutex_lock/copy_from_user
❌ 绝对不能
能调度(schedule()
被抢占
✅ 可以被其他进程抢占
❌ 不能被调度走

中断上下文不能休眠的原因很简单: 你在中断里休眠了,谁来唤醒你?中断没有关联进程,调度器没有办法把 CPU 给到“这个中断”继续执行。如果在中断上下文调了可能休眠的函数(如 mutex_lockcopy_from_user),启用了 CONFIG_DEBUG_ATOMIC_SLEEP 的内核会直接打印 WARNING 甚至触发 kernel panic。

3.2 中断处理函数里能干什么、不能干什么

irqreturn_tmy_irq_handler(int irq, void *dev_id){structgpio_key_dev *dev = dev_id;/* ✅ 能干的:操作寄存器、读 GPIO、设置标志位 */int level = gpio_get_value(dev->gpio);/* ✅ 能干的:操作自旋锁(spin_lock,但不能用 mutex) */    spin_lock(&dev->lock);/* ❌ 不能干的:调用可能休眠的函数 */// mutex_lock(&dev->mutex);           // ❌ mutex 会休眠// copy_from_user(buf, ...);          // ❌ 可能引发缺页异常// msleep(10);                         // ❌ 明显休眠// kmalloc(GFP_KERNEL);                // ❌ GFP_KERNEL 可能休眠/* ❌ 不能干的:耗时的复杂计算 */// 100ms 的浮点运算 ← 这会让所有其他中断排队等着,系统卡成狗    spin_unlock(&dev->lock);return IRQ_HANDLED;}

核心原则:中断处理函数要越快越好。 打个比方,中断处理函数就像餐厅接待员——你的工作是把客人领进门(记录中断发生),而不是进去亲自给客人做菜(处理业务逻辑)。复杂的事情交给"底半部"去做。


unsetunset四、顶半部与底半部:中断的"前台"和"后台"unsetunset

正是因为中断上下文不能做耗时操作,Linux 把中断处理分成了两半:

Linux 提供了三种实现底半部的机制:

机制
运行上下文
能否休眠
典型用途
复杂度
workqueue
内核线程(进程上下文)
✅ 能
复杂操作、调用可能休眠的函数
低(推荐)
tasklet
软中断上下文
❌ 不能
快速硬件后续处理
threaded irq
独立内核线程(进程上下文)
✅ 能
按键驱动首选
最低(推荐)

本文重点讲两种:request_threaded_irq(首选方案)和 workqueue(备选方案)。 tasklet 正在被内核社区逐步标记为过时——因为它在软中断上下文运行,不能休眠,而且一个 tasklet 只能在一个 CPU 上执行,不如 workqueue 灵活。


unsetunset五、方案一(推荐):request_threaded_irqunsetunset

request_threaded_irq 是 request_irq 的升级版:顶半部(hardirq handler)运行在中断上下文,底半部(threaded handler)运行在独立的内核线程中。

#include<linux/interrupt.h>/* * 顶半部:运行在中断上下文 * 返回值 IRQ_WAKE_THREAD 告诉内核"去叫底半部起来干活" */staticirqreturn_tgpio_key_hardirq(int irq, void *dev_id){/*     * 顶半部只做一件事:告诉内核"有按键事件要处理"。     * 实际的上报工作交给底半部。     */return IRQ_WAKE_THREAD;}/* * 底半部:运行在内核线程中,可以休眠 */staticirqreturn_tgpio_key_threaded(int irq, void *dev_id){structgpio_key_dev *dev = dev_id;int level;    level = gpio_get_value(dev->gpio);/*     * 在底半部里上报输入事件是完全安全的——     * 这里运行在进程上下文,input_event 内部可能做的     * 内存分配、锁操作都不会触发原子上下文警告。     */    input_report_key(dev->input, KEY_1, level);    input_sync(dev->input);return IRQ_HANDLED;}/* ============ probe 中注册 ============ */ret = request_threaded_irq(irq,                            gpio_key_hardirq,        /* 顶半部 */                            gpio_key_threaded,       /* 底半部 */                            IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,"gpio_key",                            dev);if (ret) {    pr_err("request_threaded_irq failed\n");return ret;}

常见用法:顶半部直接返回 IRQ_HANDLED

如果你的顶半部什么额外工作都不需要做(按键驱动就是这种情况),可以直接让顶半部返回 IRQ_HANDLED。但更推荐返回 IRQ_WAKE_THREAD 来显式表达"我有底半部要做"。

更简单的写法——顶半部留空:

/* * 如果你不需要单独在中断上下文中做任何事,顶半部可以直接返回 * IRQ_WAKE_THREAD。内核看到这个返回值会自动调用你的底半部。 *  * 甚至可以直接用 NULL 作为 hardirq handler——内核会把 * 默认的 primary handler 设置为只返回 IRQ_WAKE_THREAD。 */ret = request_threaded_irq(irq,NULL,                    /* 顶半部留空 */                            gpio_key_threaded,                            IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,"gpio_key",                            dev);

这种方式下,内核会自动处理硬件中断应答和底半部调度——你只需要写底半部


unsetunset六、方案二(了解即可):workqueueunsetunset

在 request_threaded_irq 出现之前(Linux 2.6.30 以前),workqueue 是底半部的事实标准:

#include<linux/workqueue.h>staticvoidgpio_key_work(struct work_struct *work){structgpio_key_dev *dev =container_of(workstructgpio_key_devwork);int level;    level = gpio_get_value(dev->gpio);    input_report_key(dev->input, KEY_1, level);    input_sync(dev->input);}staticirqreturn_tgpio_key_irq(int irq, void *dev_id){structgpio_key_dev *dev = dev_id;/*     * 中断上下文不能休眠,但可以调度 workqueue。     * schedule_work 把 work 放到系统工作队列,稍后由内核线程执行。     */    schedule_work(&dev->work);return IRQ_HANDLED;}/* probe 中初始化 */INIT_WORK(&dev->work, gpio_key_work);ret = request_irq(irq, gpio_key_irq,                   IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,"gpio_key", dev);

既然有了 request_threaded_irq,为什么还要知道 workqueue?

因为不是所有中断都用 threaded irq。有些驱动需要在多个地方调度同一个 work(比如定时器 + 中断都触发同一个 work),这时 workqueue 更灵活。但在按键驱动这种"一个中断 → 一个处理函数"的简单场景中,request_threaded_irq 是最优解。


unsetunset七、完整代码:中断版按键驱动unsetunset

把上一篇的轮询版改成中断版,改动集中在 probe 和 remove

#include<linux/module.h>#include<linux/platform_device.h>#include<linux/of_gpio.h>#include<linux/gpio.h>#include<linux/interrupt.h>#include<linux/input.h>structgpio_key_dev {int gpio;int irq;structinput_dev *input;};/* ============ 底半部:上报按键事件 ============ */staticirqreturn_tgpio_key_threaded(int irq, void *dev_id){structgpio_key_dev *dev = dev_id;int level;/*     * 读 GPIO 当前电平,上报按键事件。     * 注意:这里用的是双边沿触发,电平为 1 = 按下,0 = 释放。     * 如果你的硬件是低电平有效,把 level 取反即可。     */    level = gpio_get_value(dev->gpio);    input_report_key(dev->input, KEY_1, level);    input_sync(dev->input);return IRQ_HANDLED;}/* ============ probe ============ */staticintgpio_key_probe(struct platform_device *pdev){structgpio_key_dev *dev;unsignedlong irq_flags;int ret;    dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);if (!dev)return -ENOMEM;/* ---- 1. 获取 GPIO ---- */    dev->gpio = of_get_named_gpio(pdev->dev.of_node, "key-gpios"0);if (dev->gpio < 0) {        pr_err("gpio_key: failed to get key-gpios\n");return dev->gpio;    }    ret = gpio_request(dev->gpio, "key");if (ret)return ret;    gpio_direction_input(dev->gpio);/* ---- 2. GPIO → IRQ ---- */    dev->irq = gpio_to_irq(dev->gpio);if (dev->irq < 0) {        pr_err("gpio_key: gpio_to_irq failed\n");        ret = dev->irq;goto fail_gpio;    }/* ---- 3. 分配并初始化 input_dev ---- */    dev->input = devm_input_allocate_device(&pdev->dev);if (!dev->input) {        ret = -ENOMEM;goto fail_gpio;    }    dev->input->name = "gpio_key";    dev->input->phys = "gpio-keys/button0";    dev->input->id.bustype = BUS_HOST;    input_set_capability(dev->input, EV_KEY, KEY_1);    ret = input_register_device(dev->input);if (ret)goto fail_gpio;/* ---- 4. 注册中断(顶半部留空 + 底半部干活)---- *//*     * 设备树里如果指定了中断触发方式,gpio_to_irq 会自动填好。     * 这里显式用双边沿触发,同时捕获按下和释放。     */    irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;    ret = request_threaded_irq(dev->irq, NULL, gpio_key_threaded,                                irq_flags, "gpio_key", dev);if (ret) {        pr_err("gpio_key: request_threaded_irq failed, ret=%d\n", ret);goto fail_input;    }    platform_set_drvdata(pdev, dev);    pr_info("gpio_key: probed on irq=%d, /dev/input/eventX ready\n",            dev->irq);return 0;fail_input:    input_unregister_device(dev->input);fail_gpio:    gpio_free(dev->gpio);return ret;}/* ============ remove ============ */staticintgpio_key_remove(struct platform_device *pdev){structgpio_key_dev *dev = platform_get_drvdata(pdev);    free_irq(dev->irq, dev);               /* 注销中断 */    input_unregister_device(dev->input);   /* 注销输入设备 */    gpio_free(dev->gpio);return 0;}static const structof_device_idgpio_key_of_match[] = {    { .compatible = "qian,gpio-key" },    { }};MODULE_DEVICE_TABLE(of, gpio_key_of_match);static structplatform_drivergpio_key_driver = {    .driver = {        .name           = "gpio-key",        .of_match_table = gpio_key_of_match,    },    .probe  = gpio_key_probe,    .remove = gpio_key_remove,};module_platform_driver(gpio_key_driver);MODULE_LICENSE("GPL");MODULE_AUTHOR("qian");MODULE_DESCRIPTION("Interrupt-driven GPIO key via input subsystem");

对比轮询版:改了什么?

轮询版
中断版
驱动模式
timer_setup
 + mod_timer 每 20ms 一次
request_threaded_irq
按键检测
定时器回调里 gpio_get_value
硬件中断触发 + 底半部里 gpio_get_value
CPU 占用
每秒唤醒 50 次
按键不按 = CPU 零开销
响应延迟
0~20ms(取决于按键时机和定时器相位)
微秒级
(硬件中断延迟)

unsetunset八、按键去抖:中断版的老问题unsetunset

按键按下时,机械触点会"弹跳"——在几毫秒内反复通断:解决方案有两个:

方案一:硬件去抖 + 软件延迟(简单)

/* * gpiod_set_debounce 告诉 GPIO 控制器"电平稳定 X us 后才算有效"。 * 底层由 pinctrl 驱动实现(Rockchip 平台 A->5.10 已支持)。 * 注意:不是所有 GPIO 控制器都支持硬件去抖,不支持时返回 -ENOTSUPP。 */gpiod_set_debounce(gpio_to_desc(dev->gpio), 5000);  /* 5ms 去抖 */

简单省事,但依赖硬件支持。如果 GPIO 控制器不支持硬件去抖,需要方案二。

方案二:在底半部加延迟(软件去抖)

staticirqreturn_tgpio_key_threaded(int irq, void *dev_id){structgpio_key_dev *dev = dev_id;int level;/*     * 底半部运行在进程上下文,msleep 是允许的。     * 等 10ms 再读 GPIO——如果按键真的按下了,电平应该已经稳定。     */    msleep(10);    level = gpio_get_value(dev->gpio);    input_report_key(dev->input, KEY_1, level);    input_sync(dev->input);return IRQ_HANDLED;}

注意:这个 msleep 放在底半部里是合法的——因为 request_threaded_irq 的底半部运行在内核线程中(进程上下文)。如果放在顶半部里(中断上下文),msleep 会直接触发调度器断言失败。


unsetunset九、查看中断统计unsetunset

加载驱动后,可以通过 /proc/interrupts 确认中断是否正常注册和触发:

cat /proc/interrupts | grep gpio_key# 输出示例(每次按键按下,计数器 +1):#   CPU0    CPU1    CPU2    CPU3#   123:    5       0       0       0    gpio_key#     ^     ^#   irq号  触发次数

每次按下按键,右下角的计数器 +1。如果你的按键"按一下计数器加了 20 几"——说明按键抖动严重,需要加去抖。


unsetunset十、内核 gpio-keys 驱动的中断处理unsetunset

顺便看一下 gpio_keys.c 是怎么用 request_threaded_irq 的(简化版):

gpio_keys_probe()  └── 每个子节点       ├── devm_gpiod_get()           // 获取 GPIO 描述符       ├── gpiod_to_irq()             // GPIO → IRQ       ├── request_threaded_irq()       │     hardirq = gpio_keys_gpio_isr   // 顶半部:记录按键状态       │     threaded = gpio_keys_gpio_report_event  // 底半部:上报 + 去抖 + 长按       └── input_register_device()

和我们写的驱动几乎一样。 区别是 gpio-keys 的顶半部做了更复杂的时间戳记录和去抖逻辑,底半部支持自动重复和唤醒源管理。但架构一模一样——request_threaded_irq 顶半部 + 底半部。


unsetunset十一、Linux 4.19 / 5.10 / 6.1 版本差异unsetunset

中断子系统的核心 API 在三个版本中高度一致,但底半部机制有一些演进:

变化点
4.19
5.10
6.1
request_irq
✅ 支持
✅ 支持
✅ 支持
request_threaded_irq
✅ 支持(2.6.30+)
✅ 支持
✅ 支持
request_threaded_irq 顶半部为 NULL
✅ 自动使用默认 primary handler
✅ 同 4.19
✅ 同 4.19
gpiod_set_debounce
⚠️ 部分 GPIO 控制器不支持
✅ Rockchip 已支持
✅ 全面支持
gpio_to_irq
✅ 支持
✅ 支持
⚠️ 推荐 gpiod_to_irq
tasklet
✅ DECLARE_TASKLET(_name, _func)
✅ 标记过时
✅ DECLARE_TASKLET(_name, _callback) 新接口,tasklet_setup 替代 tasklet_init

本文代码在 4.19 / 5.10 / 6.1 上均可编译运行。 唯一需要注意的是:gpiod_set_debounce 在 4.19 的某些 GPIO 控制器(特别是通过 I2C/SPI 扩展的 GPIO)上可能返回 -ENOTSUPP,此时需要改用软件去抖方案(底半部 msleep 或定时器去抖)。Rockchip 主控的片上 GPIO 在 4.19 已支持硬件去抖。

关于 tasklet:5.10 时期社区曾计划用 threaded IRQ 完全替代 tasklet,但到了 6.1,tasklet 不但没有移除,反而完成了一次接口现代化重构——DECLARE_TASKLET 改为接受 callback(struct tasklet_struct *) 风格的回调,并用 tasklet_setup() 取代了老式 tasklet_init()(后者保留 DECLARE_TASKLET_OLD 兼容旧代码)。因此 tasklet 在 6.1 依然是一个可用的底半部选项。


unsetunset本文你学到了什么unsetunset

  1. 中断 vs 轮询 —— 中断是硬件主动通知,轮询是 CPU 反复询问;中断省 CPU、响应快
  2. gpio_to_irq + request_irq —— GPIO 编号转中断号、注册中断处理函数
  3. 中断上下文的限制 —— 不能休眠、不能调度、不能 copy_from_user、不能用 mutex
  4. 顶半部 / 底半部分离 —— 顶半部快(微秒级),底半部跑复杂逻辑(可以休眠)
  5. request_threaded_irq(推荐方案) —— 顶半部留空(或返回 IRQ_WAKE_THREAD),底半部运行在内核线程
  6. workqueue(了解即可) —— 更灵活但更繁琐,schedule_work 调度
  7. 按键去抖 —— 硬件去抖(gpiod_set_debounce)+ 软件去抖(msleep
  8. /proc/interrupts —— 检查中断是否触发、触发次数

unsetunset接下来unsetunset

中断让按键驱动高效了,但也引入了一个新问题——并发。底半部的内核线程和用户态的 read/write/ioctl 可能同时访问同一个设备结构体,如果不用锁保护,就会出现"读到一半被改了"的竞态条件。

下一篇,我们引入 Linux 并发与同步机制spin_lockmutexatomic_t,以及一个"不上锁就出 bug"的真实按键驱动案例。


关注「钱途无量嵌入式」,专注 Linux 驱动与 BSP 开发,每周硬核输出。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-06 16:54:25 HTTP/2.0 GET : https://f.mffb.com.cn/a/503710.html
  2. 运行时间 : 0.131004s [ 吞吐率:7.63req/s ] 内存消耗:4,701.34kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=38def75ebfc47391472b5aa9113f0a75
  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.000622s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000835s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.001605s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000276s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000552s ]
  6. SELECT * FROM `set` [ RunTime:0.000221s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000619s ]
  8. SELECT * FROM `article` WHERE `id` = 503710 LIMIT 1 [ RunTime:0.005128s ]
  9. UPDATE `article` SET `lasttime` = 1783328065 WHERE `id` = 503710 [ RunTime:0.014332s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000261s ]
  11. SELECT * FROM `article` WHERE `id` < 503710 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000459s ]
  12. SELECT * FROM `article` WHERE `id` > 503710 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000454s ]
  13. SELECT * FROM `article` WHERE `id` < 503710 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.010543s ]
  14. SELECT * FROM `article` WHERE `id` < 503710 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.008900s ]
  15. SELECT * FROM `article` WHERE `id` < 503710 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.018017s ]
0.132734s