" />

色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux內核的連續內存分配器(CMA)——避免預留大塊內存

Linux閱碼場 ? 來源:未知 ? 作者:李倩 ? 2018-03-27 11:07 ? 次閱讀

這是我2012年上半年寫的文章,現在微信公眾號再次發表。

在我們使用ARM嵌入式Linux系統的時候,一個頭疼的問題是GPU,Camera,HDMI等都需要預留大量連續內存,這部分內存平時不用, 但是一般的做法又必須先預留著。目前,Marek Szyprowski和Michal Nazarewicz實現了一套全新的Contiguous Memory Allocator。通過這套機制,我們可以做到不預留內存,這些內存平時是可用的,只有當需要的時候才被分配給Camera,HDMI等設備。下面分析 它的基本代碼流程。

聲明連續內存

內核啟動過程中arch/arm/mm/init.c中的arm_memblock_init()會調用dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit));

該函數位于:drivers/base/dma-contiguous.c

其中的size_bytes定義為:

static const unsigned long size_bytes = CMA_SIZE_MBYTES * SZ_1M; 默認情況下,CMA_SIZE_MBYTES會被定義為16MB,來源于CONFIG_CMA_SIZE_MBYTES=16->

由此可見,連續內存區域也是在內核啟動的早期,通過__memblock_alloc_base()拿到的。

另外:

drivers/base/dma-contiguous.c里面的core_initcall()會導致cma_init_reserved_areas()被調用:

cma_create_area()會調用cma_activate_area(),cma_activate_area()函數則會針對每個page調用:

init_cma_reserved_pageblock(pfn_to_page(base_pfn));

這個函數則會通過set_pageblock_migratetype(page, MIGRATE_CMA)將頁設置為MIGRATE_CMA類型的:

同時其中調用的__free_pages(page, pageblock_order);最終會調用到__free_one_page(page, zone, order, migratetype);相關的page會被加到MIGRATE_CMA的free_list上面去:

list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);

申請連續內存

申請連續內存仍然使用標準的arch/arm/mm/dma-mapping.c中定義的dma_alloc_coherent()和dma_alloc_writecombine(),這二者會間接調用drivers/base/dma-contiguous.c中的

->

->

int alloc_contig_range(unsigned long start, unsigned long end,

unsigned migratetype)

需要隔離page,隔離page的作用通過代碼的注釋可以體現:

簡單地說,就是把相關的page標記為MIGRATE_ISOLATE,這樣buddy系統就不會再使用他們。

接下來調用__alloc_contig_migrate_range()進行頁面隔離和遷移:

其中的函數migrate_pages()會完成頁面的遷移,遷移過程中通過傳入的__alloc_contig_migrate_alloc()申請新的page,并將老的page付給新的page:

其中的unmap_and_move()函數較為關鍵,它定義在mm/migrate.c中

通過unmap_and_move(),老的page就被遷移過去新的page。

接下來要回收page,回收page的作用是,不至于因為拿了連續的內存后,系統變得內存饑餓:

->

->

釋放連續內存

內存釋放的時候也比較簡單,直接就是:

arch/arm/mm/dma-mapping.c:

將page交還給buddy。

內核內存分配的migratetype

內核內存分配的時候,帶的標志是GFP_,但是GFP_可以轉化為migratetype:

之后申請內存的時候,會對比遷移類型匹配的free_list:

另外,筆者也編寫了一個測試程序,透過它隨時測試CMA的功能:

/*

* kernel module helper for testing CMA

*

* Licensed under GPLv2 or later.

*/

#include

#include

#include

#include

#include

#define CMA_NUM 10

static struct device *cma_dev;

static dma_addr_t dma_phys[CMA_NUM];

static void *dma_virt[CMA_NUM];

/* any read request will free coherent memory, eg.

* cat /dev/cma_test

*/

static ssize_t

cma_test_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)

