集散序列,散集序列?的使用。 struct scatterlist,scatter/gather散布表

Linux 4.14内核———— scatterlist介绍 scatterlist简单介绍 阅读详情

先来点概念:

http://blog.youkuaiyun.com/fudan_abc/archive/2007/07/28/1713976.aspx

 

无聊的it玩家们创建了有一个词,叫做scatter/gather,她是一种用于高性能IO的标准技术.她通常意味着一种DMA传输方式,对于一个给定的数据块,她老人家可能在内存中存在于一些离散的缓冲区,换言之,就是说一些不连续的内存缓冲区一起保存一个数据块,如果没有scatter/gather呢,那么当我们要建立一个从内存到磁盘的传输,那么操作系统通常会为每一个buffer做一次传输,或者干脆就是把这些不连续的buffer里边的冬冬全都移动到另一个很大的buffer里边,然后再开始传输.那么这两种方法显然都是效率不高的.毫无疑问,如果 操作系统/驱动程序/硬件 能够把这些来自内存中离散位置的数据收集起来(gather up)并转移她们到适当位置整个这个步骤是一个单一的操作的话,效率肯定就会更高.反之,如果要从磁盘向内存中传输,而有一个单一的操作能够把数据块直接分散开来(scatter)到达内存中需要的位置,而不再需要中间的那个块移动,或者别的方法,那么显然,效率总会更高.

  在struct scsi_cmnd中,有一个成员unsigned short use_sg,上头传下来的scsi_cmnd,其use_sg是设好了的,咱们判断一下,如果她为0,那么说明没有使用scatter/gather.struct scsi_cmnd中还有两个成员,unsigned request_bufflen和void *request_buffer,她们和use_sg是什么关系呢?

  事实上,要玩scatter/gather,就需要一个scatterlist数组,有人管她叫散列表数组.对于不同的硬件平台,定义了不同的struct scatterlist结构体,她们来自include/asm/scatterlist.h中,(如果是硬件平台i386的,那么就是include/asm-i386/scatterlist.h,如果是x86_64的平台,那么就在include/asm-x86_64/scatterlist.h中),然后所谓的scatter/gather就是一次把整个scatterlist数组给传送掉.而use_sg为0就表示没有scatter gather list,或者说scatterlist,对于这种情况,数据将直接传送给request_buffer或者直接从request_buffer中取得数据.而如果use_sg大于0,那么表示scatter gather list这么一个数组就在request_buffer中,而数组元素个数正是use_sg个.也就是说,srb->request_buffer里边的冬冬有两种可能,一种是包含了数据本身,另一种是包含了scatter gather list.具体是哪种情况通过判断use_sg来决定.而接下来即将要讲到的srb->request_bufflen顾名思义,就是buffer的长度,但对于use_sg大于0的情况,换言之,对于使用scatter gather list的情况,request_bufflen没有意义,将被忽略.

对这些原理有了基本的了解之后,我们可以从下节开始看代码了.这里先提醒一下,要注意我们这个函数虽然看似是传输数据,可它实际上并没有和usb真正发生关系,我们只是从软件上来fix一个硬件的bug,这个bug就是我们已经说过了的,不能响应基本的SCSI命令INQUIRY,你问她,她完全不予理睬.至于为什么不能响应我就不用说了吧?人的冷漠,不是因为天生就如此,只是暗淡的心境早已将所有通向阳光的窗户关闭了.而设备的冷漠,显然是制造商做的傻事了.(我没有讽刺Sony的意思,事实上这种情况并非只有Sony他们家才出现了,别的厂家也有这样的产品.只是,Device有bug,可以让程序去补,我们80后的梦碎了,拿什么去补?)

 

再来点(LDD3的):

15.4.4.7. 发散/汇聚映射

发散/汇聚映射是一个特殊类型的流 DMA 映射. 假设你有几个缓冲, 都需要传送数据到或者从设备. 这个情况可来自几个方式, 包括从一个 readv 或者 writev 系统调用, 一个成簇的磁盘 I/O 请求, 或者一个页链表在一个被映射的内核 I/O 缓冲. 你可简单地映射每个缓冲, 轮流的, 并且进行要求的操作, 但是有几个优点来一次映射整个链表.

