আপনি যদি এআইডিএল সমর্থন খুঁজছেন তবে এআইডিএল-এর সাথে এফএমকিউও দেখুন।
HIDL এর রিমোট প্রসিডিওর কল (RPC) পরিকাঠামো বাইন্ডার মেকানিজম ব্যবহার করে, যার অর্থ কলগুলি ওভারহেড জড়িত, কার্নেল অপারেশনের প্রয়োজন এবং শিডিউলার অ্যাকশন ট্রিগার করতে পারে। যাইহোক, যেসব ক্ষেত্রে কম ওভারহেড এবং কোনো কার্নেল জড়িত না থাকা প্রসেসের মধ্যে ডেটা স্থানান্তর করতে হবে, ফাস্ট মেসেজ কিউ (FMQ) সিস্টেম ব্যবহার করা হয়।
FMQ পছন্দসই বৈশিষ্ট্য সহ বার্তা সারি তৈরি করে। একটি MQDescriptorSync
বা MQDescriptorUnsync
অবজেক্ট একটি HIDL RPC কলের মাধ্যমে পাঠানো যেতে পারে এবং বার্তা সারিতে অ্যাক্সেস করার জন্য গ্রহণ প্রক্রিয়া দ্বারা ব্যবহার করা যেতে পারে।
ফাস্ট মেসেজ সারিগুলি শুধুমাত্র C++ এবং Android 8.0 এবং উচ্চতর সংস্করণে চালিত ডিভাইসগুলিতে সমর্থিত।
বার্তা সারি প্রকার
অ্যান্ড্রয়েড দুটি সারি ধরনের সমর্থন করে ( স্বাদ নামে পরিচিত):
- আনসিঙ্ক্রোনাইজড সারিগুলিকে ওভারফ্লো করার অনুমতি দেওয়া হয় এবং অনেক পাঠক থাকতে পারে; প্রতিটি পাঠকের অবশ্যই সময়মতো ডেটা পড়তে হবে বা এটি হারাতে হবে।
- সিঙ্ক্রোনাইজড সারিগুলিকে ওভারফ্লো করার অনুমতি দেওয়া হয় না এবং শুধুমাত্র একজন পাঠক থাকতে পারে৷
উভয় সারির ধরনকে আন্ডারফ্লো করার অনুমতি দেওয়া হয় না (একটি খালি সারি থেকে পড়া ব্যর্থ হয়) এবং শুধুমাত্র একজন লেখক থাকতে পারে।
আনসিঙ্ক্রোনাইজড
একটি অসিঙ্ক্রোনাইজড সারিতে শুধুমাত্র একজন লেখক আছে, কিন্তু পাঠকদের সংখ্যা যেকোনও থাকতে পারে। সারির জন্য একটি লেখার অবস্থান আছে; যাইহোক, প্রতিটি পাঠক তার নিজস্ব স্বাধীন পঠন অবস্থানের উপর নজর রাখে।
সারিতে লেখা সবসময় সফল হয় (ওভারফ্লো পরীক্ষা করা হয় না) যতক্ষণ না তারা কনফিগার করা সারির ক্ষমতার চেয়ে বড় না হয় (সারি ধারণক্ষমতার চেয়ে বড় লেখা অবিলম্বে ব্যর্থ হয়)। যেহেতু প্রতিটি পাঠকের আলাদা পড়ার অবস্থান থাকতে পারে, প্রতিটি পাঠকের প্রতিটি ডেটা পড়ার জন্য অপেক্ষা করার পরিবর্তে, যখনই নতুন লেখার জন্য স্থানের প্রয়োজন হয় তখন ডেটা সারিতে পড়ে যাওয়ার অনুমতি দেওয়া হয়।
সারির শেষ থেকে পড়ে যাওয়ার আগে ডেটা পুনরুদ্ধার করার জন্য পাঠকদের দায়বদ্ধ। একটি রিড যা উপলব্ধ থেকে বেশি ডেটা পড়ার চেষ্টা করে তা হয় অবিলম্বে ব্যর্থ হয় (যদি অবরোধ না করা হয়) বা পর্যাপ্ত ডেটা উপলব্ধ হওয়ার জন্য অপেক্ষা করে (যদি ব্লক করা হয়)। একটি পঠন যা সারির ক্ষমতার চেয়ে বেশি ডেটা পড়ার চেষ্টা করে তা অবিলম্বে ব্যর্থ হয়।
যদি একজন পাঠক লেখকের সাথে তাল মিলিয়ে চলতে ব্যর্থ হয়, যাতে সেই পাঠক দ্বারা লেখা এবং এখনও পড়া হয়নি এমন ডেটার পরিমাণ সারির ক্ষমতার চেয়ে বড় হয়, পরবর্তী পঠিত ডেটা ফেরত দেয় না; পরিবর্তে, এটি পাঠকের পঠিত অবস্থানকে সর্বশেষ লেখার অবস্থানের সমান করতে পুনরায় সেট করে তারপর ব্যর্থতা ফিরিয়ে দেয়। যদি পড়ার জন্য উপলব্ধ ডেটা ওভারফ্লো হওয়ার পরে চেক করা হয় তবে পরবর্তী পড়ার আগে, এটি সারির ক্ষমতার চেয়ে পড়ার জন্য উপলব্ধ আরও ডেটা দেখায়, ওভারফ্লো হয়েছে তা নির্দেশ করে। (যদি উপলভ্য ডেটা চেক করা এবং সেই ডেটা পড়ার চেষ্টা করার মধ্যে সারিটি ওভারফ্লো হয়, তবে ওভারফ্লো হওয়ার একমাত্র ইঙ্গিত হল পঠন ব্যর্থ হয়।)
একটি আনসিঙ্ক্রোনাইজড সারির পাঠকরা সম্ভবত সারির পঠন এবং লেখার পয়েন্টারগুলি পুনরায় সেট করতে চান না। সুতরাং, বর্ণনাকারী পাঠকদের থেকে সারি তৈরি করার সময় `resetPointers` প্যারামিটারের জন্য একটি `false` যুক্তি ব্যবহার করা উচিত।
সিঙ্ক্রোনাইজড
একটি সিঙ্ক্রোনাইজড সারিতে একজন লেখক এবং একজন পাঠক একটি একক লেখার অবস্থান এবং একটি একক পঠিত অবস্থান রয়েছে৷ সারিতে যে স্থান রয়েছে তার চেয়ে বেশি ডেটা লেখা বা সারিতে বর্তমানে যে ডেটা রয়েছে তার চেয়ে বেশি পড়া অসম্ভব৷ ব্লকিং বা ননব্লকিং রাইট বা রিড ফাংশন বলা হয় কিনা তার উপর নির্ভর করে, উপলব্ধ স্থান বা ডেটা অতিক্রম করার প্রচেষ্টা হয় অবিলম্বে ব্যর্থতা ফিরিয়ে দেয় বা পছন্দসই অপারেশন সম্পূর্ণ না হওয়া পর্যন্ত ব্লক করে। সারির ক্ষমতার চেয়ে বেশি ডেটা পড়ার বা লেখার প্রচেষ্টা সবসময় অবিলম্বে ব্যর্থ হয়।
একটি FMQ সেট আপ করুন
একটি বার্তা সারি একাধিক MessageQueue
অবজেক্টের প্রয়োজন: একটিতে লিখতে হবে এবং এক বা একাধিক থেকে পড়তে হবে। লেখা বা পড়ার জন্য কোন বস্তু ব্যবহার করা হয় তার কোন সুস্পষ্ট কনফিগারেশন নেই; এটি ব্যবহারকারীর উপর নির্ভর করে যে কোনও বস্তু পড়া এবং লেখার জন্য ব্যবহার করা হয় না, সর্বাধিক একজন লেখক আছে এবং, সিঙ্ক্রোনাইজড সারিগুলির জন্য, সর্বাধিক একজন পাঠক আছে।
প্রথম MessageQueue অবজেক্ট তৈরি করুন
একটি একক কলের সাথে একটি বার্তা সারি তৈরি এবং কনফিগার করা হয়েছে:
#include <fmq/MessageQueue.h> using android::hardware::kSynchronizedReadWrite; using android::hardware::kUnsynchronizedWrite; using android::hardware::MQDescriptorSync; using android::hardware::MQDescriptorUnsync; using android::hardware::MessageQueue; .... // For a synchronized non-blocking FMQ mFmqSynchronized = new (std::nothrow) MessageQueue<uint16_t, kSynchronizedReadWrite> (kNumElementsInQueue); // For an unsynchronized FMQ that supports blocking mFmqUnsynchronizedBlocking = new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite> (kNumElementsInQueue, true /* enable blocking operations */);
-
MessageQueue<T, flavor>(numElements)
ইনিশিয়ালাইজার একটি বস্তু তৈরি করে এবং শুরু করে যা বার্তা সারি কার্যকারিতা সমর্থন করে। -
MessageQueue<T, flavor>(numElements, configureEventFlagWord)
ইনিশিয়ালাইজার একটি অবজেক্ট তৈরি করে এবং শুরু করে যা ব্লক করার সাথে বার্তা সারি কার্যকারিতা সমর্থন করে। -
flavor
হয় একটি সিঙ্ক্রোনাইজড সারির জন্যkSynchronizedReadWrite
অথবা একটি unsynchronized সারির জন্যkUnsynchronizedWrite
হতে পারে। -
uint16_t
(এই উদাহরণে) যেকোন HIDL-সংজ্ঞায়িত প্রকার হতে পারে যাতে নেস্টেড বাফার (কোনওstring
বাvec
প্রকার), হ্যান্ডেল বা ইন্টারফেস জড়িত নয়। -
kNumElementsInQueue
এন্ট্রির সংখ্যায় সারির আকার নির্দেশ করে; এটি ভাগ করা মেমরি বাফারের আকার নির্ধারণ করে যা সারির জন্য বরাদ্দ করা হয়।
দ্বিতীয় MessageQueue অবজেক্ট তৈরি করুন
বার্তা সারির দ্বিতীয় দিকটি প্রথম দিক থেকে প্রাপ্ত একটি MQDescriptor
অবজেক্ট ব্যবহার করে তৈরি করা হয়েছে। MQDescriptor
অবজেক্ট একটি HIDL বা AIDL RPC কলের মাধ্যমে পাঠানো হয় সেই প্রক্রিয়ায় যা বার্তা সারির দ্বিতীয় প্রান্তে থাকে। MQDescriptor
সারি সম্পর্কে তথ্য রয়েছে, যার মধ্যে রয়েছে:
- বাফার ম্যাপ এবং পয়েন্টার লিখতে তথ্য.
- পঠিত পয়েন্টার ম্যাপ করার জন্য তথ্য (যদি সারিটি সিঙ্ক্রোনাইজ করা হয়)।
- ইভেন্ট পতাকা শব্দ ম্যাপ করার তথ্য (যদি সারি ব্লক করা হয়)।
- অবজেক্ট টাইপ (
<T, flavor>
), যার মধ্যে HIDL-সংজ্ঞায়িত ধরনের সারি উপাদান এবং কিউ ফ্লেভার (সিঙ্ক্রোনাইজ বা আনসিঙ্ক্রোনাইজড) অন্তর্ভুক্ত থাকে।
MQDescriptor
অবজেক্টটি একটি MessageQueue
অবজেক্ট তৈরি করতে ব্যবহার করা যেতে পারে:
MessageQueue<T, flavor>::MessageQueue(const MQDescriptor<T, flavor>& Desc, bool resetPointers)
resetPointers
প্যারামিটার নির্দেশ করে যে এই MessageQueue
অবজেক্ট তৈরি করার সময় রিড এবং রাইট পজিশন 0 এ রিসেট করতে হবে কিনা। একটি আনসিঙ্ক্রোনাইজড সারিতে, রিড পজিশন (যা আনসিঙ্ক্রোনাইজড সারিতে প্রতিটি MessageQueue
অবজেক্টের স্থানীয়) তৈরির সময় সর্বদা 0 এ সেট করা থাকে। সাধারণত, প্রথম বার্তা সারি অবজেক্ট তৈরি করার সময় MQDescriptor
শুরু করা হয়। শেয়ার্ড মেমরির উপর অতিরিক্ত নিয়ন্ত্রণের জন্য, আপনি ম্যানুয়ালি MQDescriptor
সেট আপ করতে পারেন ( MQDescriptor
system/libhidl/base/include/hidl/MQDescriptor.h
এ সংজ্ঞায়িত করা হয়েছে) তারপর এই বিভাগে বর্ণিত প্রতিটি MessageQueue
অবজেক্ট তৈরি করুন।
ব্লক সারি এবং ইভেন্ট পতাকা
ডিফল্টরূপে, সারি পড়া/লেখা ব্লক করা সমর্থন করে না। দুই ধরনের ব্লকিং রিড/রাইট কল আছে:
- সংক্ষিপ্ত ফর্ম , তিনটি পরামিতি সহ (ডেটা পয়েন্টার, আইটেমের সংখ্যা, সময় শেষ)। একটি একক সারিতে পৃথক পঠন/লেখার ক্রিয়াকলাপগুলিতে ব্লক করা সমর্থন করে। এই ফর্মটি ব্যবহার করার সময়, সারিটি ইভেন্ট ফ্ল্যাগ এবং বিটমাস্কগুলি অভ্যন্তরীণভাবে পরিচালনা করে এবং প্রথম বার্তা সারি অবজেক্টটি
true
দ্বিতীয় প্যারামিটার দিয়ে শুরু করতে হবে। যেমন:// For an unsynchronized FMQ that supports blocking mFmqUnsynchronizedBlocking = new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite> (kNumElementsInQueue, true /* enable blocking operations */);
- দীর্ঘ ফর্ম , ছয়টি প্যারামিটার সহ (ইভেন্ট পতাকা এবং বিটমাস্ক সহ)। একাধিক সারির মধ্যে একটি শেয়ার্ড
EventFlag
অবজেক্ট ব্যবহার করে সমর্থন করে এবং বিজ্ঞপ্তি বিট মাস্ক ব্যবহার করার অনুমতি দেয়। এই ক্ষেত্রে, ইভেন্ট ফ্ল্যাগ এবং বিটমাস্ক অবশ্যই প্রতিটি রিড এবং রাইট কলে সরবরাহ করতে হবে।
দীর্ঘ ফর্মের জন্য, প্রতিটি readBlocking()
এবং writeBlocking()
কলে EventFlag
স্পষ্টভাবে সরবরাহ করা যেতে পারে। সারিগুলির মধ্যে একটি একটি অভ্যন্তরীণ ইভেন্ট ফ্ল্যাগ দিয়ে শুরু করা যেতে পারে, যা অবশ্যই সেই সারির MessageQueue
অবজেক্টগুলি থেকে getEventFlagWord()
ব্যবহার করে বের করতে হবে এবং অন্যান্য FMQ এর সাথে ব্যবহারের জন্য প্রতিটি প্রক্রিয়াতে EventFlag
অবজেক্ট তৈরি করতে ব্যবহার করা হবে। বিকল্পভাবে, EventFlag
অবজেক্টগুলি যেকোনো উপযুক্ত শেয়ার করা মেমরির সাথে আরম্ভ করা যেতে পারে।
সাধারণভাবে, প্রতিটি সারিতে শুধুমাত্র একটি নন-ব্লকিং, শর্ট-ফর্ম ব্লকিং বা লং-ফর্ম ব্লকিং ব্যবহার করা উচিত। এগুলি মিশ্রিত করা কোনও ত্রুটি নয়, তবে পছন্দসই ফলাফল পেতে যত্নশীল প্রোগ্রামিং প্রয়োজন।
মেমরিটিকে শুধুমাত্র পঠিত হিসাবে চিহ্নিত করুন
ডিফল্টরূপে, শেয়ার করা মেমরিতে পড়ার এবং লেখার অনুমতি রয়েছে। আনসিঙ্ক্রোনাইজড সারিগুলির জন্য ( kUnsynchronizedWrite
), লেখক MQDescriptorUnsync
অবজেক্টগুলি হস্তান্তর করার আগে সমস্ত পাঠকদের জন্য লেখার অনুমতিগুলি সরাতে চাইতে পারেন। এটি নিশ্চিত করে যে অন্যান্য প্রক্রিয়াগুলি সারিতে লিখতে পারে না, যা পাঠক প্রক্রিয়াগুলিতে বাগ বা খারাপ আচরণ থেকে রক্ষা করার জন্য সুপারিশ করা হয়। লেখক যদি চান যে পাঠকরা যখনই সারির পঠিত দিক তৈরি করতে MQDescriptorUnsync
ব্যবহার করে তখনই সারিটি পুনরায় সেট করতে সক্ষম হন, তাহলে মেমরিটি কেবল-পঠন হিসাবে চিহ্নিত করা যাবে না। এটি `MessageQueue` কনস্ট্রাক্টরের ডিফল্ট আচরণ। সুতরাং, যদি এই সারির ইতিমধ্যেই বিদ্যমান ব্যবহারকারীরা থাকে, resetPointer=false
দিয়ে সারি তৈরি করতে তাদের কোড পরিবর্তন করতে হবে।
- লেখক: একটি
MQDescriptor
ফাইল বর্ণনাকারীর সাথেashmem_set_prot_region
কল করুন এবং অঞ্চলটি শুধুমাত্র পঠনযোগ্য (PROT_READ
):int res = ashmem_set_prot_region(mqDesc->handle->data[0], PROT_READ)
- পাঠক:
resetPointer=false
দিয়ে বার্তা সারি তৈরি করুন (ডিফল্টটিtrue
):mFmq = new (std::nothrow) MessageQueue(mqDesc, false);
MessageQueue ব্যবহার করুন
MessageQueue
অবজেক্টের সর্বজনীন API হল:
size_t availableToWrite() // Space available (number of elements). size_t availableToRead() // Number of elements available. size_t getQuantumSize() // Size of type T in bytes. size_t getQuantumCount() // Number of items of type T that fit in the FMQ. bool isValid() // Whether the FMQ is configured correctly. const MQDescriptor<T, flavor>* getDesc() // Return info to send to other process. bool write(const T* data) // Write one T to FMQ; true if successful. bool write(const T* data, size_t count) // Write count T's; no partial writes. bool read(T* data); // read one T from FMQ; true if successful. bool read(T* data, size_t count); // Read count T's; no partial reads. bool writeBlocking(const T* data, size_t count, int64_t timeOutNanos = 0); bool readBlocking(T* data, size_t count, int64_t timeOutNanos = 0); // Allows multiple queues to share a single event flag word std::atomic<uint32_t>* getEventFlagWord(); bool writeBlocking(const T* data, size_t count, uint32_t readNotification, uint32_t writeNotification, int64_t timeOutNanos = 0, android::hardware::EventFlag* evFlag = nullptr); // Blocking write operation for count Ts. bool readBlocking(T* data, size_t count, uint32_t readNotification, uint32_t writeNotification, int64_t timeOutNanos = 0, android::hardware::EventFlag* evFlag = nullptr) // Blocking read operation for count Ts; //APIs to allow zero copy read/write operations bool beginWrite(size_t nMessages, MemTransaction* memTx) const; bool commitWrite(size_t nMessages); bool beginRead(size_t nMessages, MemTransaction* memTx) const; bool commitRead(size_t nMessages);
availableToWrite()
এবং availableToRead()
একক অপারেশনে কতটা ডেটা স্থানান্তর করা যেতে পারে তা নির্ধারণ করতে ব্যবহার করা যেতে পারে। একটি অসিঙ্ক্রোনাইজড সারিতে:
-
availableToWrite()
সর্বদা সারির ক্ষমতা প্রদান করে। - প্রতিটি পাঠকের নিজস্ব পড়ার অবস্থান রয়েছে এবং
availableToRead()
এর জন্য নিজস্ব গণনা করে। - ধীর পাঠকের দৃষ্টিকোণ থেকে, সারিটি উপচে পড়ার অনুমতি দেওয়া হয়; এর ফলে
availableToRead()
সারির আকারের চেয়ে বড় একটি মান ফেরত দিতে পারে। একটি ওভারফ্লো ব্যর্থ হওয়ার পরে প্রথম পঠিত হয় এবং সেই পাঠকের জন্য রিড পজিশন বর্তমান রাইট পয়েন্টারের সমান সেট করা হয়, ওভারফ্লোটিavailableToRead()
এর মাধ্যমে রিপোর্ট করা হয়েছিল কিনা।
read()
এবং write()
পদ্ধতিগুলি true
হয় যদি অনুরোধ করা সমস্ত ডেটা সারিতে/থেকে স্থানান্তরিত হতে পারে (এবং ছিল)। এই পদ্ধতিগুলি ব্লক করে না; তারা হয় সফল (এবং true
ফিরে), অথবা ব্যর্থতা ( false
) অবিলম্বে ফিরে.
readBlocking()
এবং writeBlocking()
পদ্ধতি অনুরোধ করা অপারেশন সম্পূর্ণ না হওয়া পর্যন্ত অপেক্ষা করে, অথবা তাদের সময় শেষ না হওয়া পর্যন্ত (0 এর একটি timeOutNanos
মান মানে কখনই সময় শেষ হয় না)।
ব্লকিং অপারেশন একটি ইভেন্ট পতাকা শব্দ ব্যবহার করে প্রয়োগ করা হয়। ডিফল্টরূপে, প্রতিটি সারি readBlocking()
এবং writeBlocking()
এর সংক্ষিপ্ত রূপকে সমর্থন করার জন্য নিজস্ব পতাকা শব্দ তৈরি করে এবং ব্যবহার করে। একাধিক সারির জন্য একটি একক শব্দ ভাগ করা সম্ভব, যাতে একটি প্রক্রিয়া সারিতে লেখা বা পড়ার জন্য অপেক্ষা করতে পারে। একটি সারির ইভেন্ট ফ্ল্যাগ শব্দের একটি পয়েন্টার getEventFlagWord()
কল করে প্রাপ্ত করা যেতে পারে, এবং সেই পয়েন্টারটি (অথবা একটি উপযুক্ত শেয়ার করা মেমরি অবস্থানের যে কোনো পয়েন্টার) একটি EventFlag
অবজেক্ট তৈরি করতে ব্যবহার করা যেতে পারে যাতে readBlocking()
এর দীর্ঘ আকারে পাস করা যায় এবং writeBlocking()
একটি ভিন্ন সারির জন্য। readNotification
এবং writeNotification
প্যারামিটারগুলি বলে যে ইভেন্ট ফ্ল্যাগের কোন বিটগুলি সেই সারিতে পড়া এবং লেখার সংকেত দিতে ব্যবহার করা উচিত৷ readNotification
এবং writeNotification
হল 32-বিট বিটমাস্ক।
readBlocking()
writeNotification
বিটের উপর অপেক্ষা করে; যদি সেই প্যারামিটারটি 0 হয়, কলটি সর্বদা ব্যর্থ হয়। যদি readNotification
মান 0 হয়, তবে কলটি ব্যর্থ হবে না, কিন্তু একটি সফল পঠন কোনো বিজ্ঞপ্তি বিট সেট করবে না। একটি সিঙ্ক্রোনাইজড সারিতে, এর অর্থ হবে যে সংশ্লিষ্ট writeBlocking()
কলটি কখনই জেগে ওঠে না যদি না বিটটি অন্য কোথাও সেট করা হয়। একটি আনসিঙ্ক্রোনাইজড সারিতে, writeBlocking()
অপেক্ষা করে না (এটি এখনও রাইট নোটিফিকেশন বিট সেট করার জন্য ব্যবহার করা উচিত), এবং এটি পড়ার জন্য উপযুক্ত কোনো বিজ্ঞপ্তি বিট সেট না করা। একইভাবে, readNotification
0 হলে writeblocking()
ব্যর্থ হয়, এবং একটি সফল লেখা নির্দিষ্ট writeNotification
বিট সেট করে।
একবারে একাধিক সারিতে অপেক্ষা করতে, একটি EventFlag
অবজেক্টের wait()
পদ্ধতি ব্যবহার করে বিজ্ঞপ্তির বিটমাস্কে অপেক্ষা করুন। wait()
পদ্ধতিটি সেই বিটগুলির সাথে একটি স্ট্যাটাস শব্দ প্রদান করে যা জেগে ওঠা সেটের কারণ হয়। তারপরে এই তথ্যটি সংশ্লিষ্ট সারিতে পছন্দসই লেখা/পড়া অপারেশনের জন্য পর্যাপ্ত স্থান বা ডেটা আছে তা যাচাই করতে এবং একটি ননব্লকিং write()
/ read()
সম্পাদন করতে ব্যবহৃত হয়। একটি পোস্ট অপারেশন বিজ্ঞপ্তি পেতে, EventFlag
এর wake()
পদ্ধতিতে আরেকটি কল ব্যবহার করুন। EventFlag
বিমূর্ততার সংজ্ঞার জন্য, system/libfmq/include/fmq/EventFlag.h
দেখুন।
জিরো কপি অপারেশন
read
/ write
/ readBlocking
/ writeBlocking()
এপিআই একটি ইনপুট/আউটপুট বাফারে একটি আর্গুমেন্ট হিসাবে একটি পয়েন্টার নেয় এবং একই এবং FMQ রিং বাফারের মধ্যে ডেটা কপি করতে অভ্যন্তরীণভাবে memcpy()
কল ব্যবহার করে। কর্মক্ষমতা উন্নত করতে, অ্যান্ড্রয়েড 8.0 এবং উচ্চতর এপিআইগুলির একটি সেট অন্তর্ভুক্ত করে যা রিং বাফারে সরাসরি পয়েন্টার অ্যাক্সেস প্রদান করে, memcpy
কল ব্যবহার করার প্রয়োজনীয়তা দূর করে।
শূন্য কপি FMQ অপারেশনের জন্য নিম্নলিখিত পাবলিক API ব্যবহার করুন:
bool beginWrite(size_t nMessages, MemTransaction* memTx) const; bool commitWrite(size_t nMessages); bool beginRead(size_t nMessages, MemTransaction* memTx) const; bool commitRead(size_t nMessages);
-
beginWrite
পদ্ধতি FMQ রিং বাফারে বেস পয়েন্টার প্রদান করে। ডেটা লেখার পরে, এটিcommitWrite()
ব্যবহার করে কমিট করুন।beginRead
/commitRead
পদ্ধতি একইভাবে কাজ করে। -
beginRead
/Write
পদ্ধতিগুলি পঠিত/লিখিত বার্তাগুলির সংখ্যা ইনপুট হিসাবে গ্রহণ করে এবং পঠন/লেখা সম্ভব কিনা তা নির্দেশ করে একটি বুলিয়ান ফেরত দেয়। যদি পড়া বা লেখা সম্ভব হয় তাহলেmemTx
স্ট্রাকট বেস পয়েন্টার দিয়ে তৈরি করা হয় যা রিং বাফার শেয়ার্ড মেমরিতে সরাসরি পয়েন্টার অ্যাক্সেসের জন্য ব্যবহার করা যেতে পারে। -
MemRegion
স্ট্রাকটে মেমরির একটি ব্লকের বিশদ বিবরণ রয়েছে, যার মধ্যে রয়েছে বেস পয়েন্টার (মেমরি ব্লকের বেস অ্যাড্রেস) এবংT
এর পরিপ্রেক্ষিতে দৈর্ঘ্য (বার্তা সারির HIDL-সংজ্ঞায়িত প্রকারের পরিপ্রেক্ষিতে মেমরি ব্লকের দৈর্ঘ্য)। -
MemTransaction
struct-এ দুটিMemRegion
স্ট্রাকট রয়েছে,first
এবংsecond
রিং বাফারে পড়া বা লেখার জন্য সারির শুরুতে মোড়ানোর প্রয়োজন হতে পারে। এর অর্থ হল FMQ রিং বাফারে ডেটা পড়তে/লিখতে দুটি বেস পয়েন্টার প্রয়োজন।
একটি MemRegion
struct থেকে বেস ঠিকানা এবং দৈর্ঘ্য পেতে:
T* getAddress(); // gets the base address size_t getLength(); // gets the length of the memory region in terms of T size_t getLengthInBytes(); // gets the length of the memory region in bytes
একটি MemTransaction
অবজেক্টের মধ্যে প্রথম এবং দ্বিতীয় MemRegion
এর রেফারেন্স পেতে:
const MemRegion& getFirstRegion(); // get a reference to the first MemRegion const MemRegion& getSecondRegion(); // get a reference to the second MemRegion
শূন্য অনুলিপি API ব্যবহার করে FMQ-তে উদাহরণ লিখুন:
MessageQueueSync::MemTransaction tx; if (mQueue->beginRead(dataLen, &tx)) { auto first = tx.getFirstRegion(); auto second = tx.getSecondRegion(); foo(first.getAddress(), first.getLength()); // method that performs the data write foo(second.getAddress(), second.getLength()); // method that performs the data write if(commitWrite(dataLen) == false) { // report error } } else { // report error }
নিম্নলিখিত সহায়ক পদ্ধতিগুলিও MemTransaction
এর অংশ:
-
T* getSlot(size_t idx);
এইMemTransaction
অবজেক্টের অংশMemRegions
মধ্যে স্লটidx
এ একটি পয়েন্টার ফেরত দেয়। যদিMemTransaction
অবজেক্টটি T টাইপের N আইটেম পড়তে/লিখতে মেমরি অঞ্চলের প্রতিনিধিত্ব করে, তাহলেidx
এর বৈধ পরিসীমা 0 এবং N-1-এর মধ্যে। -
bool copyTo(const T* data, size_t startIdx, size_t nMessages = 1);
সূচীstartIdx
থেকে শুরু করে অবজেক্ট দ্বারা বর্ণিত মেমরি অঞ্চলে T টাইপেরnMessages
আইটেমগুলি লিখুন। এই পদ্ধতিটিmemcpy()
ব্যবহার করে এবং শূন্য অনুলিপি অপারেশনের জন্য ব্যবহার করা বোঝায় না। যদিMemTransaction
অবজেক্টটি T টাইপের N আইটেম পড়তে/লিখতে মেমরির প্রতিনিধিত্ব করে, তাহলেidx
এর বৈধ পরিসীমা 0 এবং N-1-এর মধ্যে। -
bool copyFrom(T* data, size_t startIdx, size_t nMessages = 1);
startIdx
থেকে শুরু করে অবজেক্ট দ্বারা বর্ণিত মেমরি অঞ্চল থেকে T টাইপেরnMessages
আইটেমগুলি পড়ার সহায়ক পদ্ধতি। এই পদ্ধতিটিmemcpy()
ব্যবহার করে এবং এটি শূন্য কপি অপারেশনের জন্য ব্যবহার করা হয় না।
HIDL এর উপর সারি পাঠান
সৃষ্টির দিকে:
- উপরে বর্ণিত হিসাবে বার্তা সারি অবজেক্ট তৈরি করুন।
-
isValid()
দিয়ে বস্তুটি বৈধ কিনা তা যাচাই করুন। - আপনি যদি
readBlocking()
/writeBlocking()
এর দীর্ঘ আকারে একটিEventFlag
পাস করে একাধিক সারিতে অপেক্ষা করছেন, তাহলে আপনি একটিMessageQueue
অবজেক্ট থেকে ইভেন্ট ফ্ল্যাগ পয়েন্টার (getEventFlagWord()
ব্যবহার করে ) বের করতে পারেন যা পতাকা তৈরি করতে শুরু করা হয়েছিল, এবং প্রয়োজনীয়EventFlag
অবজেক্ট তৈরি করতে সেই পতাকাটি ব্যবহার করুন। - একটি বর্ণনাকারী বস্তু পেতে
MessageQueue
getDesc()
পদ্ধতি ব্যবহার করুন। -
.hal
ফাইলে, পদ্ধতিটিকেfmq_sync
টাইপের একটি প্যারামিটার দিনঅথবা fmq_unsync
যেখানে T
একটি উপযুক্ত HIDL-সংজ্ঞায়িত প্রকার।getDesc()
দ্বারা প্রত্যাবর্তিত বস্তুটি গ্রহণ প্রক্রিয়ায় পাঠাতে এটি ব্যবহার করুন।
প্রাপ্তির দিকে:
- একটি
MessageQueue
অবজেক্ট তৈরি করতে বর্ণনাকারী অবজেক্ট ব্যবহার করুন। একই সারি স্বাদ এবং ডেটা টাইপ ব্যবহার করতে ভুলবেন না, অথবা টেমপ্লেট কম্পাইল করতে ব্যর্থ হয়। - আপনি যদি একটি ইভেন্ট পতাকা বের করে থাকেন, তাহলে রিসিভিং প্রক্রিয়ায় সংশ্লিষ্ট
MessageQueue
অবজেক্ট থেকে পতাকাটি বের করুন। - ডেটা স্থানান্তর করতে
MessageQueue
অবজেক্ট ব্যবহার করুন।