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核心"

B1blk-core.c\
核心API

B2blk-settings.c\
设备设置

B3blk-sysfs.c\
系统接口

B4blk-mq.c\
多队列核心

end

subgraph "请求处理"

R1blk-merge.c\
请求合并

R2blk-softirq.c\
软中断处理

R3blk-timeout.c\
超时处理

R4blk-iopoll.c\
I/O轮询

end

subgraph "I/O调度"

S1blk-mq-sched.c\
MQ调度框架

S2deadline-iosched.c\
Deadline调度器

S3bfq-iosched.c\
BFQ调度器

S4kyber-iosched.c\
Kyber调度器

end

subgraph "块设备管理"

D1genhd.c\
通用块设备

D2partition-generic.c\
分区管理

D3ioctl.c\
IO控制

D4bdev.c\
块设备操作

end

subgraph "高级功能"

A1blk-integrity.c\
完整性校验

A2blk-crypto.c\
块加密

A3blk-cgroup.c\
控制组

A4blk-throttle.c\
I/O节流

end

subgraph "统计与监控"

M1blk-stat.c\
I/O统计

M2blk-mq-debugfs.c\
调试接口

M3blk-trace.c\
I/O跟踪

M4blk-rq-qos.c\
QoS控制

end

end

subgraph "文件系统"

F1ext4

F2xfs

F3btrfs

F4vfs

end

subgraph "设备驱动"

Dev1NVMe驱动

Dev2SATA驱动

Dev3SCSI驱动

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_vecs4; // 内联向量

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_name32; // 磁盘名称

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 分钟前
LangChain4j使用文档
开发语言·python
程序员小羊!3 分钟前
12.Java 多线程编程
java·开发语言
xuhaoyu_cpp_java9 分钟前
项目学习(三)代码生成器
java·经验分享·笔记·学习
乐观勇敢坚强的老彭9 分钟前
C++信息学奥赛lesson1
java·开发语言·c++
San813_LDD14 分钟前
[深度学习] 数据序列化格式对比:以日志级别配置为例
xml·java·前端
jllllyuz16 分钟前
MATLAB实现滚动轴承故障诊断(外圈故障)
开发语言·人工智能·matlab
github_czy18 分钟前
更加优雅的类型检查与传参---mcp源码分析
java·服务器·开发语言
专注_每天进步一点点23 分钟前
IDEA中,Apifox Helper 的 2.0.15-243版本的插件 导出指定的接口,入参的中文名为空,描述为空
java·ide·intellij-idea
Irissgwe24 分钟前
C++ STL关联式容器详解:set、multiset、map、multimap
开发语言·c++·stl·set·map·multiset·关联式容器
兰令水24 分钟前
leecodecode【区间DP+树形DP】【2026.6.10打卡-java版本】
java·算法·leetcode