当前位置:首页>Linux>嵌入式Linux驱动开发入门:字符设备驱动实战指南

嵌入式Linux驱动开发入门:字符设备驱动实战指南

  • 2026-02-05 13:24:13
嵌入式Linux驱动开发入门:字符设备驱动实战指南
学长说:在2026年AIoT爆发时代,Linux驱动开发能力将成为嵌入式工程师的“黄金技能”,掌握它,你就站在了职业发展的快车道上。
大家好,我是嵌入式学长。今天我们来深入探讨嵌入式Linux驱动开发的核心——字符设备驱动。我会用最实战的方式,从环境搭建到代码编写,带你完整实现一个LED驱动模块。最后,我们聊聊这个技能在2026年嵌入式AIoT浪潮中的巨大价值。

一、为什么Linux驱动开发是2026年的黄金技能?

在开始技术细节前,我们先回答一个关键问题:为什么企业对Linux驱动人才求贤若渴?

根据行业调研,2026年全球AIoT设备数量将突破500亿台,其中超过60%采用Linux或类Linux系统。这意味着:

  1. 市场需求井喷:
    :智能汽车、工业机器人、智能家居、医疗设备...几乎所有智能化设备都需要Linux驱动工程师
  2. 薪资水平领先:
    :掌握Linux驱动开发的嵌入式工程师,平均薪资比传统单片机开发高出40%-60%
  3. 职业天花板高:
    :驱动开发涉及底层硬件、操作系统内核、系统架构,是成为系统架构师的必经之路

我辅导过的学员中,转型Linux驱动开发后,薪资涨幅普遍在50%以上。这就是我们今天要投入学习的现实回报。

二、Linux内核模块基础与编译环境搭建

2.1 Linux内核模块的核心概念

Linux内核模块就像一个可动态加载的“插件”,它运行在内核空间,能够直接操作硬件。与应用程序不同:

特性
应用程序
内核模块
运行空间
用户空间
内核空间
权限级别
受限权限
完全权限
加载方式
进程启动
动态加载/卸载
错误影响
进程崩溃
系统崩溃
学长提醒:内核模块开发需要格外小心,一个空指针解引用就可能导致整个系统宕机。但正是这种“危险”的工作,带来了高薪和价值感。

2.2 开发环境搭建(Ubuntu 20.04 + Raspberry Pi示例)

我们以Raspberry Pi 4(ARM架构)为例,搭建完整的交叉编译环境:

# 1. 安装必要的工具链sudo apt-get updatesudo apt-get install git bc bison flex libssl-dev make gcc-arm-linux-gnueabihf# 2. 获取Linux内核源码(以树莓派5.10.y内核为例)git clone --depth=1 --branch rpi-5.10.y https://github.com/raspberrypi/linux# 3. 配置内核编译选项cd linuxKERNEL=kernel7lmake ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig# 4. 准备模块开发环境make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_prepare# 5. 验证环境echo "环境搭建完成!内核版本:$(make kernelversion)"
示意图:开发环境架构图(宿主机Ubuntu交叉编译 → 目标板Raspberry Pi运行)
[宿主机 x86_64]    |    | 交叉编译工具链    v[ARM内核头文件]    |    | 编译驱动模块    v[.ko内核模块文件]    |    | scp传输    v[目标板 Raspberry Pi]    |    | insmod加载    v[运行在内核空间]

2.3 第一个内核模块:Hello World

让我们编写最简单的内核模块,建立信心:
// hello.c - 最简单的内核模块#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h>MODULE_LICENSE("GPL");MODULE_AUTHOR("Embedded Senior");MODULE_DESCRIPTION("A simple hello world module");MODULE_VERSION("1.0");staticint __init hello_init(void){    printk(KERN_INFO "嵌入式学长说:Hello, Linux Kernel!\\n");    return 0;  // 返回0表示成功}staticvoid __exit hello_exit(void){    printk(KERN_INFO "嵌入式学长说:Goodbye, Linux Kernel!\\n");}module_init(hello_init);module_exit(hello_exit);
对应的Makefile:
# Makefile - 内核模块编译obj-m := hello.oKDIR := /home/embedded/linux  # 修改为你的内核源码路径PWD := $(shell pwd)all:    $(MAKE) -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-clean:    $(MAKE) -C $(KDIR) M=$(PWD) clean
编译并测试:
# 编译make# 将hello.ko复制到树莓派scp hello.ko pi@192.168.1.100:/home/pi/# 在树莓派上运行sudo insmod hello.ko      # 加载模块sudo rmmod hello          # 卸载模块dmesg | tail -5          # 查看内核日志
代码解读
  • module_init()
    :指定模块加载时调用的函数
  • module_exit()
    :指定模块卸载时调用的函数
  • printk()
    :内核空间的打印函数,输出到内核日志
  • .ko
    文件:内核对象文件,即编译好的模块

