Linux cma预留内存使用与理解

1 概述

        本文主要介绍在Linux中如何预留出一块内存,以及预留内存的原理与使用方式,只停留在应用阶段,因为涉及Linux内存管理,没有深入Linux对预留管理的基础原理和源码,留待后续Linux内存管理章节分析。读者若只想了解如何在Linux下预留内存的应用,本文比较合适。

        本文验证环境使用qemu模拟vpress平台做的,关于该环境的搭建,参考笔者之前写的文章:

使用qemu搭建armv7嵌入式开发环境_qemu armv7-优快云博客

2 Linux下的CMA

2.1 CMA

        Linux内核的连续内存分配器 (CMA),Contiguous Memory Allocator,是内存管理子系统中的一个模块,负责物理地址连续的内存分配。CMA的核心并不是设计精巧的算法来管理地址连续的内存块,实际上它的底层还是依赖内核伙伴系统这样的内存管理机制,或者说CMA是处于需要连续内存块的其他内核模块(例如DMA mapping framework)和内存管理模块之间的一个中间层模块。

        CMA同时也用于解决大内存预留带来的内存碎片,同时支持在预留内存空闲时返回系统使用,充分利用内存空间。

2.2 预留内存的声明

        预留内存可以指定常用的属性,常见有:

        (1). reusable:表示当前的内存区域除了被dma使用之外,还可以被内存管理(buddy)子系统reuse。

        (2). no-map:表示是否需要创建页表映射,对于通用的内存,必须要创建映射才可以使用,共享CMA是可以作为通用内存进行分配使用的,因此必须要创建页表映射。

        (3). linux,cma-default:如果要cma区域为共享区域,需要配置上linux,cma-default属性。 指定了 linux,cma-default 属性,内核在分配 cma 内存时会将这片内存当成默认的 cma 分配池使用,执行内存申请时如果没有指定对应的 cma 就使用默认 cma pool。

        (4). alignment:对齐参数,保留内存的起始地址需要向该参数对齐

        (5). alloc-ranges:指定可以用来申请动态保留内存的区间.

        (6). shared-dma-pool(compatible="shared-dma-pool"):

        有的时候设备驱动程序需要采用DMA的方式使用预留的内存,对于这种场景,可以dts中的节点属性设置为shared-dma-pool,从而生成为特定设备驱动程序预留的DMA内存池。这样,设备驱动程序仅需要以常规方式使用DMA API。

2.3 内核配置

        Linux要支持CMA内存,通过dma接口使用CMA内存池内存,需要打开以下配置:

CONFIG_DMA_CMA=y
CONFIG_CMA=y

也可大小相关调试开关

CONFIG_CMA_DEBUG=y
CONFIG_CMA_DEBUGFS=y

3 Linux下使用cma

        本节主要介绍驱动如何使用Linux的cam来预留内存方法,分别有预留内存给专门的设备驱动、通过DMA的API来预留内存、使用CAM内存池预留内存。同时Linux也支持通过启动参数来预留内存。

3.1 预留内存给专门设备驱动

        预留内存给设备驱动,不再将这些内存给系统使用时,需要在设备树申明no-map。如下设备树声明:

reserved-memory {
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;
    ...
        test_reserver_sh:test_reserver_sh_region@70000000 {
            compatible = "shared-dma-pool";
            reg = <0x70000000 0x6000000>;
            no-map;
        };
...
};
camsh_lab:camsh_lab {
        compatible = "test,cam_m_sh";
        memory-region = <&test_reserver_sh>;
        status = "okay";
  };

        在代码中使用:

static struct cma_lab_ampdata cmash_lab_amp = {
    .name = "lab_of_cma_sh",
    .type = TEST_CMA_SHARED,
};

static const struct of_device_id memory_cam_lab_match[] = {
    {
        .compatible = "test,cam_m",
        .data = &cma_lab_amp,
    },
    {
        .compatible = "test,cam_m_sh",
        .data = &cmash_lab_amp,
    },
    {
        .compatible = "test,cam_m_pool",
        .data = &cmash_lab_pool,
    },
    {}
};
MODULE_DEVICE_TABLE(of, memory_cam_lab_match);

static int cma_lab_probe(struct platform_device *pdev)
{
    const struct cma_lab_ampdata *cma_match_data = NULL;
    struct device *dev = &pdev->dev;
    unsigned int dma_addr = 0;
    void *addr;
    struct device_node* dev_node;
    struct resource res;
    void* base;
    int ret = 0;
    dev_info(dev, "cma data probe hit\n");
    cma_match_data = of_device_get_match_data(&pdev->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值