1233434235

@[toc]


  **团队博客:** [**汽车电子社区**](https://bbs.csdn.net/forums/automotive-electronics)


1. 概述

  Block模块是Linux内核I/O子系统的核心组件,负责管理块设备的I/O操作。该模块提供标准化的接口来处理块设备的读写请求,支持多种I/O调度算法、块设备管理、分区处理和高级功能如完整性校验和加密。

2. 软件架构图

```mermaid

graph TB

subgraph "用户空间"

U1[文件系统]

U2[存储管理工具]

U3[性能监控工具]

U4[系统管理工具]

end

subgraph "内核空间"

subgraph "Block核心"

B1[blk-core.c<br/>核心API]

B2[blk-settings.c<br/>设备设置]

B3[blk-sysfs.c<br/>系统接口]

B4[blk-mq.c<br/>多队列核心]

end

subgraph "请求处理"

R1[blk-merge.c<br/>请求合并]

R2[blk-softirq.c<br/>软中断处理]

R3[blk-timeout.c<br/>超时处理]

R4[blk-iopoll.c<br/>I/O轮询]

end

subgraph "I/O调度"

S1[blk-mq-sched.c<br/>MQ调度框架]

S2[deadline-iosched.c<br/>Deadline调度器]

S3[bfq-iosched.c<br/>BFQ调度器]

S4[kyber-iosched.c<br/>Kyber调度器]

end

subgraph "块设备管理"

D1[genhd.c<br/>通用块设备]

D2[partition-generic.c<br/>分区管理]

D3[ioctl.c<br/>IO控制]

D4[bdev.c<br/>块设备操作]

end

subgraph "高级功能"

A1[blk-integrity.c<br/>完整性校验]

A2[blk-crypto.c<br/>块加密]

A3[blk-cgroup.c<br/>控制组]

A4[blk-throttle.c<br/>I/O节流]

end

subgraph "统计与监控"

M1[blk-stat.c<br/>I/O统计]

M2[blk-mq-debugfs.c<br/>调试接口]

M3[blk-trace.c<br/>I/O跟踪]

M4[blk-rq-qos.c<br/>QoS控制]

end

end

subgraph "文件系统"

F1[ext4]

F2[xfs]

F3[btrfs]

F4[vfs]

end

subgraph "设备驱动"

Dev1[NVMe驱动]

Dev2[SATA驱动]

Dev3[SCSI驱动]

Dev4[虚拟设备]

end

U1 --> B1

U2 --> B1

U3 --> M1

F1 --> B1

F2 --> B1

F3 --> B1

B1 --> R1

B1 --> S1

B1 --> D1

B1 --> A1

S1 --> S2

S1 --> S3

S1 --> S4

D1 --> D2

D1 --> D3

A1 --> A2

B1 --> M1

Dev1 --> B4

Dev2 --> B4

Dev3 --> B4

style B1 fill:#e1f5fe

style S1 fill:#f3e5f5

style F1 fill:#fff3e0

```

3. 调用流程图

```mermaid

sequenceDiagram

participant FS as 文件系统

participant Block as Block核心

participant Scheduler as I/O调度器

participant Device as 块设备驱动

participant Completion as 完成处理

FS->>Block: 提交I/O请求

Block->>Block: 创建请求对象

Block->>Scheduler: 请求入队

Scheduler->>Scheduler: 调度算法处理

Scheduler->>Block: 返回处理后请求

Block->>Device: 发送请求到设备

Device->>Device: 执行实际I/O

Device->>Completion: I/O完成通知

Completion->>Block: 完成处理

Block->>FS: 返回I/O结果

Note right of Scheduler: 多种调度算法可选

Note right of Device: 支持多队列并发

Note right of Completion: 软中断或轮询处理

```

4. Block子系统架构类图

```mermaid

classDiagram

class blk_core {

+blk_queue_make_request()

+blk_queue_bio()

+blk_queue_cleanup()

+blk_start_queue()

+blk_stop_queue()

+blk_queue_bounce()

+blk_queue_dma_alignment()

+blk_queue_max_segments()

+blk_queue_max_discard_segments()

+blk_queue_max_write_zeroes_segments()

}

class blk_mq {

+blk_mq_alloc_tag_set()

+blk_mq_free_tag_set()

+blk_mq_init_queue()

+blk_mq_alloc_request()

+blk_mq_free_request()

+blk_mq_submit_bio()

+blk_mq_map_queue()

+blk_mq_queue_tag_busy_iter()

+blk_mq_complete_request()

+blk_mq_start_request()

+blk_mq_end_request()

}

class blk_merge {

+blk_merge_requests()

+blk_attempt_req_merge()

+blk_attempt_plug_merge()

+blk_rq_merge_ok()

+blk_rq_mergeable()

+blk_rq_pos_less()

+blk_rq_bytes_less()

+blk_rq_sectors_less()

+blk_rq_cmp()

+blk_rq_is_passthrough()

}

class blk_softirq {

+blk_softirq_init()

+blk_softirq_exit()

+blk_softirq_run()

+blk_complete_request()

+blk_done_softirq()

+blk_complete_request_async()

+blk_complete_request_sync()

+blk_complete_request_flush()

}

class blk_timeout {

+blk_add_timer()

+blk_delete_timer()

+blk_rq_timed_out()

+blk_rq_timed_out_timer()

+blk_rq_check_expired()

+blk_rq_reset_timer()

+blk_rq_init_timer()

+blk_rq_timeout()

+blk_rq_timeout_handler()

}

class blk_iopoll {

+blk_iopoll_init()

+blk_iopoll_exit()

+blk_iopoll_sched()

+blk_iopoll_run()

+blk_iopoll_complete()

+blk_iopoll_disable()

+blk_iopoll_enable()

+blk_iopoll_queue()

+blk_iopoll_softirq()

}

class blk_integrity {

+blk_integrity_register()

+blk_integrity_unregister()

+blk_integrity_compare()

+blk_integrity_add()

+blk_integrity_merge()

+blk_integrity_split()

+blk_integrity_clone()

+blk_integrity_prep()

+blk_integrity_complete()

+blk_integrity_endio()

}

class blk_crypto {

+blk_crypto_register()

+blk_crypto_unregister()

+blk_crypto_start_using()

+blk_crypto_stop_using()

+blk_crypto_evict_key()

+blk_crypto_keyslot_program()

+blk_crypto_keyslot_evict()

+blk_crypto_keyslot_find()

+blk_crypto_keyslot_alloc()

+blk_crypto_keyslot_free()

}

class blk_cgroup {

+blk_cgroup_init()

+blk_cgroup_exit()

+blk_cgroup_add()

+blk_cgroup_remove()

+blk_cgroup_path()

+blk_cgroup_css()

+blk_cgroup_bio_start()

+blk_cgroup_bio_end()

+blk_cgroup_throttle()

+blk_cgroup_io_stat()

}

class blk_throttle {

+blk_throttle_init()

+blk_throttle_exit()

+blk_throttle_bio()

+blk_throttle_drain()

+blk_throttle_update_limits()

+blk_throttle_dispatch()

+blk_throttle_charge_bio()

+blk_throttle_uncharge_bio()

+blk_throttle_wait()

+blk_throttle_schedule_delayed()

}

class blk_stat {

+blk_stat_init()

+blk_stat_exit()

+blk_stat_add()

+blk_stat_get()

+blk_stat_reset()

+blk_stat_alloc()

+blk_stat_free()

+blk_stat_show()

+blk_stat_start()

+blk_stat_end()

}

class blk_mq_debugfs {

+blk_mq_debugfs_init()

+blk_mq_debugfs_exit()

+blk_mq_debugfs_register()

+blk_mq_debugfs_unregister()

+blk_mq_debugfs_queue_add()

+blk_mq_debugfs_queue_remove()

+blk_mq_debugfs_hctx_add()

+blk_mq_debugfs_hctx_remove()

+blk_mq_debugfs_ctx_add()

+blk_mq_debugfs_ctx_remove()

}

class blk_trace {

+blk_trace_init()

+blk_trace_exit()

+blk_trace_startstop()

+blk_trace_setup()

+blk_trace_remove()

+blk_trace_ioctl()

+blk_trace_shutdown()

+blk_trace_free()

+blk_trace_run()

+blk_trace_dump()

}

class blk_rq_qos {

+blk_rq_qos_init()

+blk_rq_qos_exit()

+blk_rq_qos_add()

+blk_rq_qos_remove()

+blk_rq_qos_throttle()

+blk_rq_qos_merge()

+blk_rq_qos_split()

+blk_rq_qos_clone()

+blk_rq_qos_prep()

+blk_rq_qos_complete()

}

blk_core --> blk_mq : uses

blk_core --> blk_merge : uses

blk_core --> blk_softirq : uses

blk_core --> blk_timeout : uses

blk_core --> blk_iopoll : uses

blk_core --> blk_integrity : uses

blk_core --> blk_crypto : uses

blk_core --> blk_cgroup : uses

blk_core --> blk_throttle : uses

blk_core --> blk_stat : uses

blk_core --> blk_mq_debugfs : uses

blk_core --> blk_trace : uses

blk_core --> blk_rq_qos : uses

blk_mq --> blk_mq_tag_set : manages

blk_cgroup --> blk_throttle : uses

blk_stat --> blk_trace : uses

```

5. 状态机分析

5.1. Block请求处理状态机

```mermaid

stateDiagram-v2

\*\] --\> REQUEST_CREATED: 请求创建 REQUEST_CREATED --\> REQUEST_QUEUED: 请求入队 REQUEST_QUEUED --\> REQUEST_MERGED: 请求合并 REQUEST_MERGED --\> REQUEST_SCHEDULED: 调度处理 REQUEST_SCHEDULED --\> REQUEST_DISPATCHED: 请求分发 REQUEST_DISPATCHED --\> REQUEST_ACTIVE: 设备处理 REQUEST_ACTIVE --\> REQUEST_COMPLETED: 处理完成 REQUEST_COMPLETED --\> REQUEST_FINISHED: 完成处理 REQUEST_FINISHED --\> \[\*

note right of REQUEST_QUEUED : 进入I/O调度器队列

note right of REQUEST_MERGED : 与相邻请求合并

note right of REQUEST_SCHEDULED : 调度算法处理

note right of REQUEST_DISPATCHED : 发送到设备驱动

note right of REQUEST_COMPLETED : 设备完成通知

```

5.2. Block I/O调度状态机

```mermaid

stateDiagram-v2

\*\] --\> SCHEDULER_IDLE: 调度器空闲 SCHEDULER_IDLE --\> REQUEST_ARRIVED: 请求到达 REQUEST_ARRIVED --\> MERGE_CHECK: 合并检查 MERGE_CHECK --\> REQUEST_MERGED: 合并成功 MERGE_CHECK --\> QUEUE_INSERT: 无法合并 REQUEST_MERGED --\> QUEUE_INSERT: 插入队列 QUEUE_INSERT --\> SCHEDULE_DECISION: 调度决策 SCHEDULE_DECISION --\> REQUEST_DISPATCHED: 请求分发 REQUEST_DISPATCHED --\> WAIT_COMPLETION: 等待完成 WAIT_COMPLETION --\> COMPLETION_ARRIVED: 完成到达 COMPLETION_ARRIVED --\> SCHEDULER_IDLE: 返回空闲 note right of MERGE_CHECK : 检查前向/后向合并 note right of SCHEDULE_DECISION : 算法特定的调度逻辑 note right of WAIT_COMPLETION : 可能使用轮询或中断 \`\`\` ## 5.3. Block设备管理状态机 \`\`\`mermaid stateDiagram-v2 \[\*\] --\> DEVICE_UNREGISTERED: 设备未注册 DEVICE_UNREGISTERED --\> DEVICE_REGISTERING: 注册开始 DEVICE_REGISTERING --\> DEVICE_REGISTERED: 注册完成 DEVICE_REGISTERED --\> DEVICE_ACTIVE: 设备激活 DEVICE_ACTIVE --\> DEVICE_SUSPENDED: 设备挂起 DEVICE_SUSPENDED --\> DEVICE_ACTIVE: 设备恢复 DEVICE_ACTIVE --\> DEVICE_REMOVING: 设备移除 DEVICE_REMOVING --\> DEVICE_UNREGISTERED: 移除完成 note right of DEVICE_REGISTERING : 分配设备号和资源 note right of DEVICE_ACTIVE : 处理I/O请求 note right of DEVICE_SUSPENDED : 电源管理状态 note right of DEVICE_REMOVING : 清理资源和队列 \`\`\` ## 5.4. Block多队列处理状态机 \`\`\`mermaid stateDiagram-v2 \[\*\] --\> MQ_INITIALIZING: 多队列初始化 MQ_INITIALIZING --\> MQ_READY: 多队列就绪 MQ_READY --\> MQ_ACTIVE: 多队列激活 MQ_ACTIVE --\> MQ_QUEUEING: 请求入队 MQ_QUEUEING --\> MQ_DISPATCHING: 请求分发 MQ_DISPATCHING --\> MQ_COMPLETING: 完成处理 MQ_COMPLETING --\> MQ_ACTIVE: 继续处理 MQ_ACTIVE --\> MQ_SUSPENDING: 多队列挂起 MQ_SUSPENDING --\> MQ_SUSPENDED: 多队列挂起完成 MQ_SUSPENDED --\> MQ_ACTIVE: 多队列恢复 note right of MQ_INITIALIZING : 创建硬件/软件上下文 note right of MQ_QUEUEING : 请求分配到特定队列 note right of MQ_DISPATCHING : 并发处理多个请求 note right of MQ_SUSPENDING : 停止新请求入队 \`\`\` # 6. 源码分析 ## 6.1. 核心数据结构分析 ### 6.1.1 request_queue结构体分析 \ \ request_queue是Block模块请求队列的核心数据结构: \`\`\`c struct request_queue { struct request \*last_merge; // 最后合并的请求 struct elevator_queue \*elevator; // I/O调度器 struct blk_mq_tag_set \*tag_set; // 多队列标签集 struct list_head queue_head; // 请求队列头 struct blk_queue_stats stats; // 队列统计 unsigned int nr_requests; // 请求数量 struct rcu_head rcu_head; // RCU回调 struct kobject kobj; // 内核对象 }; \`\`\` \ \ 该结构体管理所有I/O请求的队列和调度。 ### 6.1.2 request结构体分析 \ \ request定义了I/O请求的具体内容: \`\`\`c struct request { struct request_queue \*q; // 所属队列 struct bio \*bio; // 关联的bio struct bio \*biotail; // bio链表尾 struct list_head queuelist; // 队列链表节点 unsigned int cmd_flags; // 命令标志 sector_t __sector; // 起始扇区 unsigned int __data_len; // 数据长度 struct gendisk \*rq_disk; // 目标磁盘 blk_status_t errors; // 错误状态 refcount_t ref; // 引用计数 }; \`\`\` \ \ 该结构体表示单个I/O请求的完整信息。 ### 6.1.3 bio结构体分析 \ \ bio定义了块I/O的基本单位: \`\`\`c struct bio { struct bio \*bi_next; // 下一个bio struct block_device \*bi_bdev; // 块设备 struct bio_vec \*bi_io_vec; // I/O向量数组 struct bio_vec bi_inline_vecs\[4\]; // 内联向量 bio_end_io_t \*bi_end_io; // 完成回调 void \*bi_private; // 私有数据 unsigned short bi_vcnt; // 向量数量 unsigned short bi_max_vecs; // 最大向量数 unsigned int bi_opf; // 操作标志 sector_t bi_iter.bi_sector; // 当前扇区 }; \`\`\` \ \ 该结构体表示块I/O操作的基本单位。 ### 6.1.4 gendisk结构体分析 \ \ gendisk定义了通用磁盘的抽象: \`\`\`c struct gendisk { int major; // 主设备号 int first_minor; // 起始次设备号 int minors; // 次设备号数量 char disk_name\[32\]; // 磁盘名称 struct block_device_operations \*fops; // 操作函数 struct request_queue \*queue; // 请求队列 struct disk_part_tbl \*part_tbl; // 分区表 struct hd_struct \*part0; // 整体分区 struct rcu_head rcu_head; // RCU回调 unsigned int flags; // 磁盘标志 sector_t capacity; // 容量 }; \`\`\` \ \ 该结构体表示物理或虚拟磁盘设备。 ## 6.2. 核心算法分析 ### 6.2.1 请求合并算法 \ \ 请求合并的高效算法: \`\`\`c bool blk_attempt_req_merge(struct request_queue \*q, struct request \*rq, struct request \*next){ if (!blk_rq_merge_ok(rq, next)) return false; if (blk_rq_pos_less(rq, next)) { // 后向合并 if (blk_rq_sectors_less(rq, next) \&\& (rq-\>cmd_flags \& REQ_NOMERGE) == 0) { if (blk_rq_mergeable(rq, next)) return blk_rq_merge(rq, next); } } else { // 前向合并 if (blk_rq_sectors_less(next, rq) \&\& (next-\>cmd_flags \& REQ_NOMERGE) == 0) { if (blk_rq_mergeable(next, rq)) return blk_rq_merge(next, rq); } } return false; } \`\`\` \ \ 该算法实现请求的前向和后向合并。 ### 6.2.2 I/O调度算法 \ \ I/O调度的核心算法: \`\`\`c void elv_dispatch_sort(struct request_queue \*q, struct request \*rq) { struct elevator_queue \*e = q-\>elevator; struct list_head \*entry; if (e-\>ops-\>elevator_dispatch_fn) return e-\>ops-\>elevator_dispatch_fn(q, rq); // 默认调度逻辑 list_for_each_prev(entry, \&q-\>queue_head) { struct request \*pos = list_entry_rq(entry); if (blk_rq_pos_less(pos, rq)) break; } list_add(\&rq-\>queuelist, entry-\>next); } \`\`\` \ \ 该算法实现请求的调度和排序。 ### 6.2.3 多队列分配算法 \ \ 多队列请求分配算法: \`\`\`c struct blk_mq_hw_ctx \*blk_mq_map_queue(struct request_queue \*q, unsigned int flags, const struct blk_mq_queue_data \*qd) { struct blk_mq_tag_set \*set = q-\>tag_set; struct blk_mq_hw_ctx \*hctx; int cpu; // 获取当前CPU cpu = blk_mq_get_cpu(q, qd); // 映射到硬件上下文 hctx = set-\>ops-\>map_queue(q, cpu); if (!hctx \|\| !blk_mq_hw_queue_mapped(hctx)) hctx = blk_mq_find_hctx(q, cpu); return hctx; } \`\`\` \ \ 该算法实现请求到多队列的映射。 ## 6.3 核心函数分析 ### 6.3.1 blk_queue_make_request函数分析 \ \ 请求创建的核心实现: \`\`\`c blk_qc_t blk_queue_make_request(struct request_queue \*q, struct bio \*bio) { struct request \*rq; int el_ret; // 创建请求对象 rq = blk_get_request(q, bio_data_dir(bio), bio-\>bi_opf); // 初始化请求 for_each_bio(bio) blk_rq_bio_prep(q, rq, bio); // 合并检查 el_ret = elv_merge(q, \&rq, bio); if (el_ret == ELEVATOR_BACK_MERGE) return BLK_QC_T_NONE; // 添加到调度器 if (!blk_rq_merge_ok(rq, bio)) elv_insert(q, rq, el_ret); // 触发调度 __blk_run_queue(q); return BLK_QC_T_NONE; } \`\`\` \ \ 该函数实现请求的完整创建流程。 ### 6.3.2 blk_mq_submit_bio函数分析 \ \ 多队列bio提交的核心实现: \`\`\`c blk_qc_t blk_mq_submit_bio(struct bio \*bio) { struct request_queue \*q = bdev_get_queue(bio-\>bi_bdev); struct blk_mq_hw_ctx \*hctx; struct request \*rq; blk_qc_t cookie; // 获取硬件上下文 hctx = blk_mq_map_queue(q, 0, \&bio-\>bi_qd); // 创建请求 cookie = blk_mq_get_tag(hctx, bio, \&rq); if (blk_qc_t_is_internal(cookie)) return cookie; // 初始化请求 blk_mq_init_request(rq, bio, cookie); // 提交请求 blk_mq_put_tag(hctx, cookie); blk_mq_run_hw_queue(hctx, true); return cookie; } \`\`\` \ \ 该函数实现多队列bio的提交流程。 ### 6.3.3 blk_mq_run_hw_queue函数分析 \ \ 硬件队列运行的核心实现: \`\`\`c void blk_mq_run_hw_queue(struct blk_mq_hw_ctx \*hctx, bool async) { int srcu_idx; // 获取SRCU索引 srcu_idx = srcu_read_lock(\&hctx-\>queue_rq_srcu); // 处理队列 if (!blk_mq_hw_queue_mapped(hctx)) { srcu_read_unlock(\&hctx-\>queue_rq_srcu, srcu_idx); return; } // 调度请求 if (hctx-\>run_work) { if (!async) hctx-\>run_work-\>func(hctx-\>run_work); } else { __blk_mq_run_hw_queue(hctx); } srcu_read_unlock(\&hctx-\>queue_rq_srcu, srcu_idx); } \`\`\` \ \ 该函数实现硬件队列的运行和调度。 ## 6.4 事件处理流程分析 ### 6.4.1 请求完成处理 \ \ 请求完成的事件处理流程: \`\`\`c void blk_complete_request(struct request \*rq) { struct request_queue \*q = rq-\>q; unsigned long flags; // 完成请求 if (blk_rq_is_passthrough(rq)) blk_end_request_all(rq); else __blk_end_request_all(rq, rq-\>errors); // 更新统计 blk_account_io_completion(rq, rq-\>nr_sectors); // 触发后续处理 if (q-\>mq_ops) blk_mq_complete_request(rq); else __blk_complete_request(rq); // 释放请求 blk_put_request(rq); } \`\`\` \ \ 该流程处理请求的完成和资源释放。 ### 6.4.2 超时处理 \ \ 请求超时的事件处理: \`\`\`c void blk_rq_timed_out(struct request \*rq) { struct request_queue \*q = rq-\>q; enum blk_eh_timer_return ret; // 检查超时 if (blk_rq_check_expired(rq)) return; // 调用超时处理 ret = q-\>mq_ops-\>timeout(rq, true); if (ret == BLK_EH_DONE) return; // 重置定时器 blk_rq_reset_timer(rq); // 重试或错误处理 if (ret == BLK_EH_RESET_TIMER) blk_add_timer(rq); else blk_rq_timeout(rq); } \`\`\` \ \ 该流程处理请求的超时和错误恢复。 # 7. 设计模式 ## 7.1 策略模式(Strategy Pattern) \ \ Block模块使用策略模式处理不同的I/O调度算法: \`\`\`c // I/O调度策略接口 struct elevator_type { struct list_head list; struct elevator_ops \*ops; struct kobj_type \*elevator_ktype; struct module \*elevator_owner; }; // Deadline策略实现 static struct elevator_type elevator_deadline = { .ops = { .elevator_merge_fn = deadline_merge, .elevator_dispatch_fn = deadline_dispatch, .elevator_add_req_fn = deadline_add_request, .elevator_remove_req_fn = deadline_remove_request, .elevator_requeue_req_fn = deadline_requeue_request, .elevator_drain_elevator_fn = deadline_drain_elevator, }, .elevator_ktype = \&deadline_kobj_ktype, .elevator_owner = THIS_MODULE, }; // BFQ策略实现 static struct elevator_type elevator_bfq = { .ops = { .elevator_merge_fn = bfq_merge, .elevator_dispatch_fn = bfq_dispatch, .elevator_add_req_fn = bfq_add_request, .elevator_remove_req_fn = bfq_remove_request, .elevator_requeue_req_fn = bfq_requeue_request, .elevator_drain_elevator_fn = bfq_drain_elevator, }, .elevator_ktype = \&bfq_kobj_ktype, .elevator_owner = THIS_MODULE, }; \`\`\` \ \ 不同I/O调度算法使用不同的处理策略。 ## 7.2 工厂模式(Factory Pattern) \ \ Block模块使用工厂模式创建请求对象: \`\`\`c struct request \*blk_get_request(struct request_queue \*q, unsigned int op, blk_mq_req_flags_t flags) { struct request \*rq; // 分配请求结构 rq = blk_mq_alloc_request(q, op, flags); if (!rq) return ERR_PTR(-ENOMEM); // 初始化请求 blk_rq_init(q, rq); rq-\>cmd_flags = op; // 根据类型初始化 switch (op) { case REQ_OP_READ: case REQ_OP_WRITE: // 普通I/O请求 break; case REQ_OP_DISCARD: case REQ_OP_SECURE_ERASE: // 抛弃/安全擦除请求 break; case REQ_OP_FLUSH: case REQ_OP_FUA: // 刷新请求 break; default: // 其他类型请求 break; } return rq; } \`\`\` \ \ 工厂方法创建不同类型的请求对象。 ## 7.3 观察者模式(Observer Pattern) \ \ Block模块实现观察者模式处理I/O事件: \`\`\`c // I/O事件观察者 struct blk_io_observer { void (\*io_start)(struct request \*rq); void (\*io_complete)(struct request \*rq); void (\*io_error)(struct request \*rq, blk_status_t status); struct list_head list; }; // 注册观察者 int blk_register_io_observer(struct blk_io_observer \*observer) { mutex_lock(\&blk_io_mutex); list_add(\&observer-\>list, \&blk_io_observers); mutex_unlock(\&blk_io_mutex); return 0; } // 通知观察者 static void blk_notify_io_event(enum blk_io_event event, struct request \*rq) { struct blk_io_observer \*observer; mutex_lock(\&blk_io_mutex); list_for_each_entry(observer, \&blk_io_observers, list) { switch (event) { case BLK_IO_START: if (observer-\>io_start) observer-\>io_start(rq); break; case BLK_IO_COMPLETE: if (observer-\>io_complete) observer-\>io_complete(rq); break; case BLK_IO_ERROR: if (observer-\>io_error) observer-\>io_error(rq, rq-\>errors); break; } } mutex_unlock(\&blk_io_mutex); } \`\`\` \ \ 观察者模式通知I/O事件变更。 ## 7.4 组合模式(Composite Pattern) \ \ Block模块使用组合模式组织请求和bio: \`\`\`c // 请求组合结构 struct request { struct bio \*bio; // bio链表头 struct bio \*biotail; // bio链表尾 }; // 叶子节点:bio结构 struct bio { struct bio \*bi_next; // 下一个bio struct bio_vec \*bi_io_vec; // I/O向量数组 }; // 组合操作 int blk_rq_append_bio(struct request \*rq, struct bio \*bio) { // 添加bio到请求 if (rq-\>biotail) rq-\>biotail-\>bi_next = bio; else rq-\>bio = bio; rq-\>biotail = bio; rq-\>__data_len += bio-\>bi_iter.bi_size; return 0; } \`\`\` \ \ 组合模式统一管理请求和bio的层次结构。 ## 7.5 模板方法模式(Template Method Pattern) \ \ Block模块使用模板方法处理I/O操作: \`\`\`c int blk_execute_rq_template(struct request_queue \*q, struct request \*rq, int at_head, blk_end_io_fn \*done) { int ret; // 1. 准备操作(钩子方法) ret = blk_prepare_rq(q, rq); if (ret) return ret; // 2. 执行I/O操作(抽象方法) ret = q-\>mq_ops-\>queue_rq(q, rq); if (ret) goto cleanup; // 3. 等待完成(钩子方法) if (done) rq-\>end_io = done; // 4. 发送通知(钩子方法) blk_notify_io_start(rq); return 0; cleanup: // 5. 清理操作(钩子方法) blk_cleanup_rq(q, rq); return ret; } \`\`\` \ \ 模板方法定义I/O操作的标准流程。 ## 7.6 单例模式(Singleton Pattern) \ \ Block模块使用单例模式管理全局请求队列: \`\`\`c static struct request_queue \*blk_get_queue(dev_t dev) { static DEFINE_MUTEX(init_mutex); static struct request_queue \*queue; mutex_lock(\&init_mutex); if (!queue) { queue = blk_alloc_queue(GFP_KERNEL); if (queue) blk_queue_init(queue); } mutex_unlock(\&init_mutex); return queue; } \`\`\` \ \ 确保请求队列的全局唯一性。 # 8. 总结 \ \ Block模块作为Linux内核I/O子系统的核心组件,成功实现了块设备的统一管理和高效I/O处理。通过精心设计的请求队列管理、I/O调度框架和多队列支持,Block模块提供了从传统单队列到现代多队列的完整演进路径。

相关推荐
徐同保2 小时前
开发onlyoffice插件,功能是选择文本后立即通知父页面
开发语言·前端·javascript
Never_Satisfied2 小时前
C#数组去重方法总结
开发语言·c#
阿蒙Amon2 小时前
C#每日面试题-静态构造函数和普通构造函数区别
java·开发语言·c#
Java程序员威哥2 小时前
SpringBoot4.0+JDK25+GraalVM:云原生Java的性能革命与落地指南
java·开发语言·后端·python·云原生·c#
青小莫2 小时前
C++之模板
android·java·c++
阿杰 AJie2 小时前
MyBatis-Plus 的内置方法
java·数据库·mybatis
牧小七2 小时前
java Base64 是什么
java
liu_sir_2 小时前
android9.0 amlogic 遥控器POWER按键的假待机的实现
开发语言·git·python
Da Da 泓2 小时前
多线程(八)【定时器】
java·学习·多线程·定时器