许多设备可以接收一个散布表数组指针和长度, 并且传送它们全部在一个 DMA 操作中; 例如, "零拷贝"网络是更轻松如果报文在多个片中建立. 另一个映射发散列表为一个整体的理由是利用在总线硬件上有映射寄存器的系统. 在这样的系统上, 物理上不连续的页从设备的观点看可被汇集为一个单个的, 连续的数组. 这个技术只当散布表中的项在长度上等于页大小(除了第一个和最后一个), 但是当它做这个工作时, 它可转换多个操作到一个单个的 DMA, 和有针对性的加速事情.

最后, 如果一个反弹缓冲必须被使用, 应该连接整个列表为一个单个缓冲(因为它在被以任何方式拷贝).

因此现在你确信散布表的映射在某些情况下是值得的. 映射一个散布表的第一步是创建和填充一个 struct scatterlist 数组, 它描述被传输的缓冲. 这个结构是体系依赖的, 并且在 <asm/scatterlist.h> 中描述. 但是, 它常常包含 3 个成员:

struct page *page;

    struct page 指针, 对应在发散/汇聚操作中使用的缓冲.
unsigned int length;
unsigned int offset;

    缓冲的长度和它的页内偏移.

为映射一个发散/汇聚 DMA 操作, 你的驱动应当设置 page, offset, 和 length 成员在一个 struct scatterlist 项给每个要被发送的缓冲. 接着调用:

int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction)

这里 nents 是传入的散布表项的数目. 返回值是要发送的 DMA 缓冲的数目. 它可能小于 nents.

对于输入散布表中的每个缓冲, dma_map_sg 决定了正确的给设备的总线地址. 作为任务的一部分, 它也连接在内存中相近的缓冲. 如果你的驱动运行的系统有一个 I/O 内存管理单元, dma_map_sg 也编程这个单元的映射寄存器, 可能的结果是, 从你的驱动的观点, 你能够传输一个单个的, 连续的缓冲. 你将不会知道传送的结果将看来如何, 但是, 直到在调用之后.

你的驱动应当传送由 pci_map_sg 返回的每个缓冲. 总线地址和每个缓冲的长度存储于 struct scatterlist 项, 但是它们在结构中的位置每个体系不同. 2 个宏定义已被定义来使得可能编写可移植的代码:

dma_addr_t sg_dma_address(struct scatterlist *sg);

从这个散布表入口返回总线( DMA )地址.

unsigned int sg_dma_len(struct scatterlist *sg);

返回这个缓冲的长度.

再次, 记住要传送的缓冲的地址和长度可能和传递给 dma_map_sg 的不同.

一旦传送完成, 一个 发散/汇聚 映射被使用 dma_unmap_sg 去映射:

void dma_unmap_sg(struct device *dev, struct scatterlist *list, int nents, enum dma_data_direction direction);

注意 nents 必须是你起初传递给 dma_map_sg 的入口项的数目, 并且不是这个函数返回给你的 DMA 缓冲的数目.

发散/汇聚映射是流 DMA 映射, 并且同样的存取规则如同单一映射一样适用. 如果你必须存取一个被映射的发散/汇聚列表, 你必须首先同步它:

void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
 int nents, enum dma_data_direction direction);
void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 int nents, enum dma_data_direction direction);

//------------------------------------------------------------------------------------------------------

一般在块设备会使用到,比如sd卡驱动中,使用方法如下:

1、定义一个结构体struct has_sa{unsigned int sg_len; struct scatterlist *sg;}

其中,sg_len表示有一个“散开”的sg数组,而*sg就是表示有几个数组。这个相当于:

unsigned int len; unsigned int buffer[len];只不过他是用指针来表示数组。


2、给结构体成员赋值:

sg_len=1;

sg = &mysg;

这就表示有一个“散开”的序列。如此类推。


3、使用:

struct has_sa *has_sa;

1)取得当前的散布表:struct scatterlist *cur_sg = &has_sa->sg[index];

2)然后给此集散序列分配一段内存以便使用dma之类的:

dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);

3)使用完后释放该段内存(一般在dma中断里面):

dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);


4、还有dma_map_sg(),一次性把所有的sg全部映射完。

