当前位置:首页>Linux>Linux 6.12 内核块设备驱动开发实战:从基础到 vmem_disk 实例

Linux 6.12 内核块设备驱动开发实战:从基础到 vmem_disk 实例

  • 2026-07-02 16:50:28
Linux 6.12 内核块设备驱动开发实战:从基础到 vmem_disk 实例

title: "Linux 6.12 内核块设备驱动开发实战:从基础到 vmem_disk 实例" date: "2026-05-24" author: "Linux Kernel Developer" tags: ["块设备驱动", "Linux内核", "ARM64", "blk-mq", "嵌入式开发"] categories: ["Linux驱动开发", "内核调试", "ARM64实战"] description: "基于Linux 6.12内核,手把手教你开发虚拟内存块设备驱动,掌握blk-mq架构核心技能"


Linux 6.12 内核块设备驱动开发实战:从基础到 vmem_disk 实例

前言

🎯 业务场景

在嵌入式开发中,我们经常需要存储数据。常见的存储介质包括:

  • 硬盘/SSD:机械硬盘和固态硬盘
  • U 盘/SD 卡:便携式存储设备
  • eMMC/NAND Flash:嵌入式设备常用存储
  • 虚拟磁盘:用于测试、模拟、Ramdisk 等场景

今天我们要开发的 vmem_disk(虚拟内存磁盘),就是一种基于内存的块设备,它将一块内存区域模拟成块设备,提供标准块设备的读写接口。

💡 应用价值

vmem_disk 的典型应用场景:

  1. 高性能临时存储:将内存作为磁盘,适合需要高速读写的临时数据
  2. 测试环境搭建:无需真实硬件即可测试块设备驱动的所有功能
  3. 教学演示:学习块设备驱动的最佳实践,无需担心硬件损坏
  4. 缓存层实现:可以作为软件定义缓存的基础

🔧 驱动作用

块设备驱动是 Linux 内核中最核心的子系统之一。它负责:

  • 接收上层文件系统的 I/O 请求
  • 调度和优化请求顺序
  • 与硬件设备交互完成数据传输
  • 管理设备的生命周期

在 Linux 6.x 内核中,块设备驱动框架已经全面向 blk-mq(multi-queue block layer)架构迁移,这带来了更好的多核扩展性和性能。


一、原理精讲

1.1 块设备驱动核心概念(通俗版 🎓)

在动手开发之前,让我们先理解几个关键概念。为了让萌新也能理解,我会用通俗的语言解释:

📦 主设备号与次设备号

想象一个城市里的停车场系统:

  • 主设备号(Major Number):就像"停车场类型编号",A区是地上停车场,B区是地下停车场。Linux 中,主设备号标识驱动类型(如 8 是 SCSI 磁盘,253 是虚拟设备)
  • 次设备号(Minor Number):就像"A区的第56号车位"。Linux 中,次设备号区分同一驱动下的多个设备
#define VMEM_DISK_MINORS 4  // 支持4个次设备号,即最多4个分区

🎫 gendisk 结构体

gendisk 就像块设备的"身份证"和"档案卡",记录了设备的所有信息:

字段
作用
通俗解释
major
主设备号
设备类型编号
first_minor
首个次设备号
第一个分区编号
minors
次设备号数量
最多支持几个分区
fops
文件操作集
设备的"操作手册"
queue
请求队列
等待处理的 I/O 请求队列
private_data
私有数据
驱动自己的"秘密档案"

🚀 blk-mq 架构

什么是 blk-mq?

传统的块设备层是单队列的,就像只有一个收银台的超市,结账要排队。

blk-mq(Block Multi-Queue,多队列块层)就像超市改造后有 8 个收银台,多个收银员可以同时处理结账,效率大幅提升!

Linux 6.12 内核为什么选择 blk-mq?

  1. 更好的多核扩展性:多个 CPU 核心可以同时处理 I/O 请求
  2. 降低锁竞争:不同队列使用不同的锁,减少等待
  3. 硬件原生支持:现代 NVMe SSD 等硬件本身就支持多队列

1.2 整体架构图

让我们通过 Mermaid 图来理解整个块设备驱动的架构:

1.3 函数调用时序图

下面是应用程序读写 vmem_disk 的完整调用流程:

1.4 数据结构关系图

1.5 核心 API 一览表

