功能说明
===============

hbmem模块主要实现的功能包括 **内存分配** 、 **内存共享** 、 **内存队列管理** 和 **内存池** ，专门用于对 **系统预留内存** 进行管理。

.. image:: ./media/image1.png
   :align: center
   :alt:

内存分配
------------

内存分配相关接口主要实现了连续物理内存的分配、释放和刷新等功能。该模块提供了两种类型的内存分配，com_buf用于常规的整块连续内存分配，适用于语音，纯featuremap等场景，graph_buf用于RGB、RAW和YUV图像的内存分配，对于RGB和RAW格式，使用一个buffer；对于planar YUV格式，各个component的物理地址不连续 ，适用于Pyramid的输出buffer等场景。

此外如果需要申请使用多个graphic，可以利用graphic buffer group相关的接口。这系列接口支持一次性申请多个graphic buffer，并组成一个group返回。

该模块同时支持设置内存属性，包括cache属性和内存heap属性等。内存分配成功后， **用户可获得对应的文件句柄** 。基于该文件句柄，用户可对相关的物理内存进行释放，invalidate/flush，获取buffer信息等操作。为了便于用户操作内存，该模块也支持使用虚拟地址进行invalidate/flush，获取buffer信息等操作。

不建议用户直接对物理地址进行mmap或传递等操作，这些操作 **不会增加该内存的引用计数** ，存在内存释放后用户仍在访问的情况。

内存共享
------------

内存共享模块相关接口实现了多个线程/进程之间的内存安全共享。用户可直接传递com_buf或graph_buf类型的buffer到另一个线程或进程中，再通过相关import接口导入该buffer，进而获取该buffer的相关信息以及增加对该buffer的引用计数，防止被其他模块释放，从而实现buffer的安全共享。主要通过内存队列管理实现buffer在生产者和消费者之间的共享操作。

同时，graphic buffer group也支持多线程/进程之后的内存安全共享，使用方法与graphic buffer类似。

内存队列管理
----------------

内存队列管理模块提供了一种通用的队列管理机制，该机制支持生产者和消费者以 **FREE/DEQUEUE/QUEUE/REQUEST** 4种状态操作队列元素。FREE状态代表生产者可获取该队列空间并填充元素信息；DEQUEUE状态代表该元素被生产者获取并尚未归还；QUEUE状态代表生产者已填充该队列元素并可被消费者获取；REQUEST状态代表该元素被消费者获取并尚未释放。生产者和消费者通过各自的接口保证buffer元素在两者之间正常轮转。

**需要注意的是，因为内存队列为一个环形队列，所以要当队列满了之后，再往队列中写入事件，就会将之前的第一个事件给覆盖。此外，该队列只支持单进程内操作。**

.. image:: ./media/image2.png
   :align: center
   :alt:

内存池
----------

内存池模块相关接口支持用户通过内存分配功能创建本地内存池，再从该内存池中分配和释放小块的内存。

**使用内存池模块可以保证用户不经过内核态快速分配内存** ，从而实现更高效的内存管理。目前用户程序（hbrt、dnn等）中常有自身实现的内存管理模块来提高内存分配速度，造成代码重复，开发和维护不便，因此用户可使用内存池模块来进行内存管理，可提高模块的复用性。

在系统启动过程中，提前为用户申请一块大内存，这样用户在申请内存时，可以直接使用内存池中的内存，绕过了陷入内核态申请内存的步骤，或者说是提前将该步骤实现了。 **需要注意的是，该内存池暂时只支持单进程内操作，从内存池上分配得到的内存不支持多进程间共享。**

共享内存池
--------------

共享内存池功能同上，不同在于共享内存池分配的内存支持多进程共享，但是从共享内存池上分配的buffer大小相同，且buffer的大小只能在创建共享内存池时指定。由于支持多进程共享，共享内存池分配的内存在做import、free时，效率略低于普通内存。
