Linux内核 scatterlist介绍
生活随笔
收集整理的這篇文章主要介紹了
Linux内核 scatterlist介绍
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
scatterlist
- 物理內(nèi)存的散列表。通俗講,就是把一些分散的物理內(nèi)存,以列表的形式組織起來
誕生背景
- 假設(shè)有三個(gè)模塊可以訪問memory:CPU、DMA控制器和某個(gè)外設(shè)。
- CPU通過MMU以虛擬地址(VA)的形式訪問memory;
- DMA直接以物理地址(PA)的形式訪問memory;
- Device通過自己的IOMMU以設(shè)備地址(DA)的形式訪問memory。
- 然后,某個(gè)“軟件實(shí)體”分配并使用了一片存儲(chǔ)空間。該存儲(chǔ)空間在CPU視角上(虛擬空間)是連續(xù)的,起始地址是va1(實(shí)際上,它映射到了3塊不連續(xù)的物理內(nèi)存上,我們以pa1,pa2,pa3表示)。那么,如果該軟件單純的以CPU視角訪問這塊空間(操作va1),則完全沒有問題,因?yàn)镸MU實(shí)現(xiàn)了連續(xù)VA到非連續(xù)PA的映射。
- 不過,如果軟件經(jīng)過一系列操作后,要把該存儲(chǔ)空間交給DMA控制器,最終由DMA控制器將其中的數(shù)據(jù)搬移給某個(gè)外設(shè)的時(shí)候,由于DMA控制器只能訪問物理地址,只能以“不連續(xù)的物理內(nèi)存塊”為單位遞交(而不是我們所熟悉的虛擬地址)。此時(shí),scatterlist就誕生了:為了方便,我們需要使用一個(gè)數(shù)據(jù)結(jié)構(gòu)來描述這一個(gè)個(gè)“不連續(xù)的物理內(nèi)存塊”(起始地址、長(zhǎng)度等信息),這個(gè)數(shù)據(jù)結(jié)構(gòu)就是scatterlist。而多個(gè)scatterlist組合在一起形成一個(gè)表(可以是一個(gè)struct scatterlist類型的數(shù)組,也可以是kernel幫忙抽象出來的struct sg_table),就可以完整的描述這個(gè)虛擬地址了。
- 最后,從本質(zhì)上說:scatterlist(數(shù)組)是各種不同地址映射空間(PA、VA、DA、等等)的媒介(因?yàn)槲锢淼刂肥钦鎸?shí)的、實(shí)在的存在,因而可以作為通用語(yǔ)言),借助它,這些映射空間才能相互轉(zhuǎn)換(例如從VA轉(zhuǎn)到DA)
介紹
struct scatterlist
-
struct scatterlist用于描述一個(gè)在物理地址上連續(xù)的內(nèi)存塊(以page為單位),它的定義位于“include/linux/scatterlist.h”中,如下:
- page_link,指示該內(nèi)存塊所在的頁(yè)面。bit0和bit1有特殊用途(可參考后面的介紹),因此要求page最低4字節(jié)對(duì)齊。
- offset,指示該內(nèi)存塊在頁(yè)面中的偏移(起始位置)。
- length,該內(nèi)存塊的長(zhǎng)度。
- dma_address,該內(nèi)存塊實(shí)際的起始地址(PA,相比page更接近我們?nèi)祟惖恼Z(yǔ)言)。
- dma_length,相應(yīng)的長(zhǎng)度信息。
?struct sg_table
- 多個(gè)scatterlist組成一個(gè)數(shù)組,以表示在物理上不連續(xù)的虛擬地址空間。通常情況下,使用scatterlist功能的模塊,會(huì)自行維護(hù)這個(gè)數(shù)組(指針和長(zhǎng)度),例如[2]中所提到的struct mmc_data:
-
不過呢,為了使用者可以偷懶,kernel抽象出來了一個(gè)簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu):struct sg_table,幫忙保存scatterlist的數(shù)組指針和長(zhǎng)度
- 其中sgl是內(nèi)存塊數(shù)組的首地址,orig_nents是內(nèi)存塊數(shù)組的size,nents是有效的內(nèi)存塊個(gè)數(shù)(可能會(huì)小于orig_nents)。
- scatterlist數(shù)組中到底有多少有效內(nèi)存塊呢?這不是一個(gè)很直觀的事情,主要有如下2個(gè)規(guī)則決定:
- 1)如果scatterlist數(shù)組中某個(gè)scatterlist的page_link的bit0為1,表示該scatterlist不是一個(gè)有效的內(nèi)存塊,而是一個(gè)chain(鉸鏈),指向另一個(gè)scatterlist數(shù)組。通過這種機(jī)制,可以將不同的scatterlist數(shù)組鏈在一起,因?yàn)閟catterlist也稱作chain scatterlist。
- 2)如果scatterlist數(shù)組中某個(gè)scatterlist的page_link的bit1為1,表示該scatterlist是scatterlist數(shù)組中最后一個(gè)有效內(nèi)存塊(后面的就忽略不計(jì)了)。
- table中sgl數(shù)組大小最大為PAGE_SIZE,如果nents個(gè)數(shù)超過了SG_MAX_SINGLE_ALLOC,那么就需要使用到chain了。具體實(shí)現(xiàn)可以查看sg_alloc_table -> __sg_alloc_table
- 使用提供的API函數(shù)就可以訪問所有的sg了,例如for_each_sg()
參考鏈接
- Linux內(nèi)核scatterlist API介紹 - AlanTu - 博客園
- Linux內(nèi)存管理 - 隨筆分類(第2頁(yè)) - AlanTu - 博客園
- 聊聊scatterlist的chain結(jié)構(gòu)
- Welcome to The Linux Kernel’s documentation! — The Linux Kernel 4.7 documentation
- Linux Kernel Crypto API — The Linux Kernel 4.7 documentation
- 內(nèi)核解壓縮 · Linux Inside 中文版
- Linux內(nèi)核加密模塊crypto的使用 | 楊磊的博客
總結(jié)
以上是生活随笔為你收集整理的Linux内核 scatterlist介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国债2022年发行时间利率,买不到国债的
- 下一篇: 布朗桥python_MATLAB 里面有