三、字符设备驱动框架深度解析

3.1 字符设备驱动三大支柱

字符设备驱动(如LED、按键、串口)的架构建立在三个核心数据结构上:
  1. struct file_operations
    :定义驱动提供的操作函数集(open、read、write等)
  2. struct cdev
    :内核中的字符设备对象
  3. dev_t
    :设备号(主设备号+次设备号)
示意图:字符设备驱动架构层次
用户空间应用程序    |    | 系统调用(openreadwrite    vVFS虚拟文件系统层    |    | 调用file_operations中的对应函数    v字符设备驱动层    |    ↑    |    | 硬件操作    v    v物理硬件设备

3.2 file_operations结构体详解

这是驱动开发的核心,定义了设备能响应的所有操作:
// file_operations结构体示例(简化版)struct file_operations {    struct module *owner;    loff_t (*llseek) (struct file *, loff_t, int);    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);    int (*open) (struct inode *, struct file *);    int (*release) (struct inode *, struct file *);    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);    // ... 更多操作};
关键函数的作用
函数
触发时机
典型实现内容
open
用户调用open()
初始化设备、增加引用计数
release
用户调用close()
释放资源、减少引用计数
read
用户调用read()
从设备读取数据到用户空间
write
用户调用write()
从用户空间写数据到设备
ioctl
用户调用ioctl()
设备特定控制命令

3.3 设备号管理与注册流程

Linux内核通过设备号来唯一标识设备,注册流程如下:
// 设备注册代码框架staticint __init mydriver_init(void){    dev_t devno;    int ret;    // 1. 申请设备号(动态申请)    ret = alloc_chrdev_region(&devno, 01"myled");    if (ret < 0) {        printk(KERN_ERR "申请设备号失败\\n");        return ret;    }    major = MAJOR(devno);  // 获取主设备号    // 2. 初始化cdev结构体    cdev_init(&my_cdev, &my_fops);    my_cdev.owner = THIS_MODULE;    // 3. 添加到内核    ret = cdev_add(&my_cdev, devno, 1);    if (ret < 0) {        printk(KERN_ERR "添加cdev失败\\n");        unregister_chrdev_region(devno, 1);        return ret;    }    // 4. 创建设备节点(自动创建)    my_class = class_create(THIS_MODULE, "myled_class");    device_create(my_class, NULL, devno, NULL"myled");    printk(KERN_INFO "LED驱动注册成功,主设备号:%d\\n", major);    return 0;}
学长经验:在早期项目中,我曾忘记调用cdev_del()unregister_chrdev_region(),导致模块卸载后设备号未释放,系统重启后才能重新加载。这个教训让我深刻理解了内核资源管理的重要性。

四、实战:完整的LED驱动模块开发

4.1 硬件连接与原理图

我们使用Raspberry Pi 4的GPIO 17(物理引脚11)连接LED:
树莓派 GPIO 17 (BCM) → 220Ω电阻 → LED正极 → LED负极 → GND
示意图LED驱动硬件连接图
      +3.3V        |        |     GPIO17        |        |     220Ω电阻        |        |----> LED正极        |      LED负极        |        |       GND

4.2 完整的LED驱动代码(myled.c)

// myled.c - 完整的LED字符设备驱动#include<linux/module.h>#include<linux/fs.h>#include<linux/cdev.h>#include<linux/device.h>#include<linux/uaccess.h>#include<linux/gpio.h>#include<linux/errno.h>#define DEVICE_NAME "myled"#define LED_GPIO 17  // BCM GPIO 17#define BUFFER_SIZE 1024MODULE_LICENSE("GPL");MODULE_AUTHOR("Embedded Senior");MODULE_DESCRIPTION("Raspberry Pi LED Driver");static int major;static struct class *my_class;static struct cdev my_cdev;static char device_buffer[BUFFER_SIZE];static int buffer_pointer = 0;// 设备打开函数staticintmyled_open(struct inode *inode, struct file *file){    printk(KERN_INFO "LED设备被打开\\n");    try_module_get(THIS_MODULE);  // 增加模块引用计数    return 0;}// 设备关闭函数staticintmyled_release(struct inode *inode, struct file *file){    printk(KERN_INFO "LED设备被关闭\\n");    module_put(THIS_MODULE);  // 减少模块引用计数    return 0;}// 读取函数 - 返回LED状态staticssize_tmyled_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){    int value;    char status[32];    int len;    // 读取GPIO当前状态    value = gpio_get_value(LED_GPIO);    if (value)        len = snprintf(status, sizeof(status), "LED状态:ON\\n");    else        len = snprintf(status, sizeof(status), "LED状态:OFF\\n");    // 复制到用户空间    if (copy_to_user(buf, status, len)) {        return -EFAULT;    }    return len;}// 写入函数 - 控制LED亮灭staticssize_tmyled_write(struct file *filp, constchar __user *buf, size_t count, loff_t *f_pos){    char command;    if (count != 1) {        printk(KERN_WARNING "只需要一个字符命令:'0'关,'1'开\\n");        return -EINVAL;    }    // 从用户空间获取命令    if (copy_from_user(&command, buf, 1)) {        return -EFAULT;    }    // 执行命令    if (command == '1') {        gpio_set_value(LED_GPIO, 1);        printk(KERN_INFO "LED打开\\n");    } else if (command == '0') {        gpio_set_value(LED_GPIO, 0);        printk(KERN_INFO "LED关闭\\n");    } else {        printk(KERN_WARNING "无效命令:%c\\n", command);        return -EINVAL;    }    return 1;  // 成功写入1个字节}// ioctl控制函数staticlongmyled_ioctl(struct file *filp, unsignedint cmd, unsignedlong arg){    int value;    switch (cmd) {        case 0x01:  // 获取LED状态            value = gpio_get_value(LED_GPIO);            if (copy_to_user((int __user *)arg, &value, sizeof(int)))                return -EFAULT;            break;        case 0x02:  // 翻转LED            value = gpio_get_value(LED_GPIO);            gpio_set_value(LED_GPIO, !value);            printk(KERN_INFO "LED翻转,新状态:%d\\n", !value);            break;        default:            return -ENOTTY;  // 不支持的命令    }    return 0;}// file_operations结构体定义static struct file_operations myled_fops = {    .owner = THIS_MODULE,    .open = myled_open,    .release = myled_release,    .read = myled_read,    .write = myled_write,    .unlocked_ioctl = myled_ioctl,};// 模块初始化函数staticint __init myled_init(void){    dev_t devno;    int ret;    // 1. 申请GPIO    if (!gpio_is_valid(LED_GPIO)) {        printk(KERN_ERR "无效的GPIO号:%d\\n", LED_GPIO);        return -ENODEV;    }    ret = gpio_request(LED_GPIO, "LED_GPIO");    if (ret) {        printk(KERN_ERR "申请GPIO失败:%d\\n", ret);        return ret;    }    // 2. 配置GPIO为输出,初始低电平    gpio_direction_output(LED_GPIO, 0);    // 3. 申请设备号    ret = alloc_chrdev_region(&devno, 01, DEVICE_NAME);    if (ret < 0) {        printk(KERN_ERR "申请设备号失败\\n");        gpio_free(LED_GPIO);        return ret;    }    major = MAJOR(devno);    // 4. 初始化cdev    cdev_init(&my_cdev, &myled_fops);    my_cdev.owner = THIS_MODULE;    // 5. 添加cdev到内核    ret = cdev_add(&my_cdev, devno, 1);    if (ret < 0) {        printk(KERN_ERR "添加cdev失败\\n");        unregister_chrdev_region(devno, 1);        gpio_free(LED_GPIO);        return ret;    }    // 6. 创建设备节点    my_class = class_create(THIS_MODULE, "myled_class");    if (IS_ERR(my_class)) {        printk(KERN_ERR "创建class失败\\n");        cdev_del(&my_cdev);        unregister_chrdev_region(devno, 1);        gpio_free(LED_GPIO);        return PTR_ERR(my_class);    }    device_create(my_class, NULL, devno, NULL, DEVICE_NAME);    printk(KERN_INFO "LED驱动初始化成功!主设备号:%d\\n", major);    printk(KERN_INFO "使用:echo 1 > /dev/myled  # 打开LED\\n");    printk(KERN_INFO "使用:echo 0 > /dev/myled  # 关闭LED\\n");    return 0;}// 模块清理函数staticvoid __exit myled_exit(void){    dev_t devno = MKDEV(major, 0);    // 1. 销毁设备节点    device_destroy(my_class, devno);    // 2. 销毁class    class_destroy(my_class);    // 3. 删除cdev    cdev_del(&my_cdev);    // 4. 释放设备号    unregister_chrdev_region(devno, 1);    // 5. 释放GPIO    gpio_set_value(LED_GPIO, 0);    gpio_free(LED_GPIO);    printk(KERN_INFO "LED驱动卸载完成\\n");}module_init(myled_init);module_exit(myled_exit);

4.3 对应的Makefile

# Makefile for LED driverobj-m := myled.oKDIR := /home/embedded/linux  # 修改为你的内核源码路径PWD := $(shell pwd)all:    $(MAKE) -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-clean:    $(MAKE) -C $(KDIR) M=$(PWD) clean

4.4 用户空间测试程序(test_led.c)

// test_led.c - LED驱动测试程序#include<stdio.h>#include<stdlib.h>#include<fcntl.h>#include<unistd.h>#include<string.h>#include<sys/ioctl.h>#define DEVICE_PATH "/dev/myled"// ioctl命令定义#define GET_LED_STATUS 0x01#define TOGGLE_LED     0x02intmain(int argc, char *argv[]){    int fd;    char command;    int status;    // 打开设备    fd = open(DEVICE_PATH, O_RDWR);    if (fd < 0) {        perror("打开设备失败");        return -1;    }    printf("LED驱动测试程序\\n");    printf("===============\\n");    // 获取当前状态    if (ioctl(fd, GET_LED_STATUS, &status) < 0) {        perror("ioctl失败");        close(fd);        return -1;    }    printf("当前LED状态:%s\\n", status ? "ON" : "OFF");    // 交互式控制    while (1) {        printf("\\n命令:1=开,0=关,t=翻转,q=退出:");        command = getchar();        getchar();  // 消耗换行符        switch (command) {            case '1':                write(fd, "1"1);                printf("LED已打开\\n");                break;            case '0':                write(fd, "0"1);                printf("LED已关闭\\n");                break;            case 't':                ioctl(fd, TOGGLE_LED);                printf("LED已翻转\\n");                break;            case 'q':                close(fd);                printf("程序退出\\n");                return 0;            default:                printf("无效命令\\n");                break;        }    }    close(fd);    return 0;}
编译测试程序
# 交叉编译测试程序arm-linux-gnueabihf-gcc -o test_led test_led.c# 复制到树莓派scp test_led pi@192.168.1.100:/home/pi/# 在树莓派上运行chmod +x test_ledsudo ./test_led

五、用户空间与内核空间数据交互机制

5.1 三种数据交互方式对比

方式
原理
适用场景
性能
安全性
copy_to/from_user
显式拷贝数据
小数据量(<4KB)
中等
mmap内存映射
映射内核内存到用户空间
大数据量(如图像、音频)
中等
ioctl命令
通过命令码传递控制信息
设备控制、配置

5.2 copy_to_user/copy_from_user最佳实践

// 安全的数据拷贝示例static ssize_t safe_data_transfer(structfile *filp, char __user *buf, size_t count){    char kernel_buf[256];    int ret;    // 1. 检查用户空间缓冲区是否可读写    if (!access_ok(buf, count)) {        return -EFAULT;    }    // 2. 限制拷贝大小,防止缓冲区溢出    if (count > sizeof(kernel_buf)) {        count = sizeof(kernel_buf);    }    // 3. 从用户空间拷贝到内核空间    ret = copy_from_user(kernel_buf, buf, count);    if (ret) {        // 实际拷贝的字节数 = count - ret        printk(KERN_WARNING "部分数据拷贝失败:%d字节未拷贝\\n", ret);        return -EFAULT;    }    // 4. 处理数据...    // 5. 将结果拷贝回用户空间    ret = copy_to_user(buf, kernel_buf, count);    if (ret) {        printk(KERN_WARNING "回写数据失败:%d字节未写入\\n", ret);        return -EFAULT;    }    return count;}

5.3 mmap内存映射实战

// 实现mmap操作staticintmyled_mmap(structfile *filp, struct vm_area_struct *vma){    unsigned long size = vma->vm_end - vma->vm_start;    // 1. 检查映射大小是否合理    if (size > PAGE_SIZE * 4) {        printk(KERN_WARNING "映射请求过大:%lu字节\\n", size);        return -EINVAL;    }    // 2. 映射内核缓冲区到用户空间    if (remap_pfn_range(vma, vma->vm_start,                        virt_to_phys(device_buffer) >> PAGE_SHIFT,                       size, vma->vm_page_prot)) {        printk(KERN_ERR "内存映射失败\\n");        return -EAGAIN;    }    printk(KERN_INFO "成功映射%lu字节到用户空间\\n", size);    return 0;}// 在file_operations中添加mmap支持static struct file_operations myled_fops = {    // ... 其他操作    .mmap = myled_mmap,};
示意图:mmap内存映射原理
用户空间进程地址空间    |    | 通过页表建立映射    v内核空间缓冲区    |    | 直接访问    v物理内存

六、驱动调试技巧与常见错误处理

6.1 四大调试工具对比

工具
适用场景
优点
缺点
printk
基本日志输出
简单、无需额外工具
影响性能、日志量大
动态调试
选择性输出调试信息
灵活、可运行时控制
需要配置
内核跟踪
性能分析、调用跟踪
全面、可视化
学习曲线陡
KGDB
源码级调试
强大、可单步执行
配置复杂、需要两台机器

6.2 printk级别与使用技巧

// printk级别定义(从高到低)#define KERN_EMERG   "<0>"// 系统不可用#define KERN_ALERT   "<1>"// 需要立即行动#define KERN_CRIT    "<2>"// 严重错误#define KERN_ERR     "<3>"// 一般错误#define KERN_WARNING "<4>"// 警告#define KERN_NOTICE  "<5>"// 正常但重要#define KERN_INFO    "<6>"// 信息性消息#define KERN_DEBUG   "<7>"// 调试信息// 最佳实践示例staticintmy_function(void){    int ret;    // 进入函数时记录(DEBUG级别)    printk(KERN_DEBUG "my_function: 开始执行\\n");    // 执行核心操作    ret = do_something();    if (ret < 0) {        // 错误时记录(ERR级别)        printk(KERN_ERR "my_function: do_something失败,错误码=%d\\n", ret);        return ret;    }    // 成功时记录(INFO级别)    printk(KERN_INFO "my_function: 成功完成,结果=%d\\n", ret);    return ret;}

6.3 常见错误与解决方案

错误现象
可能原因
排查步骤
解决方案
insmod失败
符号未导出
1. 检查内核版本2. 查看dmesg输出
使用EXPORT_SYMBOL导出所需符号
设备节点无法创建
权限问题
1. 检查class是否创建成功2. 查看sysfs
确保驱动初始化流程完整
用户程序读写失败
内存访问违规
1. 检查copy_to/from_user返回值2. 使用strace跟踪
添加access_ok检查
系统崩溃/死机
内核空指针
1. 分析崩溃dump2. 逐步注释代码
使用NULL指针检查,减少全局变量
学长调试故事:在第一个商业驱动项目中,系统会在运行几小时后随机死机。经过三天三夜的排查,最终发现是中断处理函数中使用了可能为NULL的指针。教训是:内核代码必须假设所有指针都可能为NULL,必须做防御性检查

6.4 防御性编程最佳实践

// 1. 指针安全检查staticvoidsafe_pointer_access(struct device *dev){    if (!dev) {        printk(KERN_ERR "设备指针为NULL\\n");        return;    }    if (!dev->driver_data) {        printk(KERN_WARNING "驱动数据未初始化\\n");        return;    }    // 安全访问    // ...}// 2. 资源申请检查staticintsafe_resource_allocation(void){    void *buffer;    int ret;    buffer = kmalloc(SIZE, GFP_KERNEL);    if (!buffer) {        printk(KERN_ERR "内存分配失败\\n");        return -ENOMEM;    }    ret = do_operation(buffer);    if (ret < 0) {        kfree(buffer);  // 错误时释放资源        return ret;    }    // 成功时也要记得最终释放    kfree(buffer);    return 0;}

七、学习路线与2026年就业建议

7.1 Linux驱动开发四阶段学习法

第一阶段(2周):基础夯实
  • 目标:理解内核模块机制,能编写简单字符设备驱动
  • 实践:完成LED、按键、PWM等基础驱动
  • 检验:驱动能稳定运行24小时不崩溃
第二阶段(3周):框架精通
  • 目标:掌握平台设备、设备树、中断处理
  • 实践:实现SPI、I2C、USB等总线设备驱动
  • 检验:能阅读芯片手册独立编写外设驱动
第三阶段(4-6周):项目实战
  • 目标:参与真实硬件项目,解决复杂问题
  • 实践:贡献开源驱动或参与公司项目
  • 检验:能独立完成一个中等复杂度驱动
第四阶段(持续):深度专精
  • 目标:选择细分领域(网络、存储、图形等)深入
  • 实践:研究内核子系统,优化驱动性能
  • 检验:能解决领域内的疑难杂症

7.2 2026年Linux驱动工程师能力矩阵

能力等级
薪资范围(应届生)
核心技能要求
代表岗位
初级
10-22K
字符设备驱动、内核模块、基础调试
嵌入式驱动工程师
中级
22-35K
设备树、中断、DMA、并发控制
Linux驱动开发工程师
高级
35-60K
子系统开发、性能优化、架构设计
内核开发专家
专家
60K+
内核贡献、专利技术、团队管理
系统架构师

7.3 面试常见问题与高分回答

问题1:"请描述字符设备驱动的注册流程"
高分回答结构
1. 设备号申请(静态/动态)2. cdev结构体初始化3. 添加cdev到内核4. class创建与设备节点生成5. 资源清理的逆向操作
问题2:"如何保证驱动的稳定性和性能?"
展示专业度的回答
1. 防御性编程:指针检查、资源管理2. 并发安全:锁机制、原子操作3. 性能优化:减少拷贝、DMA使用4. 测试覆盖:单元测试、压力测试5. 代码审查:遵循内核编码规范

八、实战作业与下期预告

8.1 本周实战作业

初级任务在树莓派上实现本文的LED驱动,并能通过用户程序控制。
进阶挑战:为LED驱动添加PWM功能,实现呼吸灯效果(提示:使用内核定时器)。
高手关卡:实现一个虚拟字符设备,支持mmap映射,并测量不同数据交互方式的性能差异。

8.2 下期预告

下周我们讲Linux设备树与平台设备驱动,这是现代嵌入式Linux开发的必备技能。我会带大家从零编写一个完整的设备树文件,并实现对应的平台设备驱动。

-------------------------------------------------------------------

码蚁--嵌入式学长实验室 · 专注大学生嵌入式就业指导

每周一、三、五更新深度技术干货

关注公众号回复"Linux驱动代码"获取本文完整工程文件

加入技术交流群:公众号菜单栏"加入我们"

免费资料包领取

  • 《Linux驱动开发入门到精通》电子书
  • 10个真实项目驱动源码
  • 2026年嵌入式岗位面试题库
  • 内核调试工具使用指南
学长寄语:Linux驱动开发是一座高山,攀登的过程很辛苦,但站在山顶看到的风景是无价的。每天进步一点点,半年后你会感谢今天开始学习的自己。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-07 17:04:11 HTTP/2.0 GET : https://f.mffb.com.cn/a/473552.html
  2. 运行时间 : 0.098423s [ 吞吐率:10.16req/s ] 内存消耗:4,688.80kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=29af549503a3796f136bc49a9b3305ec
  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.000638s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000734s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.001093s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.001650s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000557s ]
  6. SELECT * FROM `set` [ RunTime:0.000227s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000616s ]
  8. SELECT * FROM `article` WHERE `id` = 473552 LIMIT 1 [ RunTime:0.000723s ]
  9. UPDATE `article` SET `lasttime` = 1770455052 WHERE `id` = 473552 [ RunTime:0.001221s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.003529s ]
  11. SELECT * FROM `article` WHERE `id` < 473552 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.002603s ]
  12. SELECT * FROM `article` WHERE `id` > 473552 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001083s ]
  13. SELECT * FROM `article` WHERE `id` < 473552 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.007302s ]
  14. SELECT * FROM `article` WHERE `id` < 473552 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.004105s ]
  15. SELECT * FROM `article` WHERE `id` < 473552 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.004865s ]
0.099983s