HIDL MemoryBlock لایه انتزاعی است که روی hidl_memory، HIDL
@1.0::IAllocator، و HIDL @1.0::IMapper ساخته شده است. این ویژگی برای سرویسهای HIDL طراحی شده است
که چندین بلوک حافظه دارند تا یک پشته حافظه را همرسانی کنند.
بهبود عملکرد
استفاده از MemoryBlock در برنامهها میتواند تعداد خطاهای
mmap/munmap و خطاهای تقسیمبندی فضای کاربر را بهطور قابلتوجهی کاهش دهد و درنتیجه عملکرد را بهبود بخشد.
برای مثال:
- Using per
hidl_memoryfor each buffer allocation averages 238 us/1 allocation. - Using
MemoryBlockand sharing a singlehidl_memoryaverages 2.82 us/1 allocation.
معماری
معماری HIDL MemoryBlock شامل سرویسهای HIDL با چندین بلوک حافظه است که یک توده حافظه واحد را به اشتراک میگذارند:
شکل ۱. معماری 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 نمونه:
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); ...لغو تخصیص
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 ismunmap()-ed when nothing refers to it. To keephidl_memoryalways mapped, you can uselockMemory, a RAII style object that keeps the correspondinghidl_memory در سراسر چرخه حیات قفلmmap()نگاشت میشود. مثال:#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:
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; };سپس، فراداده را با
MemoryBlockبااستفاده ازMemoryDealerپیوند دهید. مثال:MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);