HIDL MemoryBlock
هي طبقة تجريدية تم إنشاؤها باستخدام hidl_memory
وHIDL
@1.0::IAllocator
وHIDL @1.0::IMapper
. وهو مصمم لخدمات HIDL
التي تحتوي على كتل ذاكرة متعددة لمشاركة كومة ذاكرة واحدة.
أضفنا تحسينات على الأداء
يمكن أن يؤدي استخدام MemoryBlock
في التطبيقات إلى تقليل عدد أخطاء mmap
/munmap
وتقسيم مساحة المستخدم بشكل كبير، ما يؤدي إلى تحسين الأداء.
مثلاً:
- عند استخدام
hidl_memory
لكل عملية تخصيص ذاكرة تخزين مؤقت، يكون متوسط الوقت المستغرَق لكل عملية تخصيص هو 238 ميكرو ثانية. - عند استخدام
MemoryBlock
ومشاركةhidl_memory
واحد، يبلغ متوسط الوقت المستغرَق 2.82 ميكرو ثانية لكل عملية تخصيص.
هندسة معمارية
تتضمّن بنية 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; };
إذا كان التطبيق يصل إلى البيانات الوصفية بمعدّل أقل بكثير من القطعة، يكون من الأفضل تمرير البيانات الوصفية بشكل سلبي باستخدام واجهة. مثال:
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(...);