HIDL MemoryBlock
هي طبقة تجريدية تم إنشاؤها باستخدام hidl_memory
وHIDL
@1.0::IAllocator
وHIDL @1.0::IMapper
. تم تصميمه لخدمات HIDL
التي تحتوي على عدة كتل ذاكرة تتشارك كومة واحدة من الذاكرة.
أضفنا تحسينات على الأداء
يمكن أن يؤدي استخدام MemoryBlock
في التطبيقات إلى تقليل عدد
mmap
/munmap
وأخطاء تقسيم مساحة المستخدمين، ما يؤدي إلى تحسين الأداء
مثلاً:
- يبلغ استخدام كل
hidl_memory
لكل عملية تخصيص مخزن مؤقت 238 مستخدمًا/1. التخصيص. - عند استخدام
MemoryBlock
ومشاركةhidl_memory
واحدة، يكون المعدَّل 2.82 لنا/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 }));
إنشاء مثيل
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
" علىmmap()
في المرة الأولى التي تم فيها ربطMemoryBlock instances is mapped and is
munmap()-ed when nothing refers to it. To keep
hidl_memoryalways mapped, you can use
lockMemory, a RAII style object that keeps the corresponding
hidl_memory` في جميع أجزاء القفل. دورة حياة المنتج. مثال:#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; };
إذا كان التطبيق يصل إلى البيانات الوصفية بمعدل أقل بكثير من من الأفضل تمرير بيانات التعريف بشكل سلبي من واجهة pyplot. مثال:
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(...);