1. 程式人生 > >【引用】DMA記憶體申請--dma_alloc_coherent

【引用】DMA記憶體申請--dma_alloc_coherent

在專案驅動過程中會經常用到dma傳輸資料,而dma需要的記憶體有自己的特點,一般認為需要實體地址連續,並且記憶體是不可cache的,在linux核心中提供一個供dma所需記憶體的申請函式dma_alloc_coheren. 如下所述:
dma_alloc_coherent()

dma_alloc_coherent() -- 獲取物理頁,並將該物理頁的匯流排地址保存於dma_handle,返回該物理頁的虛擬地址

void *
dma_alloc_coherent(struct device *dev,        size_t size,
                   dma_addr_t    *dma_handle, gfp_t gfp)
{
    void *ret;
    if (!dev || *dev->dma_mask >= 0xffffffffUL)
        gfp &= ~GFP_DMA;
    ret = (void *)__get_free_pages
(gfp, get_order(size)); //(1)
    if (ret) {
        memset(ret, 0, size);
        *dma_handle = virt_to_bus(ret);                   //(2)
    }
    return ret;
}

(1) 將size轉換成order, 即2^order
(2) 將虛擬地址ret轉換成匯流排地址

這個函式是一個平臺相關的函式,以上是在x86平臺的實現細節,從這裡我們可以看到該函式返回值為linux 核心線性地址,所以對於驅動開發過程的mmap函式實現提供了便利。
但是在powerpc平臺卻不是這樣,筆者就曾經遇到在將pci驅動從x86平臺移植到powerpc平臺時出現問題。
首先我們來先看一下兩個平臺對於dma記憶體的處理。
x86:
     linux記憶體區域分為DMA區域,Normal記憶體區域與高階記憶體區域,高階記憶體區域為當實體記憶體高於768M時使用,一般DMA區域為16M,這段空間由作業系統預留。DMA區域與Normal區域全部使用線性對映,採用邏輯地址使用,高階記憶體使用核心虛擬地址。其中核心空間的分部為:
物理區--8M隔離--vmalloc區--8k隔離--4M的高階對映區--固定對映區--128k

powerpc:
    本節採用freescale的mpc5121晶片為例,核心沒有采用Normal記憶體區域,只使用ZONE_DMA和ZONE_HIMEM兩種型別的空間,其中ZONE_DMA存放低端記憶體, ZONE_HIMEN存放高階記憶體,整個記憶體不在採用邏輯地址這一概念。所以基於邏輯地址的操作沒有可移植性。

