34 从磁盘读取数据到内存的调试

前言

我们大多数的文件是存储在磁盘上面的 

然后 我们通过 open + read/write 相关 api 是控制的是 磁盘 和 内存 之间的数据交互 

磁盘 到 内存, 或者 内存 到 磁盘 

我们这里 来大致看一下 磁盘到 内存的这一个过程 

 

 

调试读取磁盘数据到 page 的流程

这里的流程主要是包含如下 

1. 系统调用 read 封装读取数据的请求 

2. scsi 中间层初始化 scsi 的命令, 做一些准备工作 

3. 底层驱动[这里是 ata] 发送 ata 命令到具体的设备, 以基于 dma 将数据拷贝到内存 

 

 

1. 系统调用 read 封装读取数据的请求 

这个 读取磁盘的请求 封装成为一个 bio, 其中 bi_sector 表示的是需要读取的数据的 扇区 

比如这里的 sector 是 18220, 其计算是通过 ext4_map_blocks 根据 inode 获取的存储的 block 的相关信息, 进而 计算的 sector 

a843c0ea5a9042beb52f7dc3c08f633c.png

 

然后具体的请求的实际处理 是在这里开始处理的 

轮询队列中的请求, 然后 进行处理 

7f6921b2b8f64d058668bd65bcd42ff7.png

 

 

2. scsi 中间层初始化 scsi 的命令, 做一些准备工作 

这一层主要做的事情是 基于 bio 请求, 封装 request, 初始化 scsiCmd 

根据 bio 封装 scsiCmd, 两个步骤 get_request 是创建 request, init_request_from_bio 是根据 bio 初始化 request 的一部分配置 

ba8fd7e4372143c4bf26ac1dc440dbfd.png

 相对比较重要的数据传输主要是 __sector 字段cd383abb27b541cab62fa2d48b7e934b.png

 

 

将 scsiCmd 传递到 底层的驱动 

sd.sd_setup_read_write_cmnd 中 初始化 scsiCmd 的请求 

第一个字节为 读取命令
第二个字节为 flags
第三四五六字节为 block 的编号
第七字节为 0
第八九字节为 需要读取的连续的 扇区 的数量
第十字节 为 0
第一个字节,因为是读取命令,初始化为 READ_6, 使用十字节交互 + (READ_10 - READ_6), 因此第一个字节为 READ_10 为 28
(gdb) x /10gx 0xffff88007f746868
0xffff88007f746868:	0x0000844900000028	0x0000000000000002
0xffff88007f746878:	0xffff88007f746868	0x0000000000000010
0xffff88007f746888:	0x0000000000000000	0x0000000000000000
0xffff88007f746898:	0x0000000000000000	0xffff88007f7468a0
0xffff88007f7468a8:	0xffff88007f7468a0	0x00000000000000000x28 表示的是 读取指令 
0x00 flags 
0x000004984 表示待读取扇区的索引, 18220 
0x00 固定为 0
0x0002 为需要连续读取的 扇区的数量 
0x00 固定为 0

5f5d61218e2741f78958f94f58e0cdfd.png

 

然后接下来是将 scsiCmd 转换到底层设备 

da43dc3e13de40788ad3fe2a47be1e8d.png

查看一下 scsiCmd.cmnd 的数据, 和上面 一致 

(gdb) x /10gx 0xffff88007f746868
0xffff88007f746868:	0x0000844900000028	0x0000000000000002
0xffff88007f746878:	0xffff88007f746868	0x0000000000000010
0xffff88007f746888:	0x0000040000000000	0x0000000000000000
0xffff88007f746898:	0x000000010008a7f0	0xffff88007f8cf1e0
0xffff88007f7468a8:	0xffff88007f8cf1e0	0x0000000000001d4c

 

 

3. 底层驱动[这里是 ata] 发送 ata 命令到具体的设备, 以基于 dma 将数据拷贝到内存  

将 scsiCmd 转换为 ata 命令, 并向给定的 设备 发送请求 

这里 qc 就是 ata 设备的命令, 这里根据 scsiCmd 创建所需要的 ata_queue_cmd 

8d5b8056d31e4adb83c189b1eef0c86b.png

 

 

具体的步骤大概是如下三步, sff_qc_issue, bmdma_set_up, bmdma_start 

