HIDL MemoryBlock یک لایه انتزاعی است که بر روی hidl_memory ، HIDL @1.0::IAllocator و HIDL @1.0::IMapper ساخته شده است. این برای سرویس های HIDL طراحی شده است که دارای چندین بلوک حافظه برای به اشتراک گذاشتن یک پشته حافظه واحد هستند.
بهبود عملکرد
استفاده از MemoryBlock در برنامهها میتواند به میزان قابل توجهی تعداد mmap / munmap و خطاهای تقسیمبندی فضای کاربر را کاهش دهد و در نتیجه عملکرد را بهبود بخشد. به عنوان مثال:
- استفاده از هر
hidl_memoryبرای هر تخصیص بافر به طور متوسط 238 us/1 تخصیص است. - استفاده از
MemoryBlockو به اشتراک گذاری یکhidl_memoryبه طور میانگین 2.82 us/1 تخصیص دارد.
معماری
معماری HIDL MemoryBlock شامل خدمات HIDL با چندین بلوک حافظه است که یک پشته حافظه را به اشتراک می گذارند:

شکل 1. معماری HIDL MemoryBlock
استفاده معمولی
این بخش نمونه ای از استفاده از MemoryBlock با اعلام HAL و سپس پیاده سازی HAL ارائه می دهد.
HAL را اعلام کنید
برای مثال زیر IFoo HAL:
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
getSome() generates(MemoryBlock block);
giveBack(MemoryBlock block);
};
Android.bp به شرح زیر است:
hidl_interface {
...
srcs: [
"IFoo.hal",
],
interfaces: [
"android.hidl.memory.block@1.0",
...
};
HAL را اجرا کنید
برای پیاده سازی مثال HAL:
hidl_memoryدریافت کنید (برای جزئیات، به HIDL C++ مراجعه کنید).#include <android/hidl/allocator/1.0/IAllocator.h> using ::android::hidl::allocator::V1_0::IAllocator; using ::android::hardware::hidl_memory; ... sp<IAllocator> allocator = IAllocator::getService("ashmem"); allocator->allocate(2048, [&](bool success, const hidl_memory& mem) { if (!success) { /* error */ } // you can now use the hidl_memory object 'mem' or pass it }));با
hidl_memoryبه دست آمده یک نمونهHidlMemoryDealerبسازید:#include <hidlmemory/HidlMemoryDealer.h> using ::android::hardware::HidlMemoryDealer /* The mem argument is acquired in the Step1, returned by the ashmemAllocator->allocate */ sp<HidlMemoryDealer> memory_dealer = HidlMemoryDealer::getInstance(mem);تخصیص
MemoryBlock، که ساختاری است که با HIDL تعریف شده است.نمونه
MemoryBlock:struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };مثال استفاده از
MemoryDealerبرای تخصیصMemoryBlock:#include <android/hidl/memory/block/1.0/types.h> using ::android::hidl::memory::block::V1_0::MemoryBlock; Return<void> Foo::getSome(getSome_cb _hidl_cb) { MemoryBlock block = memory_dealer->allocate(1024); if(HidlMemoryDealer::isOk(block)){ _hidl_cb(block); ...Dealocate
MemoryBlock:Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...دستکاری داده ها:
#include <hidlmemory/mapping.h> #include <android/hidl/memory/1.0/IMemory.h> using ::android::hidl::memory::V1_0::IMemory; sp<IMemory> memory = mapMemory(block); uint8_t* data = static_cast<uint8_t*>(static_cast<void*>(memory->getPointer()));پیکربندی
Android.bp:shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",برای تعیین اینکه آیا نیاز به
lockMemoryدارید، جریان را بررسی کنید.به طور معمول،
MemoryBlockاز تعداد مرجع برای حفظhidl_memoryاشتراکگذاری شده استفاده میکند که اولین باری که یکی ازMemoryBlock instances is mapped and ismmap()-ed است و-ed when nothing refers to it. To keephidl_memoryalways mapped, you can use, a RAII style object that keeps the corresponding. مثال:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
استفاده گسترده
این بخش جزئیاتی در مورد استفاده گسترده از MemoryBlock ارائه می دهد.
از تعداد مراجع برای مدیریت MemoryBlock استفاده کنید
در بیشتر مواقع، کارآمدترین راه برای استفاده MemoryBlock تخصیص/تخصیص صریح است. با این حال، در برنامه های پیچیده، استفاده از تعداد مرجع برای جمع آوری زباله ممکن است ایده بهتری باشد. برای داشتن تعداد مرجع در MemoryBlock ، میتوانید MemoryBlock با یک شی بایندر متصل کنید، که به شمارش مراجع کمک میکند و زمانی که تعداد به صفر کاهش مییابد، MemoryBlock اختصاص میدهد.
HAL را اعلام کنید
هنگام اعلام HAL، یک ساختار HIDL را توصیف کنید که شامل یک نمونه MemoryBlock و یک IBase است:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
MemoryBlock block;
IBase refcnt;
};
از MemoryBlockAllocation برای جایگزینی MemoryBlock استفاده کنید و روش بازگرداندن MemoryBlock حذف کنید. با شمارش مرجع با MemoryBlockAllocation اختصاص داده می شود. مثال:
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
HAL را اجرا کنید
نمونه ای از اجرای سمت سرویس HAL:
class MemoryBlockRefCnt: public virtual IBase {
MemoryBlockRefCnt(uint64_t offset, sp<MemoryDealer> dealer)
: mOffset(offset), mDealer(dealer) {}
~MemoryBlockRefCnt() {
mDealer->deallocate(mOffset);
}
private:
uint64_t mOffset;
sp<MemoryDealer> mDealer;
};
Return<void> Foo::allocateSome(allocateSome_cb _hidl_cb) {
MemoryBlockAllocation allocation;
allocation.block = memory_dealer->allocate(1024);
if(HidlMemoryDealer::isOk(block)){
allocation.refcnt= new MemoryBlockRefCnt(...);
_hidl_cb(allocation);
مثالی از اجرای HAL سمت مشتری:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
...
);
متادیتا را پیوست و بازیابی کنید
برخی از برنامه ها برای اتصال به MemoryBlock اختصاص داده شده به داده های اضافی نیاز دارند. با استفاده از دو روش می توانید متادیتا را اضافه و بازیابی کنید:
اگر برنامه به اندازه خود بلوک به ابرداده دسترسی دارد، متادیتا را اضافه کنید و همه آنها را در یک ساختار ارسال کنید. مثال:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };اگر برنامه با دفعات کمتری نسبت به بلوک به ابرداده دسترسی پیدا کند، انتقال ابرداده به صورت غیرفعال با یک رابط کارآمدتر است. مثال:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };سپس، با استفاده از
MemoryDealer، متادیتا را باMemoryBlockپیوند دهید. مثال:MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);