एचआईडीएल मेमोरी ब्लॉक

HIDL MemoryBlock hidl_memory , HIDL @1.0::IAllocator और HIDL @1.0::IMapper पर निर्मित एक अमूर्त परत है। इसे HIDL सेवाओं के लिए डिज़ाइन किया गया है जिनमें एकल मेमोरी हीप को साझा करने के लिए कई मेमोरी ब्लॉक होते हैं।

कार्य में सुधार

अनुप्रयोगों में मेमोरीब्लॉक का उपयोग mmap / munmap और उपयोगकर्ता स्थान विभाजन दोषों की संख्या को काफी कम कर सकता है, जिससे प्रदर्शन में सुधार हो सकता है। उदाहरण के लिए:

  • प्रत्येक बफ़र आवंटन के लिए प्रति hidl_memory उपयोग करने पर औसत 238 यूएस/1 आवंटन होता है।
  • MemoryBlock उपयोग करना और एकल hidl_memory साझा करना औसत 2.82 यूएस/1 आवंटन है।

वास्तुकला

HIDL मेमोरीब्लॉक आर्किटेक्चर में एकल मेमोरी हीप को साझा करने वाले एकाधिक मेमोरी ब्लॉक वाली HIDL सेवाएं शामिल हैं:

एचआईडीएल मेमोरीब्लॉक

चित्र 1. एचआईडीएल मेमोरीब्लॉक आर्किटेक्चर

सामान्य उपयोग

यह अनुभाग पहले एचएएल घोषित करके और फिर एचएएल लागू करके मेमोरीब्लॉक का उपयोग करने का एक उदाहरण प्रदान करता है।

एचएएल की घोषणा

निम्नलिखित उदाहरण के लिए 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 को लागू करने के लिए:

  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. प्राप्त hidl_memory के साथ एक HidlMemoryDealer बनाएं:

    #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 आवंटित करें, जो एचआईडीएल के साथ परिभाषित एक संरचना है।

    उदाहरण MemoryBlock :

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

    MemoryBlock आवंटित करने के लिए MemoryDealer का उपयोग करने का उदाहरण:

    #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 की आवश्यकता है।

    आम तौर पर, मेमोरीब्लॉक साझा hidl_memory बनाए रखने के लिए संदर्भ गणना का उपयोग करता है जो कि पहली बार mmap() -ed होता है जब इसका MemoryBlock मैप किया जाता है और जब कुछ भी इसे संदर्भित नहीं करता है तो munmap() -ed होता है। hidl_memory हमेशा मैप किए रखने के लिए, आप lockMemory उपयोग कर सकते हैं, एक RAII स्टाइल ऑब्जेक्ट जो लॉक जीवन चक्र के दौरान संबंधित hidl_memory मैप करता रहता है। उदाहरण:

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

विस्तारित उपयोग

यह अनुभाग MemoryBlock के विस्तारित उपयोग के बारे में विवरण प्रदान करता है।

मेमोरीब्लॉक को प्रबंधित करने के लिए संदर्भ गणना का उपयोग करना

अधिकांश स्थितियों में, मेमोरीब्लॉक का उपयोग करने का सबसे प्रभावी तरीका स्पष्ट रूप से आवंटित/डीललोकेट करना है। हालाँकि, जटिल अनुप्रयोगों में कचरा संग्रहण के लिए संदर्भ गणना का उपयोग करना एक बेहतर विचार हो सकता है। मेमोरीब्लॉक पर संदर्भ गणना करने के लिए, आप मेमोरीब्लॉक को बाइंडर ऑब्जेक्ट से बांध सकते हैं, जो संदर्भों को गिनने और गिनती शून्य होने पर मेमोरीब्लॉक को हटाने में मदद करता है।

एचएएल की घोषणा

HAL की घोषणा करते समय, एक HIDL संरचना का वर्णन करें जिसमें एक MemoryBlock और एक IBase शामिल हो:

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

struct MemoryBlockAllocation {
    MemoryBlock block;
    IBase refcnt;
};

MemoryBlock बदलने के लिए MemoryBlockAllocation का उपयोग करें और MemoryBlock वापस देने के लिए विधि को हटा दें। इसे MemoryBlockAllocation के साथ संदर्भ गणना द्वारा हटा दिया जाएगा। उदाहरण:

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

एचएएल का कार्यान्वयन

एचएएल के सेवा पक्ष कार्यान्वयन का उदाहरण:

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);

एचएएल के ग्राहक पक्ष कार्यान्वयन का उदाहरण:

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;
    };
    

    इसके बाद, मेमोरी डीलर का उपयोग करके मेटाडेटा को मेमोरीब्लॉक के साथ बाइंड करें। उदाहरण:

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