sff_tf_load 中传输 feature, block, n_blocks, scsi_command 中的 block, n_blocks 对应到 tf 中分别对应于,tf.lbah/lbam/lbal, tf.nsec 

bmdma_setup 中传输 bmdma.prd_dma,reset bmdma.start,command.ATA_READ 

bmdma_start 中传输 bmdma.start 

def4b3d00b1b4ecba0c511171b946fe5.png

 

sff_tf_load, 这里 tf->lbal, tf->lbam, tf->lbah 合计起来 73 * 256 + 132 = 18220 

c8a7139bfd564032a14aed28f8a38770.png

 bmdma_setup, 传递了三条指令  1649c8f52f65489da0542de5fb57a082.png

 

bmdma_start 传递了 start 命令

f72359212eec40fea0f9678a05e3a986.png

 

 

bio 使用的 page 如何 和 dma 关联起来的?

bio 使用的 page 的初始化是在 ext4_mpage_readpages 中初始化了 bio 请求之后 

将从 pagecache 中分配的 page, 挂在 bio 上面 

0232d850c7944bf5845cac174cc6edaa.png

 

这里将 bio 中的 bio->bi_io_vec和 scsi_cmd->sdb->table->sgl 的 scatterlist 关联起来 

15a1732cb7f3471e9aefd24733c8d4f5.png

 

然后后面新建 ata_queue_cmd 之后根据 scsi_cmd 初始化 ata_cmd 

如下图, 可以看到 这个对应关系 

8a0b165292fa42ed8e05bfa3ba8f7768.png

 

 然后 最后就是 dma 将数据从 设备读取, 拷贝到该 page 的流程了

这个 目前没有找到, 作为一个 todo, 后面回来补充 

 

 

拷贝的目标 page 来自于哪里?

这个 page 分配自这里的 pages, 来自于 page_pool 

ee1143b606994df299bd33aac1ae28bd.png

 

然后将该物理页放入 page_cache_tree, 根据 mapping 和 page->index 进行索引 

2ec07263778948ffa7eac7a9c952c04b.png

 

外面 find_get_page 也是通过 mapping 和 index 进行索引的, 查询的就是 page_cache_tree 中的物理页 

fc236b962bdb406aab07368946783a21.png

 

 

 

scsi 日志分析

# 打开 所有 scsi 日志
echo -1 > /proc/sys/dev/scsi/logging_level
# 关闭 所有 scsi 日志
echo 0 > /proc/sys/dev/scsi/logging_level

 

比如 上面的例子, 读取 block 为 18220 的数据 

-- blk_peek_request 中的 scsi_setup_command 中的 sd_setup_read_write_cmnd
[  175.242337] sd 0:0:0:0: [sda] sd_setup_read_write_cmnd: block=18820, count=2
[  175.244203] sd 0:0:0:0: [sda] block=18820
[  175.244203] sd 0:0:0:0: [sda] reading 2/2 512 byte blocks.
-- scsi_dispatch_cmd 中 scsi_log_send
[  175.252363] sd 0:0:0:0: [sda] tag#0 Send: scmd 0xffff88007fab8900
[  175.253165] sd 0:0:0:0: [sda] tag#0 CDB: Read(10) 28 00 00 00 49 84 00 00 02 00-- scsi_softirq_done 中的 scsi_log_completion
[  175.257789] sd 0:0:0:0: [sda] tag#0 Done: SUCCESS Result: hostbyte=DID_OK driverbyte=DRIVER_OK
[  175.258937] sd 0:0:0:0: [sda] tag#0 CDB: Read(10) 28 00 00 00 49 84 00 00 02 00
[  175.259519] sd 0:0:0:0: [sda] tag#0 scsi host busy 1 failed 0
-- scsi_softirq_done 中的 scsi_finish_command
[  175.260058] sd 0:0:0:0: Notifying upper driver of completion (result 0)
-- scsi_softirq_done 中的 scsi_finish_command 中的 drv->done
[  175.260444] sd 0:0:0:0: [sda] tag#0 sd_done: completed 1024 of 1024 bytes
-- scsi_softirq_done 中的 scsi_finish_command 中的 scsi_io_completion
[  175.260878] sd 0:0:0:0: [sda] tag#0 2 sectors total, 1024 bytes done.

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/52984.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【FAQ】EasyGBS平台通道显示在线,视频无法播放并报错400的排查