{

int i;

for (i = 0; i < CMA_NUM; i++) {??

if (dma_virt[i]) {

dma_free_coherent(cma_dev, (i + 1) * SZ_1M, dma_virt[i], dma_phys[i]);

_dev_info(cma_dev, "free virt: %p phys: %p\n", dma_virt[i], (void *)dma_phys[i]);

dma_virt[i] = NULL;

break;

}

}

return 0;

}

/*

* any write request will alloc coherent memory, eg.

* echo 0 > /dev/cma_test

*/

static ssize_t

cma_test_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)

{

int i;

int ret;

for (i = 0; i < CMA_NUM; i++) {??

if (!dma_virt[i]) {

dma_virt[i] = dma_alloc_coherent(cma_dev, (i + 1) * SZ_1M, &dma_phys[i], GFP_KERNEL);

if (dma_virt[i]) {

void *p;

/* touch every page in the allocated memory */

for (p = dma_virt[i]; p

*(u32 *)p = 0;

_dev_info(cma_dev, "alloc virt: %p phys: %p\n", dma_virt[i], (void *)dma_phys[i]);

} else {

dev_err(cma_dev, "no mem in CMA area\n");

ret = -ENOMEM;

}

break;

}

}

return count;

}

static const struct file_operations cma_test_fops = {

.owner = THIS_MODULE,

.read = cma_test_read,

.write = cma_test_write,

};

static struct miscdevice cma_test_misc = {

.name = "cma_test",

.fops = &cma_test_fops,

};

static int __init cma_test_init(void)

{

int ret = 0;

ret = misc_register(&cma_test_misc);

if (unlikely(ret)) {

pr_err("failed to register cma test misc device!\n");

return ret;

}

cma_dev = cma_test_misc.this_device;

cma_dev->coherent_dma_mask = ~0;

_dev_info(cma_dev, "registered.\n");

return ret;

}

module_init(cma_test_init);

static void __exit cma_test_exit(void)

{

misc_deregister(&cma_test_misc);

}

module_exit(cma_test_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");

MODULE_DESCRIPTION("kernel module to help the test of CMA");

MODULE_ALIAS("CMA test");

申請內存:

#echo0>/dev/cma_test

釋放內存:

#cat/dev/cma_test

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11322

    瀏覽量

    209869
  • 分配器
    +關注

    關注

    0

    文章

    194

    瀏覽量

    25778

原文標題:宋寶華:Linux內核的連續內存分配器(CMA)——避免預留大塊內存

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux內核內存規整總結

    1.前言 伙伴系統作為內核最基礎的物理頁內存分配器,具有高效、實現邏輯簡介等優點,其原理頁也盡可能降低內存外部碎片產生,但依然無法杜絕碎片問題。外部碎片帶來的最大影響就是
    的頭像 發表于 11-11 11:17 ?1344次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b><b class='flag-5'>內存</b>規整總結

    Linux內核內存管理之ZONE內存分配器

    內核中使用ZONE分配器滿足內存分配請求。該分配器必須具有足夠的空閑頁幀,以便滿足各種內存大小請
    的頭像 發表于 02-21 09:29 ?919次閱讀

    Linux內核內存管理之內核連續物理內存分配

    的主要優點是避免了外部碎片,而缺點是需要修改內核頁表。顯然,非連續內存區域的大小必須是4096的倍數。Linux使用非
    的頭像 發表于 02-23 09:44 ?1024次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b><b class='flag-5'>內存</b>管理之<b class='flag-5'>內核</b>非<b class='flag-5'>連續</b>物理<b class='flag-5'>內存</b><b class='flag-5'>分配</b>

    Linux內存系統: Linux 內存分配算法

    通用對象的初始化,從而避免了為同一目而對一個對象重復進行初始化 8、slab 高速緩存1) 普通高速緩存· slab 分配器所提供的小塊連續內存
    發表于 08-24 07:44

    如何去制作一個高效的內存分配器

    高效內存分配機制是什么意思?如何去制作一個高效的內存分配器呢?
    發表于 01-20 06:57

    內存之旅——如何提升CMA利用率?

    內存區域稱為 CMA 區域;把 CMA 的上層使用者稱為 CMA 業務。)一、為什么需要CMACMA
    發表于 03-22 16:26

    為什么需要CMACMA具體是如何工作的

    CMACMA 全稱是 Contiguous Memory Allocator(連續內存分配器)。顧名思義它是一種
    發表于 03-23 11:22

    linux內存管理中的SLAB分配器詳解

    管理區頁框分配器,這里我們簡稱為頁框分配器,在頁框分配器中主要是管理物理內存,將物理內存的頁框分配
    發表于 05-17 15:01 ?2214次閱讀
    <b class='flag-5'>linux</b><b class='flag-5'>內存</b>管理中的SLAB<b class='flag-5'>分配器</b>詳解

    深入剖析SLUB分配器和SLAB分配器的區別

    首先為什么要說slub分配器內核里小內存分配一共有三種,SLAB/SLUB/SLOB,slub分配器是slab
    發表于 05-17 16:05 ?1115次閱讀
    深入剖析SLUB<b class='flag-5'>分配器</b>和SLAB<b class='flag-5'>分配器</b>的區別

    Linux內核深度解析》之內存地址空間

    內核空間提供了把頁劃分成小內存分配的塊分配器,提供分配內存的接口 kmalloc()和釋放
    的頭像 發表于 07-15 14:22 ?2331次閱讀

    bootmem分配器使用的數據結構

    內核初始化的過程中需要分配內存內核提供了臨時的引導內存分配器,在頁
    的頭像 發表于 07-22 11:18 ?1463次閱讀

    Linux之引導內存分配器

    早期使用的引導內存分配器是 bootmem,目前正在使用 memblock 取代 bootmem。如果開啟配置宏 CONFIG_NO_BOOTMEM,memblock 就會取代 bootmem。為了保證兼容性,bootmem 和 memblock 提供了相同的接口。
    的頭像 發表于 07-22 11:17 ?1486次閱讀

    Linux內核之伙伴分配器

    內核初始化完畢后,使用頁分配器管理物理頁,當前使用的頁分配器是伙伴分配器,伙伴分配器的特點是算法簡單且效率高。
    的頭像 發表于 07-25 14:06 ?1865次閱讀

    Linux內核之塊分配器

    為了解決小塊內存分配問題,Linux 內核提供了塊分配器,最早實現的塊分配器是SLAB
    的頭像 發表于 07-27 09:35 ?1683次閱讀

    Linux內核引導內存分配器的原理

    Linux內核引導內存分配器使用的是伙伴系統算法。這種算法是一種用于動態內存分配的高效算法,它將
    發表于 04-03 14:52 ?417次閱讀
    主站蜘蛛池模板: 花蝴蝶在线直播观看| 手机伊在人线香蕉2| 伊人综合在线影院| 久久婷婷五月免费综合色啪| 2021精品乱码多人收藏| 欧美色图一区二区三区| 国产高清免费观看| 一道精品视频一区二区| 男同志vdieos免费| 国产a视频视卡在线| 一本久道久久综合婷婷五月| 免费看欧美一级特黄a大片| 国产AV果冻传奇麻豆| 一区二区三区福利视频| 泡妞高手在都市完整版视频免费| 国产人妻人伦精品久久无码| 1313久久国产午夜精品理论片| 日韩精品人成在线播放| 久久99re6热在线播放| www.x日本| 亚洲中文久久精品AV无码| 秋霞电影院兔费理论观频84mb| 国产亚洲欧美日韩综合综合二区 | 宿舍BL 纯肉各种PLAY H| 精品国产乱码久久久久久免费| 99久久国产露脸国语对白| 亚洲AV天堂无码麻豆电影| 男人J桶进男人屁股过程| 国产色无码精品视频国产| 99久久国产露脸精品国产吴梦梦| 午夜天堂AV久久久噜噜噜| 欧美Av无码高清在线| 精品三级在线观看| 国产99小视频| 99久久免费国产精品特黄| 亚洲乱码日产精品BD在线下载| 日本女人水多| 免费成年人在线观看视频| 韩日美无码精品无码| 国产99在线视频| xxx日本免费|