HIDL MemoryBlock

HIDL MemoryBlock, hidl_memory, HIDL @1.0::IAllocator ve HIDL @1.0::IMapper üzerine kurulu soyut bir katmandır. Tek bir bellek yığı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. Örneğin:

  • Her arabellek ayırma işlemi için hidl_memory kullanıldığında ortalama 238 μsn/1 ayırma işlemi elde edilir.
  • MemoryBlock kullanmak ve tek bir hidl_memory paylaşmak ortalama 2,82 μsn/1 ayırma süresine karşılık gelir.

Mimari

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

HIDL MemoryBlock

1. şekil. HIDL MemoryBlock mimarisi

Normal kullanım

Bu bölümde, önce HAL'yi bildirip ardından HAL'yi uygulayarak MemoryBlock kullanma örneği verilmektedir.

HAL'yi beyan etme

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

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

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

Android.bp şu şekildedir:

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

HAL'yi uygulama

Örnek HAL'yi uygulamak için:

  1. hidl_memory (Ayrıntılar için HIDL C++ başlıklı makaleyi inceleyin).

    #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ımlanmış bir yapı olan MemoryBlock öğesini ayırın.

    Örnek MemoryBlock:

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

    MemoryDealer kullanarak MemoryBlock ayırma örneği:

    #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 öğesinin tahsisini kaldırma:

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

    #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. Yapılandırma 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 gerekip gerekmediğini belirlemek için akışı inceleyin.

    Normalde, MemoryBlock, paylaşılan hidl_memory öğesini korumak için referans sayısı kullanır. Bu öğe, 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()-lendiğinde oluşturulur. Örnek:

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

Genişletilmiş kullanım

Bu bölümde, MemoryBlock'nı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'yı kullanmanın en etkili yolu açıkça ayırmak/ayırmaktır. Ancak, çöp toplama için referans sayısı kullanan karmaşık uygulamalarda bu yöntem daha iyi olabilir. MemoryBlock üzerinde referans sayımı yapmak için MemoryBlock öğesini bir bağlayıcı nesneyle bağlayabilirsiniz. Bu, referansları saymaya ve sayı sıfıra düştüğünde MemoryBlock öğesinin tahsisini kaldırmaya yardımcı olur.

HAL'yi beyan etme

HAL'yi bildirirken MemoryBlock örneği ve IBase içeren bir HIDL yapısı açıklayın:

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

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

MemoryBlock yerine MemoryBlockAllocation kullanın ve MemoryBlock'ı geri vermek için yöntemi kaldırın. MemoryBlockAllocation ile referans sayımı yapılarak serbest bırakılır. Örnek:

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

HAL'yi uygulama

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

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

Meta verileri 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öntem kullanabilirsiniz:

  • Uygulama, meta verilere blokla aynı sıklıkta 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 bloktan ç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(...);