HIDL MemoryBlock
là một lớp trừu tượng được xây dựng trên hidl_memory
, HIDL
@1.0::IAllocator
và HIDL @1.0::IMapper
. Dịch vụ này được thiết kế cho các dịch vụ HIDL
có nhiều khối bộ nhớ dùng chung một vùng nhớ khối xếp bộ nhớ.
Cải thiện hiệu suất
Việc sử dụng MemoryBlock
trong các ứng dụng có thể làm giảm đáng kể số lượng
mmap
/munmap
và lỗi phân đoạn theo không gian của người dùng, nhờ đó cải thiện hiệu suất.
Ví dụ:
- Việc sử dụng trên mỗi
hidl_memory
cho mỗi mức phân bổ vùng đệm trung bình là 238 us/1 thời gian phân bổ. - Việc sử dụng
MemoryBlock
và chia sẻ mộthidl_memory
duy nhất có trung bình 2,82 chúng tôi/1 thời gian phân bổ.
Kiến trúc
Kiến trúc HIDL MemoryBlock
bao gồm các dịch vụ HIDL có nhiều bộ nhớ
chặn thao tác chia sẻ một vùng nhớ khối xếp bộ nhớ duy nhất:
Hình 1. Cấu trúc HIDL MemoryBlock
Mức sử dụng thông thường
Phần này đưa ra ví dụ về cách sử dụng MemoryBlock
bằng cách khai báo trước thuộc tính
HAL sau đó triển khai HAL.
Khai báo HAL
Trong ví dụ sau đây về IFoo HAL:
import android.hidl.memory.block@1.0::MemoryBlock;
interface IFoo {
getSome() generates(MemoryBlock block);
giveBack(MemoryBlock block);
};
Android.bp
như sau:
hidl_interface {
...
srcs: [
"IFoo.hal",
],
interfaces: [
"android.hidl.memory.block@1.0",
...
};
Triển khai HAL
Cách triển khai HAL (Lớp trừu tượng phần cứng) mẫu:
Lấy
hidl_memory
(để biết chi tiết, hãy tham khảo 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 }));
Tạo một thực thể
HidlMemoryDealer
bằnghidl_memory
đã thu nạp được:#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);
Phân bổ
MemoryBlock
(một cấu trúc được xác định bằng HIDL).Ví dụ
MemoryBlock
:struct MemoryBlock { IMemoryToken token; uint64_t size; uint64_t offset; };
Ví dụ về cách sử dụng
MemoryDealer
để phân bổ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); ...
Phân bổ
MemoryBlock
:Return<void> Foo::giveBack(const MemoryBlock& block) { memory_dealer->deallocate(block.offset); ...
Thao túng dữ liệu:
#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()));
Cấu hình
Android.bp
:shared_libs: [ "android.hidl.memory@1.0", "android.hidl.memory.block@1.0" "android.hidl.memory.token@1.0", "libhidlbase", "libhidlmemory",
Xem xét quy trình để xác định xem bạn có cần
lockMemory
hay không.Thông thường,
MemoryBlock
sử dụng số lượng tham chiếu để duy trìhidl_memory
đượcmmap()
-ed lần đầu tiên một trong nhữngMemoryBlock instances is mapped and is
munmap()-ed when nothing refers to it. To keep
hidl_memoryalways mapped, you can use
lockMemory, a RAII style object that keeps the corresponding
hidl_memory` được ánh xạ trong toàn bộ khoá vòng đời. Ví dụ:#include <hidlmemory/mapping.h> sp<RefBase> lockMemory(const sp<IMemoryToken> key);
Sử dụng mở rộng
Phần này cung cấp thông tin chi tiết về việc sử dụng mở rộng MemoryBlock
.
Sử dụng số lượng tham chiếu để quản lý MemoryBlock
Trong hầu hết trường hợp, cách hiệu quả nhất để sử dụng MemoryBlock
là nêu rõ
phân bổ/phân bổ. Tuy nhiên, trong những ứng dụng phức tạp sử dụng số lượng tham chiếu
để thu gom rác có thể là ý tưởng tốt hơn. Để có số lượng tham chiếu trên
MemoryBlock
, bạn có thể liên kết MemoryBlock
bằng một đối tượng liên kết để
đếm các tệp tham chiếu và phân loại MemoryBlock
khi số lượng giảm xuống
về 0.
Khai báo HAL
Khi khai báo HAL, hãy mô tả cấu trúc HIDL chứa MemoryBlock
và một IBase:
import android.hidl.memory.block@1.0::MemoryBlock;
struct MemoryBlockAllocation {
MemoryBlock block;
IBase refcnt;
};
Sử dụng MemoryBlockAllocation
để thay thế MemoryBlock
và xoá phương thức
để hoàn lại MemoryBlock
. Nó được giải phóng bằng cách tính tham chiếu
cùng với MemoryBlockAllocation
. Ví dụ:
interface IFoo {
allocateSome() generates(MemoryBlockAllocation allocation);
};
Triển khai HAL
Ví dụ về cách triển khai phía dịch vụ của 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);
Ví dụ về cách triển khai HAL (Lớp trừu tượng phần cứng) phía máy khách:
ifoo->allocateSome([&](const MemoryBlockAllocation& allocation){
...
);
Đính kèm và truy xuất siêu dữ liệu
Một số ứng dụng cần thêm dữ liệu để liên kết với MemoryBlock
được phân bổ.
Bạn có thể nối thêm và truy xuất siêu dữ liệu bằng hai phương thức:
Nếu ứng dụng truy cập vào siêu dữ liệu thường xuyên như chính khối, thêm siêu dữ liệu và truyền tất cả vào một cấu trúc. Ví dụ:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; MetaDataStruct metaData; };
Nếu ứng dụng truy cập siêu dữ liệu ít thường xuyên hơn so với thì sẽ hiệu quả hơn nếu truyền siêu dữ liệu một cách thụ động bằng . Ví dụ:
import android.hidl.memory.block@1.0::MemoryBlock; struct MemoryBlockWithMetaData{ MemoryBlock block; IMetaData metaData; };
Tiếp theo, hãy liên kết siêu dữ liệu với
MemoryBlock
bằngMemoryDealer
. Ví dụ:MemoryBlockWithMetaData memory_block; memory_block.block = dealer->allocate(size); if(HidlMemoryDealer::isOk(block)){ memory_block.metaData = new MetaData(...);