Linux 内核 scatterlist 介绍
todo
scatterlist 介绍
我们在应用开发时,经常会遇到需要分配一大块内存用来存放数据的情况,无论内存是否连续,通过虚拟地址实现,我们在访问虚拟地址时总是认为它是连续的,因此可以让 CPU "连续"访问这块内存。然而当虚拟内存映射到实际的物理内存时,则并非如此,这块连续的虚拟地址空间,在物理内存中可能是分开的。在使用 CPU 通过虚拟地址方式访问时,自然有硬件为其服务将虚拟地址翻译成对应的物理地址,但是有时为了缓解 CPU 对数据操作的负担,我们需要将数据的操作卸载到硬件设备来完成对数据的操作,此时需要 DMA 参与完成数据的搬运,但是对 DMA 而言,它访问的是真正的物理地址空间,对于 CPU 连续的虚拟地址空间,对 DMA 而言,则是分片存在的。当然我们可以使用某接口,在分配内存时,就保证其在物理空间是连续的。那么考虑第二种情况,比如一类应用场景,我们有a数据,b数据,c数据,等等,在不同阶段为它们分配了空间,这几段空间在自己的空间段内连续,但是在它们整体而言,却是彼此隔离的。这样我们就有了多段分散的内存。我们此时希望将它们放到硬件中处理,只要我们以合适的顺序组织数据,告知硬件各段的长度,硬件自动将数据处理好给到我们,这时候是否需要将它们复制到一整块内存上呢?只要硬件做好逻辑,是没有必要做这个动作的,要知道,CPU 做拷贝动作就不能执行其他动作,而内存拷贝相较于缓存地访问,速度缓慢了一个数量级,这是对 CPU 资源的显著浪费。若没有一个预先准备的内存池子,那么分时段分配的内存是很难在物理内存空间上自然连续。
图片(虚拟内存的连续对应物理内存的分散)
图片(多个数据段的内部连续,彼此隔离)
基于种种原因,假设分散的内存块天然存在,那么我们怎么能够在不进行内存拷贝的前提,使用 DMA 进行数据的拷贝呢?