【底层机制】Linux内核4.10版本的完整存储栈架构讲解--用户空间到物理设备完整IO路径

这张图详细展示了Linux内核4.10版本的完整存储栈架构,从用户空间到物理设备的完整I/O路径。

整体架构概览

Linux存储栈采用分层架构,每层都有明确的职责:

复制代码
用户空间应用 → VFS → 文件系统 → 页面缓存 → 块层 → I/O调度 → 设备驱动 → 物理设备

1. 用户空间 (Userspace)

系统调用接口

  • vfs_writev, vfs_read, ...:虚拟文件系统提供的系统调用
  • 用户空间文件系统:如sshfs,通过FUSE实现

关键知识点

  • 应用程序通过系统调用进入内核态
  • 所有文件操作首先经过VFS层
  • FUSE允许在用户空间实现文件系统

2. 虚拟文件系统 (VFS - Virtual File System)

作用

  • 提供统一的文件操作接口,抽象不同文件系统的差异
  • 实现通用的文件系统功能(目录缓存、inode缓存等)

支持的文件系统类型

块设备文件系统
  • ext2/ext3/ext4:Linux传统文件系统
  • XFS:高性能日志文件系统
  • Btrfs:带快照和校验的现代文件系统
网络文件系统
  • NFS:网络文件系统
  • CIFS:Common Internet File System
  • Ceph:分布式文件系统
伪文件系统
  • proc:进程信息文件系统
  • sysfs:系统设备信息
  • tmpfs:临时文件系统
特殊用途文件系统
  • FUSE:用户空间文件系统
  • 其他专用文件系统

3. 页面缓存 (Page Cache)

功能

  • 缓存文件数据,减少磁盘访问
  • 使用LRU等算法管理缓存页面
  • 处理匿名页(anonymous pages)和文件页

工作机制

c 复制代码
// 页面缓存核心数据结构
struct address_space {
    struct inode    *host;      // 所属inode
    struct radix_tree_root page_tree; // 页面树
    // ...
};

4. 块I/O层 (Block I/O Layer)

BIO结构体 (Block I/O)

c 复制代码
struct bio {
    sector_t        bi_sector;      // 磁盘扇区
    unsigned int    bi_size;        // 数据大小
    struct bio_vec  *bi_io_vec;     // bio向量
    unsigned int    bi_idx;         // 当前向量索引
    // ...
};

struct bio_vec {
    struct page     *bv_page;       // 物理页面
    unsigned int    bv_len;         // 长度
    unsigned int    bv_offset;      // 偏移
};

BIO处理流程

  1. 文件系统将I/O请求转换为BIO
  2. BIO包含要读写的磁盘位置和内存位置
  3. 支持分散/聚集I/O(scatter-gather)

5. I/O调度层 (I/O Scheduler)

调度器类型

CFQ (Completely Fair Queuing)
  • 为每个进程维护独立的I/O队列
  • 公平分配I/O带宽
  • 适合桌面系统
Deadline
  • 每个请求有截止时间
  • 防止请求饥饿
  • 适合数据库应用
NOOP
  • 简单的FIFO队列
  • 不进行重新排序
  • 适合SSD和智能存储设备
多队列调度器 (blk-mq)
  • 为多核系统设计
  • 减少锁竞争
  • 软件队列 + 硬件分发队列

6. 设备映射层 (Device Mapper)

功能

  • 提供逻辑卷管理
  • 支持快照、条带化、镜像等

目标设备

  • dm-multipath:多路径I/O
  • dm-thin:精简配置
  • dm-crypt:设备加密

7. SCSI子系统

SCSI中间层 (SCSI Mid Layer)

  • 提供统一的SCSI设备抽象
  • 处理SCSI命令和响应

SCSI上层驱动

  • sd :SCSI磁盘驱动 (/dev/sda, /dev/sdb)
  • sr :SCSI光盘驱动 (/dev/sr0)
  • st:SCSI磁带驱动
  • sg:通用SCSI设备

其他块设备驱动

  • virtio_blk:虚拟化块设备
  • nbd:网络块设备
  • loop:回环设备
  • mmcblk:MMC/SD卡设备
  • ubd:用户模式Linux块设备

