ひでみのアイデア帳

くだらないことなんだけど、忘れないために・・・

Linuxでのメモリ確保

Linuxでメモリ確保をするのをケース別で・・・

(1) アプリで確保

通常のアプリでメモリを確保する。

これはmallocだよね。

特に説明する必要はないのでgoogleで"man malloc"でもすれば良い。

(2) カーネルで確保

(2-1) 4K以下なら

slab領域から取得すれば良い。

kmallocすれば良い。

これも特に説明する必要はないのでgoogle先生に"man kmalloc"とすれば良い。

(2-2) 4K以上なら

vmallocでも良いか・・・

vmallocは使わないので調べてない。

間違えてたらゴメン。

(2-3) Linuxから見えない領域にする。

実メモリが1GBならKernel起動時に例えば"mem=768M"とすると、1GB空間の実メモリのうち、後半の256MBはLinuxが使わない空間になる。

ここをLinuxからmmapで確保する。

mmapはKernel 3.X系では2MBまで確保できるようになったらしいが、Linuxには基本4KBのページングがあることを忘れてはいけない。

下図のようにLinux領域とピンク領域を物理的に分けてしまう方法だね。

連続領域が必要なDMAを実装したり、Linuxに明示的に邪魔されたくない場合はこの方法を使用する。

![](./files/675059103511472.png" width="480)

(2-4) CMA(Contiguous Memory Allocator)

CMA領域を使用して、連続したメモリ領域を取得する。

連続領域が必要なDMAを実装する場合で、かつ、Linux用のメモリとしても使用したい場合はこの方法を使用する。

確保方法は下記の通りである。

  {

    int dmasize = 0;

    char *dmabuf = NULL;

    dma_addr_t dmaphys = 0;

    dmasize = 0x1000000;

    dmabuf = dma_alloc_coherent(NULL, dmasize, &dmaphys, GFP_KERNEL|GFP_DMA),

    printk(KERN_INFO "Depois do dma_alloc\n"),

        if (!dmabuf){

      printk("can''t alloc dmabuf\n"),

    }else{

      printk("dmabuf: %08X\n", dmaphys),

    }

  }

コンフィグでCMAを有効にすることと、メモリ領域を予め指定しておくことが必要。

Kernelの起動時に"CMA=16M"としても良い。

開放は"dma_free_coherent"する。

(3)まとめ

ユーザランドでMMUで取得して、それをDMAにscatter/gather空間としてDMAできると良いのだが、これに対応するにはハードのMMU、Linuxの仮想メモリ空間、DMA回路への合わせこみとかなり大変な作業になる。

そこら辺を意識したOSならいいんだが、Linuxだと大変そうだなぁ。

自作DMAでも、scatter/gather化することはそう滅多に無いので、連続領域が取れればOKだ。