قفل الذاكرة HIDL

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 ذات الذاكرة المتعددة. الوحدات التي تتشارك في كومة واحدة من الذاكرة:

قفل الذاكرة 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:

  1. الحصول على "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
      }));
    
  2. إنشاء مثيل 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);
    
  3. يمكنك تخصيص "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);
        ...
    
  4. توزيع MemoryBlock:

    Return<void> Foo::giveBack(const MemoryBlock& block) {
        memory_dealer->deallocate(block.offset);
    ...
    
  5. معالجة البيانات:

    #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()));
    
  6. الإعداد Android.bp:

    shared_libs: [
            "android.hidl.memory@1.0",
    
            "android.hidl.memory.block@1.0"
    
            "android.hidl.memory.token@1.0",
            "libhidlbase",
            "libhidlmemory",
    
  7. راجِع المسار لتحديد ما إذا كنت بحاجة إلى lockMemory.

    يستخدم MemoryBlock عادةً عدد المراجع للحفاظ على القيم المشتركة تم ضبط "hidl_memory" على mmap() في المرة الأولى التي تم فيها ربط 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` في جميع أجزاء القفل. دورة حياة المنتج. مثال:

    #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(...);