EasyGBS是基于国标GB28181协议的视频云服务平台,它可以支持国标协议的设备接入,在视频能力上能实现直播、录像存储、检索与回放、云台控制、告警上报、语音对讲、平台级联等功能,既能作为业务平台使用,也能作为能力层平台调用。 我…

装饰器模式(Decorator)

装饰器模式是一种结构型设计模式,用来动态地给一个对象增加一些额外的职责。就增加对象功能来说,装饰器模式比生成子类实现更为灵活。装饰器模式的别名为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。 Decor…

【每天40分钟,我们一起用50天刷完 (剑指Offer)】第四十七天 47/50

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)   文章字体风格: 红色文字表示&#…

VGG卷积神经网络-笔记

VGG卷积神经网络-笔记 VGG是当前最流行的CNN模型之一, 2014年由Simonyan和Zisserman提出, 其命名来源于论文作者所在的实验室Visual Geometry Group。 测试结果为: 通过运行结果可以发现,在眼疾筛查数据集iChallenge-PM上使用VGG…

实例031 窗体中的滚动字幕

实例说明 普通窗体中的文字位置都是固定的,一些窗体中需要让文字动起来,例如一些广告性较强的界面中需要做一些滚动的字幕。本例实现了一个具有滚动字幕效果的窗体,运行本例,单击【演示】按钮,看到窗口中的文字开始滚…

java讲解Spring Boot配置文件级别 相互覆盖关系 解决一方不愿意给数据库密码 一方不愿意给源码时 数据库配置问题

前面 我们讲过Spring Boot 修改临时变量的方式 但另一个场景 就是 我们 在本地开发环境 用的是一个配置 但如果项目经理上线 他想改这些配置 怎么弄呢 特别是数据库之类的配置 很多线上是不太一样的 那么 我们先看一个比较基本的方法 在配置文件的同目录下创建一个目录 叫 con…

C语言笔记6

关于microsoft visual 的学习笔记 CtrlF5就是启动编译程序 先CtrlA进行全选&#xff0c;然后AitF8就自动的调节代码的格式 #include <stdio.h> #include <stdlib.h> int main() {//system启动程序(在一个程序中启动另外一个程序)//如果程序环境变量中找不到程序&am…

2019年09月《全国青少年软件编程等级考试》Python一级真题解析

一、单选题 第1题 关于Python的编程环境&#xff0c;下列的哪个表述是正确的&#xff1f; A&#xff1a;Python的编程环境是图形化的&#xff1b; B&#xff1a;Python只有一种编程环境ipython&#xff1b; C&#xff1a;Python自带的编程环境是IDLE&#xff1b; D&#…

Java Collection接口详解

Collection 接口 Collection接口是Java集合框架的根接口。 Collection 接口是 List、Set 和 Queue 接口的父接口&#xff0c;通常情况下不被直接使用。 Collection 接口定义了一些通用的方法&#xff0c;通过这些方法可以实现对集合的基本操作。定义的方法既可用于操作 Set …

2023华数杯数学建模C题思路 - 母亲身心健康对婴儿成长的影响

# 1 赛题 C 题 母亲身心健康对婴儿成长的影响 母亲是婴儿生命中最重要的人之一&#xff0c;她不仅为婴儿提供营养物质和身体保护&#xff0c; 还为婴儿提供情感支持和安全感。母亲心理健康状态的不良状况&#xff0c;如抑郁、焦虑、 压力等&#xff0c;可能会对婴儿的认知、情…

Arthas协助MQ消费性能优化

背景 项目中使用AWS的SQS消息队列进行异步处理&#xff0c;QA通过压测发现单机TPS在23左右&#xff0c;目标性能在500TPS&#xff0c;所以需要对消费逻辑进行优化&#xff0c;提升消费速度。 目标 消费TPS从23提升到500 优化流程 优化的思路是先分析定位性能瓶颈&#xff…

新手指南:流程图中各种图形的含义及用法解析

我们经常在技术设计、沟通、业务演示等一些领域看到流程图&#xff0c;它也可以称为输入输出图。顾名思义&#xff0c;它是指一种简单的工作流程的具体步骤&#xff0c;比如包括一次会议的流程&#xff0c;以及一次生产制造的顺序和过程等。本文将为大家介绍流程图的含义和具体…