下面看下具體的區別:
void *  __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
{
          //物理空間頁的申請
          page = alloc_pages(gfp, order);
        
         //對物理空間進行清零cache
         {
                       unsigned long kaddr = (unsigned long)page_address(page);                
                       memset(page_address(page), 0, size);
                       flush_dcache_range(kaddr, kaddr + size);
          }

         //申請虛擬空間
         c = vm_region_alloc(&consistent_head, size,   gfp & 
                                     ~(__GFP_DMA | __GFP_HIGHMEM));

       //實現虛擬地址與實體地址對映
       if (c) {
                 unsigned long vaddr = c->vm_start;
                 pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
                 struct page *end = page + (1 << order);

                 split_page(page, order);

                 /*
                  * Set the \"dma handle\"
                  */
                 *handle = page_to_bus(page);

                do {
                         BUG_ON(!pte_none(*pte));

                         SetPageReserved(page);
                         set_pte_at(&init_mm, vaddr,
                                   pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
                         page++;
                         pte++;
                         vaddr += PAGE_SIZE;
                 } while (size -= PAGE_SIZE);

     // 返回值為核心虛擬地址。
      return (void *)c->vm_start



相關推薦

引用DMA記憶體申請--dma_alloc_coherent

在專案驅動過程中會經常用到dma傳輸資料,而dma需要的記憶體有自己的特點,一般認為需要實體地址連續,並且記憶體是不可cache的,在linux核心中提供一個供dma所需記憶體的申請函式dma_alloc_coheren. 如下所述:dma_alloc_coherent()dma_alloc_coherent

CA證書申請+IIS配置HTTPS+默認訪問https路徑

網站 加網 剛才 你會 重寫 tin 如果 art 復制 本文非原創,原文地址:https://www.cnblogs.com/lichunting/p/9274422.html 一.CA證書申請 (一). 新StartSSL註冊帳號 1. StartS

轉載jvm記憶體回收

1.java的記憶體 java的記憶體結構分為 堆 (是gc的主要區域) 執行緒共享,主要是用於分配例項物件和陣列 棧 執行緒私有,它的生命週期和執行緒相同,又分成 虛擬機器棧和本地方法棧,只有它會報 StackOverFlowError,棧深度超標 方法區 執行緒共享 用於儲存被虛

Linux記憶體管理

摘要:本章首先以應用程式開發者的角度審視Linux的程序記憶體管理,在此基礎上逐步深入到核心中討論系統實體記憶體管理和核心記憶體的使用方法。力求從外到內、水到渠成地引導網友分析Linux的記憶體管理與使用。在本章最後,我們給出一個記憶體對映的例項,幫助網友們理解核心記憶體管理與使用者記憶體管理之間的

基礎計算機記憶體分配-堆-棧等概念的區別

說明 在資料結構範疇內,堆是一種排序的方式,棧是一種“先進後出”的資料結構。 在記憶體分配的範疇內,堆是一種儲存區間,該區間通過連結串列的方式進行組織;棧也是一種儲存區間,該區間的操作類似資料結構中棧的操作方式--“先進後出”。 記憶體分配 靜態儲存區 棧區

C++動態記憶體分配

如何動態新增資料,輸入長度不受限制? 陣列是不行的,它的長度為常量。有人就像將手動輸入一個長度,然後就有了如下程式碼: int n = 0; scanf("%d", &n); int Contact[n]; 編譯錯誤。我只能說你太年輕,陣列的長度是常量呀,你這分明是

舉例Android動態申請許可權

寫在前面:對於新版本的Android,部分許可權必須手動向使用者發起請求並獲得允許後才能使用。關於這一部分的基礎知識,這裡就不詳述。大家可以自行百度去獲取。 相關知識: 【舉例】Android自定義Dialog——做出“確定/取消”的選擇 http://blog.cs

JDK 記憶體引數含義

Eclipse崩潰,錯誤提示: MyEclipse has detected that less than 5% of the 64MB of Perm  Gen (Non-heap memory) space remains. It is strongly recommended tha

乾貨Linux記憶體資料的獲取與轉存 直搗密碼

知識源:Unit 2: Linux/Unix Acquisition 2.1 Linux/Unix Acquistion Memory Acquisition 中的實驗demo部分  小白注意,這是網路安全RITx: CYBER502x 部分的內容。 19年1月初,該系列課程會推出501x,這是面向

JAVA談談記憶體洩露

                                          &

MySQLInnoDB 記憶體管理機制 --- Buffer Pool

InnoDB Buffer Pool 是一塊連續的記憶體,用來儲存訪問過的資料頁面 innodb_buffer_pool_size 引數用來定義 innodb 的 buffer pool 的大小 是 MySQL 中擁有最大的記憶體的模組 Innodb 中,資料的訪問是按照頁/塊(預設為16

轉載Linux記憶體管理與相關概念

    在Linux中經常發現空閒記憶體很少,似乎所有的記憶體都被系統佔用了,表面感覺是記憶體不夠用了,其實不然。Linux記憶體管理的一個特點是無論實體記憶體有多大,Linux 都將其充分利用(The reason Linux uses so much mem

Linux記憶體管理(最透徹的一篇)

摘要:本章首先以應用程式開發者的角度審視Linux的程序記憶體管理,在此基礎上逐步深入到核心中討論系統實體記憶體管理和核心記憶體的使用方法。力求從外到內、水到渠成地引導網友分析Linux的記憶體管理與使用。在本章最後,我們給出一個記憶體對映的例項,幫助網友們理解核心記憶體管理

java記憶體洩漏的定位與分析

1、為什麼會發生記憶體洩漏 Java如何檢測內在洩漏呢?我們需要一些工具進行檢測,並發現記憶體洩漏問題,不然很容易發生down機問題。 編寫java程式最為方便的地方就是我們不需要管理記憶體的分配和釋放,一切由jvm來進行處理,當java物件不再被應用時,等到堆記憶體不夠

乾貨Windows記憶體獲取和分析---查詢惡意程序,埠

來源:Unit 5: Windows Acquisition 5.1 Windows Acquisition Windows Memory Acquisition and Analysis   調查人員檢查實體記憶體內容,以檢測惡意程序、威脅和記憶體駐留惡意軟體,以恢復密碼和獲取金鑰。 &nb

C++動態記憶體管理

一、C/C++記憶體分佈 我們先回顧在C語言學習階段學習過的一張記憶體分佈圖: 然後我們可以根據上邊的這幅圖,做一下下面這道筆試中一定會遇到的判斷儲存區的筆試題: int globalVar = 1

筆記ios 記憶體大小的限制 (因佔用記憶體太大而crash)

因ios對每個程式都有最大的記憶體分配限制,如果超過了這個閾值,會被系統強制關閉,造成crash,通常出現在bugly上的錯誤碼是 SEGV_ACCERR。在除錯的時候,會顯示類似這樣的資訊   EXC_RESOURCE RESOURCE_TYPE_MEMORY (lim

乾貨分散式記憶體資料庫新架構,極速OLTP應用新利器

TimesTen Scaleout,它實際上是一款關係型資料庫,不過是在執行的期間,把資料全量載入到記憶體當中來進行實現。 Oracle TimesTen 先簡單的說一下TimesTen Scaleout的歷史,它實際上是一款關係型資料庫,不過是在執行的期間,把資料全量載入到記憶體當中來進行實現。Ti

引用高效軟體開發習慣總結

高效軟體開發習慣總結: 一、  程式設計與開發 1.      充分重視需求,理解需求,明確需求,確認需求; 2.      提供儘可能多的方案,選擇符合約束的最佳方案; 3.      程式設計前,儘可能將設計與實現方案思考成熟; 4.      程式設計時,寫好配

C++記憶體和棧記憶體詳解

一個由C/C++編譯的程式佔用的記憶體分為以下幾個部分  1、棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧  2、堆區(heap) — 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由OS回