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

شکل 1. معماری بلوک حافظه HIDL
استفاده عادی
این بخش مثالی از استفاده از MemoryBlock را ارائه میدهد که در آن ابتدا 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-alloca&te(2048, [](bool success, const h&idl_memory mem) { if (!success) { /* error */ } // you can now use the hidl_memory object 'mem'or pass it }));یک نمونه
HidlMemoryDealerباhidl_memoryاکتسابی ایجاد کنید:#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); ...آزادسازی
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 isآن،mmap()-ed و-ed when nothing refers to it. To keephidl_memoryalways mapped, you can uselockMemory, a RAII style object that keeps the correspondingاستفاده کنید. مثال:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
استفاده گسترده
این بخش جزئیاتی در مورد کاربرد گسترده MemoryBlock ارائه میدهد.
استفاده از تعداد ارجاع برای مدیریت MemoryBlock
در بیشتر مواقع، کارآمدترین روش برای استفاده MemoryBlock تخصیص/حذف صریح منابع است. با این حال، در برنامههای پیچیده، استفاده از تعداد مرجع برای جمعآوری زباله ممکن است ایده بهتری باشد. برای داشتن تعداد مرجع در MemoryBlock ، میتوانید MemoryBlock با یک شیء binder متصل کنید، که به شمارش منابع و آزادسازی 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 اختصاص داده شده به دادههای اضافی نیاز دارند. میتوانید با استفاده از دو روش، متادیتا را اضافه و بازیابی کنید:
اگر برنامه به متادیتا به اندازه خود بلوک دسترسی دارد، متادیتا را ضمیمه کرده و همه آنها را در یک ساختار (struct) ارسال کنید. مثال:
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(...);