HIDL MemoryBlock

HIDL MemoryBlock, hidl_memory, HIDL @1.0::IAllocator ve HIDL @1.0::IMapper üzerine inşa edilmiş soyut bir katmandır. Tek bir bellek yığınını paylaşmak için birden fazla bellek bloğu olan HIDL hizmetleri için tasarlanmıştır.

Performans iyileştirmeleri

Uygulamalarda MemoryBlock kullanmak, mmap/munmap ve kullanıcı alanı segmentasyon hatalarının sayısını önemli ölçüde azaltarak performansı artırabilir. Örnek:

  • Her arabelleği ayırma için hidl_memory başına kullanım, 1 ayırma başına ortalama 238 us'dir.
  • MemoryBlock kullanarak ve tek bir hidl_memory paylaşarak 1 tahsisat için ortalama 2,82 ABD doları ödersiniz.

Mimari

HIDL MemoryBlock mimarisi, tek bir bellek yığınını paylaşan birden fazla bellek bloğu içeren HIDL hizmetlerini içerir:

HIDL MemoryBlock

Şekil 1. HIDL MemoryBlock mimarisi

Normal kullanım

Bu bölümde, önce HAL'i açıklayarak, ardından HAL'i uygulayarak MemoryBlock'ü kullanma örneği verilmiştir.

HAL'i beyan etme

Aşağıdaki örnekte IFoo HAL:

import android.hidl.memory.block@1.0::MemoryBlock;

interface IFoo {
    getSome() generates(MemoryBlock block);
    giveBack(MemoryBlock block);
};

Android.bp aşağıdaki gibidir:

hidl_interface {
    ...
    srcs: [
        "IFoo.hal",
    ],
    interfaces: [
        "android.hidl.memory.block@1.0",
        ...
};

HAL'i uygulama

Örnek HAL'i uygulamak için:

  1. hidl_memory değerini alın (ayrıntılar için HIDL C++ bölümüne bakın).

    #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. Satın alınan hidl_memory ile bir HidlMemoryDealer örneği oluşturun:

    #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. HIDL ile tanımlanan bir yapı olan MemoryBlock'ü ayırın.

    Örnek MemoryBlock:

    struct MemoryBlock {
    IMemoryToken token;
    uint64_t size;
    uint64_t offset;
    };
    

    MemoryBlock atama işlemi için MemoryDealer işlevinin kullanıldığı örnek:

    #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 için ayrılan alanı kaldırın:

    Return<void> Foo::giveBack(const MemoryBlock& block) {
        memory_dealer->deallocate(block.offset);
    ...
    
  5. Verileri işleme:

    #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 yapılandırması:

    shared_libs: [
            "android.hidl.memory@1.0",
    
            "android.hidl.memory.block@1.0"
    
            "android.hidl.memory.token@1.0",
            "libhidlbase",
            "libhidlmemory",
    
  7. lockMemory yapmanız gerekip gerekmediğini belirlemek için akışı inceleyin.

    Normalde MemoryBlock, kilit yaşam döngüsü boyunca eşlenen 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` öğelerinden biri ilk kez mmap() edildiğinde paylaşılan hidl_memory'ı korumak için referans sayısını kullanır. Örnek:

    #include <hidlmemory/mapping.h>
    
    sp<RefBase> lockMemory(const sp<IMemoryToken> key);
    

Genişletilmiş kullanım

Bu bölümde, MemoryBlock'ün genişletilmiş kullanımıyla ilgili ayrıntılar verilmektedir.

MemoryBlock'u yönetmek için referans sayısını kullanma

Çoğu durumda, MemoryBlock'ü kullanmanın en verimli yolu açıkça ayırmaktır/ayrılmamış duruma getirmektir. Ancak karmaşık uygulamalarda, referans sayısını kullanarak çöp toplama işlemini gerçekleştirmek daha iyi bir fikir olabilir. MemoryBlock'te referans sayısının olması için MemoryBlock'yi bir bağlayıcı nesneyle bağlayabilirsiniz. Bu, referansları saymanıza ve sayı sıfıra düştüğünde MemoryBlock'nin ayrılmasına yardımcı olur.

HAL'i beyan etme

HAL'i tanımlarken bir MemoryBlock örneği ve IBase içeren bir HIDL yapısı tanımlayın:

import android.hidl.memory.block@1.0::MemoryBlock;

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

MemoryBlock yerine MemoryBlockAllocation'ü kullanmak için MemoryBlockAllocation'ü, MemoryBlock'ü geri vermek için ise yöntemi kaldırın. MemoryBlockAllocation ile referans sayımı yapılarak ayrılır. Örnek:

interface IFoo {
    allocateSome() generates(MemoryBlockAllocation allocation);
};

HAL'i uygulama

HAL'in hizmet tarafı uygulaması örneği:

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'in istemci tarafı uygulaması örneği:

ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
    ...
);

Meta veri ekleme ve alma

Bazı uygulamaların, ayrılan MemoryBlock ile bağlanmak için ek verilere ihtiyacı vardır. Meta verileri eklemek ve almak için iki yöntemden birini kullanabilirsiniz:

  • Uygulama, meta verilere bloğun kendisi kadar sık erişiyorsa meta verileri ekleyin ve hepsini bir yapıda iletin. Örnek:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        MetaDataStruct metaData;
    };
    
  • Uygulama, meta verilere bloğa kıyasla çok daha az sıklıkta erişiyorsa meta verileri bir arayüzle pasif olarak iletmek daha verimlidir. Örnek:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        IMetaData metaData;
    };
    

    Ardından, MemoryDealer kullanarak meta verileri MemoryBlock ile bağlayın. Örnek:

    MemoryBlockWithMetaData memory_block;
    memory_block.block = dealer->allocate(size);
    if(HidlMemoryDealer::isOk(block)){
        memory_block.metaData = new MetaData(...);