API 函数
作用
通俗解释
register_blkdev()
注册块设备
"我在系统里登记一下"
blk_mq_alloc_tag_set()
分配请求队列
"给我开个收银台"
blk_mq_alloc_disk()
分配 gendisk
"给设备办张身份证"
add_disk()
添加设备到系统
"正式开门营业"
blk_mq_start_request()
开始处理请求
"开始处理这单业务"
blk_mq_end_request()
结束请求处理
"这单完成了"

二、代码实操

2.1 完整驱动源码

以下是 [vmem_disk.c](file:///home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/testcode/driver/vmem/vmem_disk.c) 的完整实现,可直接编译使用:

/** * vmem_disk.c - 虚拟内存块设备驱动 *  * 功能:创建一个基于内存的虚拟块设备 * 内核版本:Linux 6.12 * 硬件平台:ARM64 (RK3568/RZ/G2L) *  * 作者:Linux Kernel Developer * 版本:1.0 */#include<linux/module.h>      // 内核模块相关#include<linux/fs.h>         // 文件系统相关#include<linux/blkdev.h>     // 块设备相关#include<linux/blk-mq.h>     // 多队列块层#include<linux/hdreg.h>       // 硬盘geometry#include<linux/slab.h>        // 内存分配#include<linux/spinlock.h>   // 自旋锁#include<linux/vmalloc.h>    // 虚拟内存分配/*====================================== * 宏定义 *======================================*/#define VMEM_DISK_NAME "vmem_disk"// 设备名称#define VMEM_DISK_MINORS 4                   // 支持4个次设备号#define VMEM_DISK_SIZE (16 * 1024 * 1024)    // 16MB虚拟磁盘/*====================================== * 设备结构体定义 *======================================*//** * vmem_disk_dev - 虚拟磁盘设备结构体 *  * 这个结构体保存了设备的所有私有信息, * 通过 gendisk->private_data 访问。 */structvmem_disk_dev {unsignedchar *data;         // 数据存储区(vmalloc分配)unsignedlong size;          // 设备大小spinlock_t lock;             // 保护open_count的自旋锁int open_count;              // 打开计数,防止意外卸载structblk_mq_tag_settag_set;// blk-mq队列配置structgendisk *disk;// 指向 gendisk 的指针};/*====================================== * 全局变量 *======================================*/staticstructvmem_disk_dev *vmem_dev;// 设备实例指针staticint vmem_major;                   // 主设备号(动态分配)/*====================================== * I/O 请求处理函数(核心⭐) *======================================*//** * vmem_queue_rq - 处理块 I/O 请求 *  * 这是驱动最核心的函数!每当有读写请求时, * 内核就会调用这个函数来处理。 *  * @hctx: 硬件队列上下文 * @bd: 请求队列数据 *  * 返回值:BLK_STS_OK 表示成功,其他表示错误 */staticblk_status_tvmem_queue_rq(struct blk_mq_hw_ctx *hctx,const struct blk_mq_queue_data *bd){structrequest *req = bd->rq;// 获取请求structbio_vecbvec;// bio段结构structreq_iteratoriter;// 迭代器sector_t sector = blk_rq_pos(req);      // 起始扇区号int ret = BLK_STS_OK;                    // 默认成功// ⭐ 告诉内核我开始处理这个请求了    blk_mq_start_request(req);// 遍历请求中的所有 bio 段// 为什么要遍历?因为一个大请求可能被分成多个段    rq_for_each_segment(bvec, req, iter) {char *buffer = page_address(bvec.bv_page) + bvec.bv_offset;unsignedint seg_len = bvec.bv_len;// 🔒 边界检查:防止访问越界if (sector * SECTOR_SIZE + seg_len > vmem_dev->size) {            pr_err("vmem_disk: access beyond device size!\n");            ret = BLK_STS_IOERR;break;        }// 📖📝 根据读写方向执行数据拷贝if (rq_data_dir(req) == READ) {// 读:从虚拟内存拷贝到用户缓冲区memcpy(buffer, vmem_dev->data + sector * SECTOR_SIZE, seg_len);        } else {// 写:从用户缓冲区拷贝到虚拟内存memcpy(vmem_dev->data + sector * SECTOR_SIZE, buffer, seg_len);        }// 更新扇区号,为下一个段做准备        sector += seg_len / SECTOR_SIZE;    }// ✅ 请求处理完成,通知内核    blk_mq_end_request(req, ret);return BLK_STS_OK;}/*====================================== * blk-mq 操作集定义 *======================================*//** * blk_mq_ops - blk-mq 操作函数集 *  * 定义了驱动支持的回调函数。 * 这里我们只实现了 queue_rq,即请求处理函数。 */staticconststructblk_mq_opsvmem_mq_ops = {    .queue_rq = vmem_queue_rq,  // 核心:请求处理函数};/*====================================== * 设备操作函数 *======================================*//** * vmem_open - 打开块设备 *  * 当应用程序打开 /dev/vmem_disk 时调用 */staticintvmem_open(struct gendisk *disk, blk_mode_t mode){structvmem_disk_dev *dev = disk->private_data;    spin_lock(&dev->lock);    dev->open_count++;  // 增加打开计数    spin_unlock(&dev->lock);    pr_info("vmem_disk: device opened (count=%d)\n", dev->open_count);return0;}/** * vmem_release - 释放块设备 *  * 当应用程序关闭文件描述符时调用 */staticvoidvmem_release(struct gendisk *disk){structvmem_disk_dev *dev = disk->private_data;    spin_lock(&dev->lock);    dev->open_count--;  // 减少打开计数    spin_unlock(&dev->lock);    pr_info("vmem_disk: device released (count=%d)\n", dev->open_count);}/** * vmem_getgeo - 获取磁盘几何信息 *  * 用于 fdisk 等分区工具识别设备参数 */staticintvmem_getgeo(struct block_device *bdev, struct hd_geometry *geo){structvmem_disk_dev *dev = bdev->bd_disk->private_data;// 计算柱面数    geo->cylinders = dev->size / (geo->heads * geo->sectors * SECTOR_SIZE);    geo->heads = 4;      // 磁头数    geo->sectors = 16;   // 每磁道扇区数    geo->start = 0;      // 起始扇区return0;}/*====================================== * 块设备操作集 *======================================*//** * block_device_operations - 设备操作集 *  * 定义了设备支持的所有操作函数 */staticconststructblock_device_operationsvmem_blk_ops = {    .owner = THIS_MODULE,    .open = vmem_open,           // 打开设备    .release = vmem_release,      // 释放设备    .getgeo = vmem_getgeo,        // 获取几何信息};/*====================================== * 驱动初始化(模块加载时执行) *======================================*//** * vmem_init - 驱动初始化函数 *  * 模块加载时,内核会调用这个函数。 * 我们在这里完成所有的准备工作。 */staticint __init vmem_init(void){int ret;// 定义队列限制参数(Linux 6.12 新API)structqueue_limitslim = {        .logical_block_size = SECTOR_SIZE,     // 逻辑块大小        .physical_block_size = SECTOR_SIZE,    // 物理块大小    };    pr_info("vmem_disk: initializing...\n");/* 步骤1:分配设备结构体 */// 使用 kzalloc 分配并清零内存    vmem_dev = kzalloc(sizeof(struct vmem_disk_dev), GFP_KERNEL);if (!vmem_dev) {        pr_err("vmem_disk: failed to allocate device structure\n");return -ENOMEM;    }/* 步骤2:分配虚拟内存作为存储空间 */    vmem_dev->size = VMEM_DISK_SIZE;    vmem_dev->data = vmalloc(vmem_dev->size);if (!vmem_dev->data) {        pr_err("vmem_disk: failed to allocate %lu bytes\n", vmem_dev->size);        ret = -ENOMEM;goto out_free_dev;    }memset(vmem_dev->data, 0, vmem_dev->size);  // 清零内存// 初始化自旋锁和计数器    spin_lock_init(&vmem_dev->lock);    vmem_dev->open_count = 0;/* 步骤3:注册块设备(动态分配主设备号) */// 第一个参数为0表示动态分配    vmem_major = register_blkdev(0, VMEM_DISK_NAME);if (vmem_major <= 0) {        pr_err("vmem_disk: failed to register block device\n");        ret = -EBUSY;goto out_free_data;    }    pr_info("vmem_disk: registered with major number %d\n", vmem_major);/* 步骤4:配置 blk-mq tag_set */// 这是 Linux 6.x 内核的新方式    vmem_dev->tag_set.ops = &vmem_mq_ops;    vmem_dev->tag_set.nr_hw_queues = 1;        // 硬件队列数(简单设备用1)    vmem_dev->tag_set.queue_depth = 128;        // 队列深度    vmem_dev->tag_set.numa_node = NUMA_NO_NODE; // 不绑定特定NUMA节点    vmem_dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; // 允许合并相邻请求    vmem_dev->tag_set.driver_data = vmem_dev;   // 传递私有数据指针    ret = blk_mq_alloc_tag_set(&vmem_dev->tag_set);if (ret) {        pr_err("vmem_disk: failed to allocate tag set: %d\n", ret);goto out_unregister;    }/* 步骤5:分配并初始化 gendisk */// Linux 6.12 使用 blk_mq_alloc_disk 一步到位    vmem_dev->disk = blk_mq_alloc_disk(&vmem_dev->tag_set, &lim, vmem_dev);if (IS_ERR(vmem_dev->disk)) {        ret = PTR_ERR(vmem_dev->disk);        pr_err("vmem_disk: failed to allocate gendisk: %d\n", ret);goto out_free_tag_set;    }/* 步骤6:配置 gendisk 参数 */    vmem_dev->disk->major = vmem_major;    vmem_dev->disk->first_minor = 0;    vmem_dev->disk->minors = VMEM_DISK_MINORS;    vmem_dev->disk->fops = &vmem_blk_ops;    vmem_dev->disk->private_data = vmem_dev;snprintf(vmem_dev->disk->disk_name, DISK_NAME_LEN, "%s", VMEM_DISK_NAME);    set_capacity(vmem_dev->disk, vmem_dev->size / SECTOR_SIZE);/* 步骤7:将设备添加到系统 */    ret = add_disk(vmem_dev->disk);if (ret) {        pr_err("vmem_disk: failed to add disk: %d\n", ret);goto out_put_disk;    }    pr_info("vmem_disk: Virtual block device registered\n");    pr_info("  - Size: %lu MB\n", vmem_dev->size / (1024 * 1024));    pr_info("  - Major: %d\n", vmem_major);    pr_info("  - Device: /dev/%s\n", VMEM_DISK_NAME);return0;/* 错误处理:资源释放顺序很重要! */out_put_disk:    put_disk(vmem_dev->disk);out_free_tag_set:    blk_mq_free_tag_set(&vmem_dev->tag_set);out_unregister:    unregister_blkdev(vmem_major, VMEM_DISK_NAME);out_free_data:    vfree(vmem_dev->data);out_free_dev:    kfree(vmem_dev);return ret;}/*====================================== * 驱动退出(模块卸载时执行) *======================================*//** * vmem_exit - 驱动退出函数 *  * 模块卸载时,内核会调用这个函数。 * 我们在这里释放所有申请的资源。 */staticvoid __exit vmem_exit(void){    pr_info("vmem_disk: unloading...\n");// 资源释放顺序与初始化相反    del_gendisk(vmem_dev->disk);           // 1. 从系统移除设备    put_disk(vmem_dev->disk);               // 2. 释放 gendisk    blk_mq_free_tag_set(&vmem_dev->tag_set); // 3. 释放 tag_set    unregister_blkdev(vmem_major, VMEM_DISK_NAME); // 4. 注销块设备    vfree(vmem_dev->data);                  // 5. 释放虚拟内存    kfree(vmem_dev);                        // 6. 释放设备结构体    pr_info("vmem_disk: unloaded successfully\n");}/*====================================== * 模块入口和出口 *======================================*/module_init(vmem_init);   // 指定初始化函数module_exit(vmem_exit);   // 指定退出函数/*====================================== * 模块信息 *======================================*/MODULE_LICENSE("GPL");                              // 开源协议MODULE_DESCRIPTION("Virtual Memory Disk Block Device Driver");  // 描述MODULE_AUTHOR("Linux Kernel Developer");             // 作者MODULE_VERSION("1.0");                              // 版本

2.2 Makefile 编写

驱动编译需要交叉编译器,Makefile 如下:

#========================================# vmem_disk Makefile# 适用于 Linux 6.12 内核# 目标平台:ARM64 (RK3568/RZ/G2L)#========================================# 内核源码目录KDIR := /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt# 当前目录PWD := $(shell pwd)# 编译目标obj-m := vmem_disk.o# 默认目标all: @echo "========================================" @echo "Building vmem_disk for ARM64..." @echo "Kernel source: $(KDIR)" @echo "========================================"$(MAKE) -C $(KDIR) M=$(PWD) modules ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- @echo "" @echo "Build complete! Check vmem_disk.ko"# 清理clean: @echo "Cleaning..."$(MAKE) -C $(KDIR) M=$(PWD) clean# 安装到目标板(需要配置IP)install: all scp vmem_disk.ko root@192.168.3.133:/root/# 查看模块信息info: @echo "========================================" @echo "vmem_disk Module Info" @echo "========================================" @echo "Source: $(PWD)/vmem_disk.c" @echo "Output: $(PWD)/vmem_disk.ko" @echo "Target: ARM64 RK3568" @echo "" @if [ -f vmem_disk.ko ]; then \  echo "Module size:"; \  size vmem_disk.ko; \  echo ""; \  echo "Module info:"; \  modinfo vmem_disk.ko; \else \  echo "vmem_disk.ko not found. Run 'make' first."; \ fi

三、编译测试

3.1 编译环境准备

环境信息

项目
版本/配置
内核版本
Linux 6.12.43-cip7-rt12
硬件平台
ARM64 (RK3568/RZ/G2L SMARC)
交叉编译器
aarch64-linux-gnu-gcc
开发主机
x86_64 Linux

检查编译环境

# 检查交叉编译器aarch64-linux-gnu-gcc --version# 检查内核源码ls -la /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/Makefile# 检查内核版本cat /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/include/config/kernel.release

3.2 编译驱动

# 进入驱动目录cd testcode/driver/vmem# 编译驱动make

编译输出示例

========================================Building vmem_disk for ARM64...Kernel source: /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt========================================make -C /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt M=/home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/testcode/driver/vmem modules ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-make[1]: Entering directory '/home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt'  CC [M]  /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/testcode/driver/vmem/vmem_disk.o  MODPOST /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/testcode/driver/vmem/Module.symvers  CC [M]  /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/testcode/driver/vmem/vmem_disk.mod.o  LD [M]  /home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt/testcode/driver/vmem/vmem_disk.komake[1]: Leaving directory '/home/rlk/rzg/rz_linux-cip-rz-6.12-cip7-rt'Build complete! Check vmem_disk.ko# 查看编译产物-rw-r--r-- 1 rlk rlk 129120 May 24 22:34 vmem_disk.ko

3.3 部署到目标设备

# 拷贝驱动到目标设备scp vmem_disk.ko root@192.168.3.133:/root/# SSH 登录到目标设备ssh root@192.168.3.133

3.4 加载驱动

# 加载驱动insmod /root/vmem_disk.ko# 查看内核日志dmesg | tail -10

预期输出

vmem_disk: initializing...vmem_disk: registered with major number 253vmem_disk: Virtual block device registered  - Size: 16 MB  - Major: 253  - Device: /dev/vmem_disk

3.5 验证驱动加载

# 查看已加载的模块lsmod | grep vmem_disk# 查看块设备cat /proc/partitions# 查看设备节点ls -la /dev/vmem_disk# 查看内核日志dmesg | grep vmem_disk

预期输出

# lsmodvmem_disk 12288 0 - Live 0xffff800079b60000 (O)# cat /proc/partitionsmajor minor  #blocks  name 253        0      16384 vmem_disk# ls -la /dev/vmem_diskbrw-------    1 root     root      253,   0 Jan  1 08:03 /dev/vmem_disk

3.6 功能测试

# 1. 写入测试数据echo'Hello from vmem_disk!' > /tmp/test.txtdd if=/tmp/test.txt of=/dev/vmem_disk bs=512 count=1# 2. 读回数据验证dd if=/dev/vmem_disk of=/tmp/readback.txt bs=512 count=1cat /tmp/readback.txt# 3. 卸载驱动(确保设备未被使用)rmmod vmem_disk

测试结果

# 写入测试0+1 records in0+1 records out22 bytes (22B) copied, 0.000440 seconds, 48.8KB/s# 读回测试1+0 records in1+0 records out512 bytes (512B) copied, 0.000394 seconds, 1.2MB/sHello from vmem_disk!# 卸载测试vmem_disk: unloading...vmem_disk: unloaded successfully

四、排坑总结

4.1 常见编译错误

❌ 错误1:内核版本不匹配

错误信息

vmem_disk: version magic '6.12.43-cip7-rt12-gd5afead4d776-dirty' should be '6.12.43-cip7-rt12'insmod: init_module failed: Invalid parameters

原因:驱动编译时使用的内核版本与目标系统运行的内核版本不一致

解决方案

# 方案1:在目标系统上重新编译驱动# 方案2:使用 --force-vermagic 强制加载(不推荐)insmod --force-vermagic vmem_disk.ko# 方案3:确保使用相同版本的内核源码编译

❌ 错误2:缺少内核头文件

错误信息

fatal error: linux/blkdev.h: No such file or directory

解决方案

# 确保 KDIR 指向正确的内核源码目录KDIR := /path/to/your/kernel/source

❌ 错误3:交叉编译工具链问题

错误信息

aarch64-linux-gnu-gcc: command not found

解决方案

# 安装交叉编译工具链(Ubuntu/Debian)sudo apt-get install gcc-aarch64-linux-gnu# 或使用内核自带的工具链export CROSS_COMPILE=aarch64-linux-gnu-export ARCH=arm64

4.2 运行时问题

❌ 问题1:设备节点不存在

症状/dev/vmem_disk 不存在

原因:驱动加载后没有自动创建设备节点(需要 root 权限或使用 mdev)

解决方案

# 方法1:手动创建设备节点mknod /dev/vmem_disk b 253 0chmod 666 /dev/vmem_disk# 方法2:使用 udev 规则(需要将规则文件拷贝到目标板)# 创建 /etc/udev/rules.d/99-vmem.rulesecho'KERNEL=="vmem_disk", SUBSYSTEM=="block", MODE="666"' > /etc/udev/rules.d/99-vmem.rulesudevadm settle

❌ 问题2:Permission denied

症状/dev/vmem_disk: Permission denied

解决方案

# 修改设备权限chmod 666 /dev/vmem_disk# 或以 root 身份运行su -

4.3 兼容性问题

⚠️ Linux 6.12 API 变更

旧 API (Linux 5.x)
新 API (Linux 6.x)
说明
alloc_disk()
 + blk_init_queue()
blk_mq_alloc_disk()
一步到位创建 gendisk 和队列
fmode_tblk_mode_t
open 函数的参数类型
struct request_queue
通过 blk_mq_alloc_disk() 间接创建
不再需要手动创建

4.4 性能优化技巧

🚀 技巧1:增大队列深度

vmem_dev->tag_set.queue_depth = 256;  // 默认128,可增大到256或512

🚀 技巧2:启用请求合并

vmem_dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;  // 允许合并相邻请求

🚀 技巧3:使用 DMA

对于真实硬件,考虑使用 DMA 减少 CPU 开销:

// 启用 DMA(需要硬件支持)blk_queue_flag_set(QUEUE_FLAG_NOMERGES, queue);  // 禁用合并以便 DMA

五、总结延伸

5.1 知识点回顾

通过本文,你应该掌握了以下核心知识点:

✅ 块设备驱动基础

  • 主设备号和次设备号的概念
  • gendisk 结构体的作用

✅ blk-mq 架构

  • 为什么要用多队列
  • 请求处理函数(queue_rq)的编写

✅ 驱动开发流程

  • 模块初始化和退出
  • 资源申请和释放
  • 错误处理

✅ 调试技巧

  • dmesg 日志查看
  • /proc/partitions 信息
  • lsmod 模块查看

5.2 拓展学习方向

如果你对块设备驱动感兴趣,可以继续学习:

📚 进阶内容

  1. 真实块设备驱动开发:如 SD 卡、MMC、NVMe 等
  2. 请求调度算法:了解 CFQ、Deadline、mq-deadline 等
  3. 分区管理:实现自动分区和分区表解析
  4. IO 性能优化:使用 blktrace 分析 I/O 性能

🔧 相关项目

  1. 尝试添加 ioctl 接口支持自定义操作
  2. 实现设备的热插拔支持
  3. 添加省电模式(runtime PM)

参考资料

  • Linux Block Device Driver Documentation
  • Linux Device Drivers, 3rd Edition
  • blk-mq documentation

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 15:35:06 HTTP/2.0 GET : https://f.mffb.com.cn/a/495224.html
  2. 运行时间 : 0.435305s [ 吞吐率:2.30req/s ] 内存消耗:4,601.16kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=dbc0fd8e5c2177317d03d0d2cc6fec72
  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.001078s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001896s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.006270s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000736s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001496s ]
  6. SELECT * FROM `set` [ RunTime:0.014059s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001618s ]
  8. SELECT * FROM `article` WHERE `id` = 495224 LIMIT 1 [ RunTime:0.003284s ]
  9. UPDATE `article` SET `lasttime` = 1783064106 WHERE `id` = 495224 [ RunTime:0.024230s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000834s ]
  11. SELECT * FROM `article` WHERE `id` < 495224 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.010412s ]
  12. SELECT * FROM `article` WHERE `id` > 495224 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.035139s ]
  13. SELECT * FROM `article` WHERE `id` < 495224 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.025306s ]
  14. SELECT * FROM `article` WHERE `id` < 495224 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.026216s ]
  15. SELECT * FROM `article` WHERE `id` < 495224 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.121011s ]
0.439118s