HIDL MemoryBlock

HIDL MemoryBlock; hidl_memory, HIDL @1.0::IAllocator ve HIDL @1.0::IMapper üzerinde oluşturulmuş soyut bir katmandır. HIDL hizmetleri için tasarlanmıştır tek bir bellek yığınını paylaşacak birden fazla bellek bloğuna sahip olmalıdır.

Performans iyileştirmeleri

Uygulamalarda MemoryBlock kullanmak, mmap/munmap ve kullanıcı alanı segmentasyonu hataları nedeniyle performans artar. Örnek:

  • Her tampon payı için hidl_memory başına kullanım ortalaması 238 ABD/1 tahsis etme anlamına gelir.
  • MemoryBlock kullanımı ve tek bir hidl_memory paylaşımı ortalama 2,82 ABD doları/1 tahsis etme anlamına gelir.

Mimari

HIDL MemoryBlock mimarisi, birden çok belleğe sahip HIDL hizmetlerini içerir. tek bir bellek yığınını paylaşan bloklar:

HIDL MemoryBlock

Şekil 1. HIDL MemoryBlock mimarisi

Normal kullanım

Bu bölümde, önce şunu beyan ederek MemoryBlock kullanımına bir örnek verilmiştir: HAL, ardından HAL'yi uygulama.

HAL beyanı

Aşağıdaki IFoo HAL örneği için:

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'yi uygulama

Örnek HAL'yi uygulamak için:

  1. hidl_memory belgesini edinin (ayrıntılar için HIDL'ye bakın) C++) kullanabilirsiniz.

    #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. Edinilen 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 struct olan MemoryBlock ayırın.

    Örnek MemoryBlock:

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

    MemoryBlock ayırmak için MemoryDealer öğesinin 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 bayisi:

    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 işlemini yapmanız gerekip gerekmediğini belirlemek için akışı inceleyin.

    Normalde MemoryBlock, paylaşılan veri miktarını korumak için referans sayısını kullanır hidl_memory, kilit boyunca 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" parametresinden ilk kez eşlendiğinde mmap()-edildi yaşam döngüsü boyunca geçerlidir. Örnek:

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

Uzun süreli kullanım

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

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

Çoğu durumda, MemoryBlock kullanmanın en etkili yolu tahsis etme anlamına gelir. Ancak, referans sayısı kullanan karmaşık uygulamalarda düşünmesi daha iyi bir fikir olabilir. Referans sayısının açık olması için MemoryBlock bir bağlayıcı nesneyle MemoryBlock bağlayabilirsiniz. Bu, şunları yapmanıza yardımcı olur: referansları say ve sayı azaldığında MemoryBlock öğesini ayır sıfıra eşittir.

HAL beyanı

HAL belirtirken, MemoryBlock içeren bir HIDL yapısı açıklayın örnek ve bir IBase:

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

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

MemoryBlock yöntemini değiştirmek ve yöntemi kaldırmak için MemoryBlockAllocation kullanın MemoryBlock olarak bağışta bulunduk. Referans sayımına göre anlaşmaya varılır MemoryBlockAllocation ile birlikte. Örnek:

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

HAL'yi uygulama

HAL'nin hizmet tarafı uygulamasına örnek:

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

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

Meta veri ekleme ve alma

Bazı uygulamalar, ayrılan MemoryBlock ile bağlantı kurmak için ek verilere ihtiyaç duyar. Meta verileri iki yöntem kullanarak ekleyebilir ve alabilirsiniz:

  • Uygulama, meta verilere engellemenin kendisi kadar sık erişiyorsa meta verileri ekleyip tümünü bir struct'ta iletebilirim. Örnek:

    import android.hidl.memory.block@1.0::MemoryBlock;
    
    struct MemoryBlockWithMetaData{
        MemoryBlock block;
        MetaDataStruct metaData;
    };
    
  • Uygulama, meta verilere meta verileri pasif bir şekilde iletmek yerine bir kullanır. Örnek:

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

    Daha sonra, 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(...);