申請noncache記憶體

2021-10-04 17:29:24 字數 2310 閱讀 8773

申請記憶體提供給使用者態,nocache

static int shm_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)

核心態申請的記憶體,nocache,方法如下,使用者兩個函式dma_alloc_coherent 與 dma_alloc_writecombine。如果覺得麻煩,可以參考著兩個介面,自己實現一遍。dma_alloc_coherent的**實現分析,請看另外一篇文章

核心的dma一般在平台初始化的時候已經分配好了。但是對於一些有內部dma的硬體ip,比如usb ip、video加速ip,他們可能由ip廠商封裝好的,沒辦法繫結到cpu端,這時候在核心使用dma就要注意了,因為dma只認識實體地址哦。

當然,辦法還是有的,look:

以下來自:

這兩天在做 dma 相關開發, 遇到一對分配 dma buffer 的函式,dma_alloc_coherent 與 dma_alloc_writecombine。 不知其區別。 google 一下也沒有得到資訊。只好自己看**。

原來 dma_alloc_coherent 在 arm 平台上會禁止頁表項中的 c (cacheable) 域以及 b (bufferable)域。

而 dma_alloc_writecombine 只禁止 c (cacheable) 域.

#define pgprot_noncached(prot)  __pgprot(pgprot_val(prot) & ~(l_pte_cacheable | l_pte_bufferable))

#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~l_pte_cacheable)

進一步查詢 arm 書籍, 原來 c 代表是否使用高速緩衝儲存器, 而 w 代表是否使用寫緩衝區。

這樣, dma_alloc_coherent  分配出來的記憶體不使用快取,但是會使用寫緩衝區。

而 dma_alloc_writecombine 則二者都不適用。

由此,再去理解 ldd3 上講解的一致性 dma 對映 與 流式 dma 對映就比較容易了,一致性 dma 對映呼叫的是上面的函式,   由於關閉了 cache/buffer, 效能自然比較低。 而流式則通過複雜的同步機制,沒有付出效能的代價。

所以我們要盡量使用流式 dma 來程式設計。

再去看看 mmc 驅動裡使用的 分散 / 聚集對映, 原來也是一種 流式 dma 對映。

【補充】

講了那麼多沒用,總結下用法:

1、頁對齊記憶體大小:dma_map_size = page_align(my_data_size + page_size);

my_data_size是你想分配的大小.

2、呼叫

a = dma_alloc_writecombine(b,c,d,gfp_kernel);

含義:a: 記憶體的虛擬起始位址,在核心要用此位址來操作所分配的記憶體

b: struct device指標,可以平台初始化裡指定,主要是dma_mask之類,可參考framebuffer

c: 實際分配大小,傳入dma_map_size即可

d: 返回的記憶體實體地址,dma就可以用。

所以,a和d是一一對應的,只不過,a是虛擬位址,而d是實體地址。對任意乙個操作都將改變緩衝區內容。當然要注意操作環境。

大家都知道,dma的操作是需要實體地址的,但是在linux核心中使用的都是虛擬位址,如果我們想要用dma對一段記憶體進行操作,我們如何得到這一段記憶體的實體地址和虛擬位址的對映呢?dma_alloc_coherent這個函式實現了這種機制。

1、函式原型:

void *dma_alloc_coherent(struct device *dev, size_t size,dma_addr_t *dma_handle,gfp_t gfp);下面的這一段參考

2、呼叫

a = dma_alloc_writecombine(b,c,d,gfp_kernel);

含義:a: 記憶體的虛擬起始位址,在核心要用此位址來操作所分配的記憶體

b: struct device指標,可以平台初始化裡指定,主要是dma_mask之類,可參考framebuffer

c: 實際分配大小,傳入dma_map_size即可

d: 返回的記憶體實體地址,dma就可以用。

所以,a和d是一一對應的,只不過,a是虛擬位址,而d是實體地址。對任意乙個操作都將改變緩衝區內容。

我對此函式的理解是,呼叫此函式將會分配一段記憶體,d將返回這段記憶體的實際實體地址供dma來使用,a將是d對應的

虛擬位址供作業系統呼叫,對a和d的的任意乙個進行操作,都會改變這段記憶體緩衝區的內容。

VC 記憶體申請

問題 如果要申請一塊記憶體?應該如何做?解答 在vc 一般的做法是 lpvoid pvdata 宣告乙個任何型別的指標 dword dwfilesize 申請記憶體的大小 分配全域性的可移動的記憶體 hglobal hglobal globalalloc gmem moveable,dwfilesi...

動態申請記憶體

如果函式的引數是乙個指標,不要指望用該指標去申請動態記憶體。示例1中,test函式的語句getmemory str,100 並沒有使str獲得期望的記憶體,str依舊是null,為什麼?void getmemory char p,int num void test void 示例1 試圖用指標引數申...

windows記憶體申請

在進行windows的學習過程中,經常看到不同的記憶體分配方式,例如virtualalloc,heapalloc,malloc和new。它們之間存在一些差異。pvoid virtualalloc pvoid pvaddress,size t dwsize,dword fdwallocationtyp...