【SGL】Scatter-Gather List内存传输技术 再例如,文件数据在内存中可能分散在多个page cache页(例如大文件被拆分为多个4KB页):文件系统将文件的page cache页地址构建为sgl,存储设备通过sgl直接读取这些页,无需合并到连续内存。以分布式存储与对象存储为例,对象存储系统需要将大对象拆分为多个分片存储在不同节点:将对象分片的存储节点地址和偏移量写入sgl,客户端或服务端通过sgl并发读写多个分片。核心思想:通过一个链表或数组描述多个分散的内存块,使得硬件可以一次性完成对这些非连续内存区域的读写操作,无需CPU介入数据拷贝。 阅读详情

相关推荐

深入解析Linux内核中的scatter-gather list机制及其在DMA传输中的应用

本文深入解析了Linux内核中的scatter-gather list(SGL)机制及其在DMA传输中的核心应用。SGL通过描述非连续内存缓冲区,使DMA控制器能直接进行分散-聚集操作,从而避免不必要的内存拷贝,显著提升I/O效率。文章详细剖析了其数据结构、API接口、实战优势及常见避坑指南,是编写高性能Linux设备驱动的关键知识。

app77的博客 287

RDMA技术详解(三):理解RDMA Scatter Gather List

1. 前言 在使用RDMA操作之前,我们需要了解一些RDMA API中的一些需要的值。其中在ibv_send_wr我们需要一个sg_list的数组,sg_list是用来存放ibv_sge元素,那么什么是SGL以及什么是sge呢?对于一个使用RDMA进行开发的程序员来说,我们需要了解这一系列细节。 2. SGE简介 在NVMe over PCIe中,I/O命令支持SGL(Scatter Gather...

Master-TJ的个人博客 9470

Scatter Gather List (SGL)

最后一个SGL段是不包含SGL段描述符或SGL末段描述符的SGL段。•SGL数据块描述符包含地址或长度字段,其中两个较低的位任一设置为1b,控制器只支持标识控制器数据结构中的SGL Support字段中所示的Dword对齐和粒度。设置为全零的SGL描述符是地址字段设置为00000000_00000000h且长度字段设置为00000000h的SGL数据块描述符可以用作NULL描述符。•SGL段除了段中的最后一个描述符外,还包含SGL段描述符或SGL最后一个段描述符;一个SGL段包含一个或多个SGL描述符。

哦哦 会议中 1096

RDMA Scatter Gather List详解

其中在ibv_send_wr我们需要一个sg_list的数组,sg_list是用来存放ibv_sge元素,那么什么是SGL以及什么是sge呢?这个WR请求中,包括一个sg_list的元素。wr是一个链表,每一个结点包含了一个sg_list(i.e. SGL: 由一个或多个SGE构成的数组), sg_list的长度为num_sge。下面图解一下SGL和WR链表的对应关系,并说明一个SGL (struct ibv_sge *sg_list)里包含的多个数据段是如何被RDMA硬件聚合成一个连续的数据段的。

大隐隐于野 2474

浅析Linux内核scatter-gather list实现

摘要:Linux Scatter-Gather List(SGL)是内核中用于描述非连续物理内存块的数据结构,主要用于DMA传输和IO操作,可提升数据传输效率。核心数据结构包括sg_table和scatterlist,前者管理SGL表项数组,后者描述单个连续内存块。SGL支持多级表项结构,通过特定标志位实现链式连接。内核提供创建、遍历和拷贝等API接口,如sg_alloc_table、for_each_sg和sg_copy_buffer等,方便操作不连续内存块。该机制广泛应用于DMA传输场景,可减少CPU数

Aspiresky的专栏 1338

深入解析Linux内核中的scatter-gather list机制及其优化实践

本文深入解析了Linux内核中的Scatter-Gather List(SGL)机制,这是一种用于高效管理物理上不连续内存的数据结构。文章通过生动的比喻和代码示例,详细剖析了其核心数据结构(struct scatterlist)与工作原理,并重点阐述了如何通过sg_alloc_table、dma_map_sg等API与DMA结合进行优化实践,从而避免数据拷贝,显著提升I/O性能。

wdx0123456的博客 600

Linux scatterlist 详解

之前在《Linux DMA... 零拷贝》博文分享了DMA 技术和零拷贝技术,在进行I/O设备和内存的数据传输的时候,数据搬运的工作全部交给DMA 控制器,而CPU 不再参与任何与数据搬运相关的事情,这样CPU就可以去处理别的事务。用户层与外设或子系统可能需要大量数据交互,这样就需要大量的内存,而随着系统的长时间运行,物理内存可能存在大量的碎片,想要申请很大的一块物理内存已经成为奢望。并且,从性能方面考虑,用户层和子系统都希望减少交互的次数,更希望一次性将数据都交给 DMA控制器搬运。

私房菜 4667

[NVME] Scatter Gather List (SGL)

Scatter Gather List (SGL)

jinyuya的博客 1028

【存储技术分享】SGL和SGE

Scatter Gather List(SGL)是一种数据结构,用于描述分散存储的数据块(即散布在不同的物理地址上的数据块)和聚合存储的数据块(即连续存储在同一物理地址上的数据块)。SGL由多个元素组成,每个元素描述一个数据块的地址和大小。在计算机系统中,SGL常用于高速数据传输,例如在网络传输和存储系统中。通过使用SGL,可以有效地管理分散存储和聚合存储的数据块,提高数据传输的效率和可靠性。

逆风水手的博客 3596

快手did did_gt edid的注册过程

接口 https://gdfp.ksapisrv.com/rest/infra/gdfp/report/kuaishou/android did 是本地生成的16进制 或者 获取的 android_id did_gt 是did生成时间戳 1595073601970 public static final Random f16237a = new Random(System.currentTimeMillis()); public static long m19668a() {  &n

HURUWO的技术博客 1万+

C#上位机开发入门:从基础到进阶的全方位指南

C#作为一门现代化编程语言,具备强大的功能和广泛的生态支持,适合用于开发各种类型的上位机应用。通过学习并掌握UI开发、通信协议、多线程编程、数据库操作等技能,你可以打造出稳定、易用、性能优异的上位机软件。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 8310

struct scatterlist 使用

转自:http://blog.youkuaiyun.com/ganggexiongqi/article/details/7038335 1、结构解析 struct scatterlist {      ...      /* User input members */     unsigned long   page_link;// pointer to a page, but the bit0

csd_meb的专栏 1282

SKUA-GOCAD入门教程-第七节 点的创建与编辑3

本文介绍了四种从井数据创建点集的方法

江洋大葱的博客 963

scatterlist分析 (DMA)

使用scatterlist的原因就是系统在运行的时候内存会产生很多碎片,比如4k,100k的,1M的,有时候对应磁盘碎片,总之就是碎片。而在网络和磁盘操作中很多时候需要传送大块的数据,尤其是使用DMA的时候,因为DMA操作的物理地址必须是连续的。假设要1M内存,此时可以分配一个整的1M内存, 也可以把10个10K的和9个100K的组成一块1M的内存,当然这19个块可能是不连续的,也可能其中某些或全

kjtt_kjtt的专栏 2406

【DaVinci Developer工具实战】03 -导入xml文件

本文档描述了 DaVinci Developer 导入数据的的具体功能 ,它适用于导入AUTOSAR SWC 模板【AUTOSAR XML 文件】 文件。

1990

我终于停止写 JUnit 了!用 JavaParser + GPT-4 自动生成 90% 覆盖率的单元测试

本文介绍了一种基于JavaParser和GPT-4的智能单元测试生成方案。针对开发者在单元测试编写中面临的繁琐、无聊和硬指标等问题,提出通过AST语法树分析代码结构,提取关键信息后生成精准提示词,再调用GPT-4自动生成高质量的单元测试代码。文章详细阐述了技术原理、实现步骤(包括JavaParser解析、上下文感知提示词构建和GPT-4调用),并展示了该方法能自动识别依赖、Mock对象和覆盖边界条件,显著提升测试效率。同时指出了在复杂数据结构、私有方法测试等方面的局限性,最终强调这种技术组合可以解放开发者,

BUG猿的博客 1127

scatterlist

在内核驱动程序的很多代码中,都能够看到类似sgdma的内容,sgdma全称为Scatter/Gather DMA(散列/收集 DMA),内核中抽象了scatterlist和sg table用来描述和管理这种需要做散列和收集的DMA缓冲区。在内核中设计scatterlist,主要出于两方面的原因,从硬件层面来说,目前很多DMA控制器都支持硬件的SG DMA模式,由开发人员在内存中构建一个链式的DMA缓冲区描述符(Buffer Descriptor, BD),DMA控制器根据这个链式BD进行一对多、多对一或者多

abcxy2161的博客 3064

半导体物理基础:载流子输运理论_(4).载流子浓度与费米能级

费米能级(Fermi Level)是描述半导体中电子和空穴能量分布的基准能级。在绝对零度下,费米能级以下的所有能级都被电子占据,费米能级以上的所有能级都是空的。随着温度的升高,电子会获得足够的能量跃迁到费米能级以上的能级,形成导带中的自由电子和价带中的空穴。费米能级在半导体中的位置取决于掺杂浓度和温度。对于本征半导体,费米能级位于禁带的中心;对于掺杂半导体,费米能级会偏移,具体位置取决于掺杂类型和浓度。载流子浓度(Carrier Concentration)是指半导体中自由电子和空穴的数量密度。

2401_87715305的博客 831

BLOCK层代码分析(6)IO下发之SGL聚散列表

原本计划本节介绍request的分配,发现会涉及到数据组织从bio到sgl的映射,因此本节介绍SGL组织方式。 在BLOCK层数据的组织为bio和request,通过这两个结构体就可以找到数据的位置。但若传输到SCSI层,硬盘位置用scsi command表示,内存中位置用scatterlist表示。本小节讲述scatterlist是如何将数据组织起来的。在BLOCK层数据的组织为bio和request,通过这两个结构体就可以找到数据的位置。但若传输到SCSI层,硬盘位置用...

flyingnosky的专栏 3802

【Clickhouse】Clickhouse写入报错keeper server rejected the connection during the handshake

我的clickhouse集群时不时的报这个错误All connection tries failed while connecting to ZooKeeper. nodes: xxx 到时写入数据失败 用的ck自带的keeper。你需要仔细检查ZooKeeper集群的配置和状态,确保所有节点都正常运行,并且能够正确地选举领导者。检查ZooKeeper的ACL以及ClickHouse连接所使用的凭据,确保它们被正确配置和授权。版本不兼容:有时,不同版本的软件之间可能存在不兼容性,导致连接问题。

九师兄 370

【ubuntu24.04】auto remove后,重启,kernel panic ,please reboot your computer vfs unable to mount root fs

Ubuntu 24.04系统在运行auto remove后出现内核恐慌(kernel panic)无法启动,显示"VFS: unable to mount root fs"错误。该问题是由于当前内核被清除导致系统无法挂载根分区。解决步骤包括:1)尝试用GRUB菜单中的旧内核启动;2)在GRUB中临时编辑启动参数;3)使用Ubuntu启动盘进行chroot修复;4)使用Boot-Repair工具一键修复。成功启动后,需要重新安装linux-generic等元包,重建initramfs并更新