8. 传输类和sysfs

传输类

  • scsi_transport_fc:光纤通道
  • scsi_transport_sas:SAS接口
  • 其他传输协议

sysfs集成

  • 通过/sys/class/scsi_host/等路径暴露设备属性
  • 提供统一的管理接口

9. 底层设备驱动

SCSI低层驱动 (LLDs)

  • libata:SATA/AHCI驱动
  • mpt3sas:LSI SAS 12Gbps驱动
  • qla2xxx:QLogic光纤通道
  • virtio_scsi:虚拟化SCSI

其他存储接口

  • NVMe:非易失性内存快速
  • UFS:通用闪存存储(移动设备)
  • 各种HBA卡驱动

10. 物理设备层

存储介质类型

  • HDD:机械硬盘
  • SSD:固态硬盘
  • DVD/CD:光盘
  • SD/MMC:闪存卡

接口技术

  • SAS:串行SCSI
  • SATA:串行ATA
  • PCIe:高速外围组件互联
  • FC:光纤通道

完整I/O路径示例

读取文件的数据流

复制代码
应用程序read() → VFS → 文件系统 → 页面缓存检查 → 
    ↓ (缓存未命中)
创建BIO → I/O调度器 → 设备驱动 → SCSI命令 → 物理设备
    ↑
数据返回 → DMA到内存 → 完成中断 → 唤醒进程

写入文件的数据流

复制代码
应用程序write() → VFS → 文件系统 → 页面缓存 → 
    ↓ (延迟写入)
标记页面为脏 → 定期刷回或显式sync
    ↓ (立即写入)
创建BIO → I/O调度 → 设备驱动 → 物理设备

关键技术和优化

1. 多队列块层 (blk-mq)

  • 解决多核系统的锁竞争问题
  • 软件队列处理I/O准备
  • 硬件队列直接映射到CPU核心

2. 直接I/O (Direct I/O)

  • 绕过页面缓存
  • 适合数据库等自缓存应用
  • 使用O_DIRECT标志

3. 异步I/O

  • 非阻塞I/O操作
  • 提高并发性能
  • 使用libaio或内核AIO

4. 内存映射 (mmap)

  • 将文件直接映射到进程地址空间
  • 减少数据拷贝
  • 按需分页

性能调优要点

I/O调度器选择

  • HDD:CFQ或Deadline
  • SSD:NOOP或Deadline
  • NVMe:使用多队列(none调度器)

队列深度优化

  • 调整/sys/block/sdX/queue/nr_requests
  • 增加队列深度提高并行性

预读优化

  • 调整/sys/block/sdX/queue/read_ahead_kb
  • 适合顺序读场景

现代发展趋势

1. NVMe over Fabrics

  • 远程直接访问NVMe设备
  • 支持RDMA、TCP等传输

2. computational Storage

  • 在存储设备上执行计算
  • 减少数据传输

3. 持久内存

  • 字节寻址的持久存储
  • 新的编程模型要求

这个存储栈架构体现了Linux内核设计的模块化、可扩展性思想,每层都可以独立发展和优化,同时保持清晰的接口和职责分离。理解这个架构对于系统性能调优、存储问题排查和存储系统开发都至关重要。

相关推荐
开心-开心急了3 小时前
conda 命令使用进阶指南 minconda
conda·1024程序员节·minconda
王哈哈^_^3 小时前
PyTorch vs TensorFlow:从入门到落地的全方位对比
人工智能·pytorch·python·深度学习·计算机视觉·tensorflow·1024程序员节
琴剑飘零西复东3 小时前
低代码市场深度分析:数字化转型的加速器与挑战
低代码·1024程序员节
yi碗汤园3 小时前
【一文了解】八大排序-冒泡排序、选择排序
开发语言·前端·算法·unity·c#·1024程序员节
Wang's Blog3 小时前
Linux小课堂: 网络接口与连接监控命令详解
linux·运维·服务器
止观止3 小时前
JSON Web Token (JWT) 全面解析:原理、优缺点与最佳实践
jwt·1024程序员节·authz·authn
纳切威4 小时前
CentOS 10 系统安装
linux
apolloyhl4 小时前
Linux目录
linux