突围 1209

Linux内核 -- 内存管理之scatterlist结构使用

结构在 Linux 内核中主要用于 DMA(直接内存访问)操作中的内存管理。它允许将不连续的物理内存片段表示为一个逻辑上的连续块,从而使 DMA 操作可以高效地处理这些不连续的内存片段。

sz66cm 学习随笔 1515

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

scatterlist的相关概念与实例分析

scatterlist用来描述一块内存,sg_table一般用于将物理不同大小的物理内存链接起来,一次性送给DMA控制器搬运page_link:(1).对于chain sg 来说,记录下一个 SG 数组的首地址,并且用bit[0] 和 bit[1] 来表示是chain sg 还是 end sg;(2).对于 end sg 来说,只有bit[1] 为1,其他无意义;(3).对于普通 sg 来说,记录的是关联的内存页块的地址;

我的博客 2175

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

scatter/gether的知识点 struct scatterlist

struct scatterlist *sglist {     unsigned long page_link;//page 位置,大约就是虚拟地址page的位置     unsigned int offset;//偏移量     unsigned int length;//长度     dma_addr_t dma_address;//dma的地址,应该就是总线地址     unsi

fouweng的博客 1585

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

上一篇: 以太网ethernet芯片MAC和PHY的关系
下一篇: dma使用的几个概念。burst,burst size,length
#Page#
博客等级 码龄23年 1691粉丝 360原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值