तेज़ी से मैसेज की सूची (FMQ)

अगर आपको एआईडीएल से जुड़ी सहायता चाहिए, तो यह भी देखें AIDL के साथ FMQ.

HIDL का रिमोट प्रोसेस कॉल (RPC) इन्फ़्रास्ट्रक्चर, बाइंडर मैकेनिज़्म का इस्तेमाल करता है. इसका मतलब है कि कॉल में ओवरहेड शामिल है, उसके लिए कर्नेल ऑपरेशन की ज़रूरत होती है, और ये ट्रिगर हो सकते हैं शेड्यूलर कार्रवाई. हालांकि, ऐसे मामलों में जहां डेटा के बीच डेटा ट्रांसफ़र किया जाना चाहिए कम ओवरहेड वाली और कर्नेल भागीदारी के बिना प्रोसेस, फ़ास्ट मैसेज क्यू (FMQ) सिस्टम का इस्तेमाल किया गया.

FMQ, पसंदीदा प्रॉपर्टी के साथ मैसेज की सूची बनाता है. अगर आप MQDescriptorSync या MQDescriptorUnsync ऑब्जेक्ट यह हो सकता है HIDL RPC कॉल पर भेजा गया और इसका इस्तेमाल रिसीव करने की प्रोसेस में संदेश सूची.

तेज़ मैसेज की सूची सिर्फ़ C++ और डिवाइसों पर काम करती है Android 8.0 और इसके बाद वाला वर्शन होना चाहिए.

Message चेतावनी के टाइप

Android पर दो तरह की क़ीमतें काम करती हैं (जिसे फ़्लेवर कहा जाता है):

  • सिंक नहीं की गई सूचियों को ओवरफ़्लो होने की अनुमति होती है. साथ ही, इसमें कई सूचियां हो सकती हैं पाठक; हर पाठक को समय पर डेटा पढ़ना होगा या उसे खोना होगा.
  • सिंक की गई सूचियों को ओवरफ़्लो नहीं किया जा सकता है, और सिर्फ़ इन्हें ओवरफ़्लो हो सकता है एक रीडर.

दोनों तरह की सूचियों को अंडरफ़्लो (किसी खाली सूची की मदद से पढ़ने के लिए) की अनुमति नहीं है विफल होता है) और उसका केवल एक लेखक हो सकता है.

सिंक में नहीं है

सिंक नहीं की गई सूची में सिर्फ़ एक राइटर होता है, लेकिन उसकी संख्या एक भी हो सकती है पाठक. सूची में लिखने के लिए एक पोज़िशन है; हालांकि, हर पाठक पहले से ही ट्रैक करने में मदद मिलती है.

सूची में शामिल सभी टेक्स्ट हमेशा तब तक काम करते हैं (ओवरफ़्लो के लिए इसकी जांच नहीं की जाती) जब तक कि वे कॉन्फ़िगर की गई क्यू की क्षमता से ज़्यादा नहीं हैं (लिखकर क्यू की क्षमता तुरंत बंद हो जाती है). हर व्यक्ति के लिए पढ़ने का तरीका अलग हो सकता है हर व्यक्ति के लिए डेटा के हर हिस्से को पढ़ने का इंतज़ार नहीं करती. जब भी नए लेखों को लिखने के लिए जगह की ज़रूरत हो, तो उन्हें सूची से बाहर किया जा सकता है.

पाठक, डेटा के आखिर तक पहुंचने से पहले उसे वापस पाने की ज़िम्मेदारी लेते हैं सूची में है. ऐसा रीड जो उपलब्ध डेटा से ज़्यादा डेटा पढ़ने की कोशिश करता है तुरंत काम नहीं कर पाता (अगर ब्लॉक नहीं किया जाता) या ज़रूरत के मुताबिक डेटा उपलब्ध होने का इंतज़ार करता है (अगर ब्लॉक करना). ऐसा रीड जो हमेशा सूची में क्षमता से ज़्यादा डेटा पढ़ने की कोशिश करता है विफल हो जाता है.

अगर कोई पाठक लेखक से संपर्क नहीं कर पाता है, तो जितना उस पाठक ने लिखा है और अभी तक नहीं पढ़ा है, तो वह सूची की क्षमता से ज़्यादा है. अगली बार पढ़ने पर डेटा नहीं मिलता; इसके बजाय, यह रीडर के पढ़े गए टेक्स्ट को रीसेट कर देता है पोज़िशन को हाल ही में लिखे गए पेज की पोज़िशन के बराबर सेट करता है, तो नतीजे के तौर पर फ़ेल हो जाता है. अगर पढ़ने के लिए उपलब्ध डेटा की जांच ओवरफ़्लो के बाद की जाती है, लेकिन अगली बार पढ़ने से पहले, इसकी जांच की जाती है पढ़ने के लिए उपलब्ध डेटा, सूची में मौजूद क्षमता से ज़्यादा दिखाता है. इससे पता चलता है कि ओवरफ़्लो हुआ. (अगर उपलब्ध डेटा की जांच करने के दौरान सूची ज़्यादा हो जाती है और उस डेटा को पढ़ने का प्रयास करते समय, ओवरफ़्लो का एकमात्र संकेत यह होता है कि पढ़ना विफल रहा.)

सिंक नहीं की गई सूची में मौजूद पाठक, शायद रीसेट न करना चाहें सूची के 'पढ़ें और लिखें' पॉइंटर. इसलिए, डिस्क्रिप्टर रीडर को `resetPointers` के लिए `गलत` आर्ग्युमेंट का इस्तेमाल करना चाहिए पैरामीटर.

सिंक किया गया

सिंक की गई सूची में एक राइटर और एक रीडर है. इसमें एक ही लिखा है स्थिति और एक रीड पोज़िशन. इससे ज़्यादा डेटा लिखना संभव नहीं है सूची में मौजूदा डेटा से ज़्यादा डेटा पढ़ने या इसके लिए जगह है. यह इस बात पर निर्भर करता है कि टेक्स्ट को ब्लॉक करने या ब्लॉक करने वाला फ़ंक्शन, राइट या रीड फ़ंक्शन है या नहीं कॉल किया गया, तो उपलब्ध जगह को पार करने की कोशिश की जाती है या डेटा वापस मिलने में विफल हो जाता है तुरंत या ब्लॉक करें, जब तक कि मनचाहा ऑपरेशन पूरा न हो जाए. ये कोशिशें की गई हैं क्यू में क्षमता से ज़्यादा डेटा पढ़ने या लिखने में हमेशा समस्या आती है.

एफ़एमक्यू सेट अप करें

मैसेज सूची में कई MessageQueue ऑब्जेक्ट होने चाहिए: एक को लिखा हो और पढ़ने के लिए एक या ज़्यादा. इसमें कोई अश्लील कॉन्टेंट नहीं है ऐसा कॉन्फ़िगरेशन जिससे लिखने या पढ़ने के लिए इस्तेमाल किया जाता हो; यह तय करना होता है कि उपयोगकर्ता को यह पक्का करने के लिए कहा जाएगा कि पढ़ने और लिखने, दोनों के लिए किसी भी ऑब्जेक्ट का इस्तेमाल न किया जाए, ज़्यादा से ज़्यादा एक लेखक और सिंक की गई सूची के लिए, रीडर.

पहला MessageQ ऑब्जेक्ट बनाएं

मैसेज सूची को एक ही कॉल से बनाया और कॉन्फ़िगर किया जाता है:

#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 सिंक नहीं की गई सूची या kUnsynchronizedWrite सूची.
  • uint16_t (इस उदाहरण में) कोई भी HIDL से तय किया गया टाइप जो इसमें नेस्ट किए गए बफ़र शामिल नहीं होते हैं (string या vec नहीं होते हैं) टाइप), हैंडल या इंटरफ़ेस में दिख सकते हैं.
  • kNumElementsInQueue, संख्या में सूची का साइज़ दिखाता है एंट्री; यह, शेयर किए गए उस मेमोरी बफ़र का साइज़ तय करता है जिसे बांटा गया है आपका पसंदीदा विकल्प है.

दूसरा Message चेतावनी ऑब्जेक्ट बनाएं

संदेश सूची के दूसरे हिस्से को पहली तरफ़ से 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 ऑब्जेक्ट का इस्तेमाल किया जा सकता है और सूचना बिट मास्क को इस्तेमाल करने की अनुमति देता है. इस मामले में, 'रीड ऐंड राइट' कॉल के लिए, इवेंट फ़्लैग और बिटमास्क दिए जाने चाहिए.

लंबी अवधि के वीडियो के लिए, EventFlag की वैल्यू हर readBlocking() और writeBlocking() कॉल के लिए. इनमें से एक सूचियों को किसी इंटरनल इवेंट फ़्लैग के साथ शुरू किया जा सकता है. इसके लिए, यह ज़रूरी है कि इसका इस्तेमाल करके उस सूची के MessageQueue ऑब्जेक्ट से एक्सट्रैक्ट किया गया getEventFlagWord() और इसका इस्तेमाल, EventFlag बनाने में किया गया हर प्रोसेस में मौजूद एक ऑब्जेक्ट की जानकारी देती हैं जिसका इस्तेमाल दूसरे एफ़एमक्यू के साथ किया जा सकता है. इसके अलावा, EventFlag ऑब्जेक्ट को किसी भी सही शेयर के साथ शुरू किया जा सकता है मेमोरी.

आम तौर पर, हर सूची में, ब्लॉक न करने वाले और कम अवधि के सिर्फ़ एक फ़ॉर्मैट का इस्तेमाल किया जाना चाहिए या लंबी अवधि के वीडियो ब्लॉक करना. उन्हें मिक्स करना कोई गड़बड़ी नहीं है, लेकिन सावधान रहें मनचाहा नतीजा पाने के लिए प्रोग्रामिंग ज़रूरी है.

इस 'यादें' को 'सिर्फ़ पढ़ने के लिए' के तौर पर मार्क करें

शेयर की गई 'यादें' में, कॉन्टेंट पढ़ने और उसमें बदलाव करने की अनुमतियां डिफ़ॉल्ट रूप से मौजूद होती हैं. सिंक में नहीं है के लिए सूची (kUnsynchronizedWrite), तो हो सकता है कि लेखक सभी के लिए, लिखने की अनुमतियां हटाना चाहे MQDescriptorUnsync ऑब्जेक्ट को सौंपे जाने से पहले पाठकों की संख्या में कितनी कमी आती है. इससे पक्का होता है कि एक सूची में अलग-अलग प्रोसेस नहीं लिख सकतीं. ऐसा इसलिए, क्योंकि हमारा सुझाव है कि बग या ऐप्लिकेशन की खराब परफ़ॉर्मेंस से बचा जा सके पाठक की प्रोसेस को कैसे पूरा करता है. अगर लेखक चाहता है कि पाठक सूची को रीसेट करने के लिए, सूची का रीड साइड बनाने के लिए MQDescriptorUnsync. इसके बाद, मेमोरी को मार्क नहीं किया जा सकेगा सिर्फ़ पढ़ने के लिए है. यह `Message चेतावनी` कंस्ट्रक्टर का डिफ़ॉल्ट व्यवहार है. इसलिए, अगर पहले से इस सूची के मौजूदा उपयोगकर्ता हैं, तो क्यू के साथ सूची बनाने के लिए उनका कोड बदलना होगा 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);

Messageक्यू का इस्तेमाल करना

MessageQueue ऑब्जेक्ट का सार्वजनिक एपीआई यह है:

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() तरीके इंतज़ार कर रहे हैं जब तक कि अनुरोध की गई कार्रवाई पूरी नहीं की जा सकती या जब तक कि वे टाइम आउट नहीं हो जाते (a timeOutNanos की वैल्यू 0 होने का मतलब है कि कभी टाइम आउट नहीं होगा).

ब्लॉक करने की कार्रवाइयां, इवेंट फ़्लैग शब्द का इस्तेमाल करके लागू की जाती हैं. डिफ़ॉल्ट रूप से, हर सूची अपने झंडे का शब्द बनाती है और उसका इस्तेमाल करके, readBlocking() और writeBlocking(). यह उनके लिए संभव है किसी एक शब्द को शेयर करने के लिए कई सूची बनाई जा सकती हैं, ताकि लिखने पर इंतज़ार किया जा सके या सूची में मौजूद विकल्पों में से किसी को भी पढ़ सकता है. सूची में इवेंट फ़्लैग शब्द के लिए पॉइंटर getEventFlagWord() को कॉल करके मिले और उस पॉइंटर (या किसी भी का इस्तेमाल एक सही शेयर की गई मेमोरी लोकेशन के लिए किया जा सकता है. EventFlag ऑब्जेक्ट को इसके लंबे फ़ॉर्मैट में पास करना है readBlocking() और writeBlocking()किसी अन्य सूची. readNotification और writeNotification पैरामीटर से यह पता चलता है कि रीड सिग्नल के लिए इवेंट फ़्लैग में किन बिट का इस्तेमाल किया जाना चाहिए और उस सूची पर लिखता है. readNotification और writeNotification 32-बिट बिटमास्क हैं.

readBlocking(), writeNotification बिट तक इंतज़ार करता है; अगर वह पैरामीटर 0 है, तो कॉल हमेशा फ़ेल हो जाता है. अगर readNotification का मान 0 है, कॉल फ़ेल नहीं होगा, लेकिन सही तरीके से पढ़ने की सुविधा से, सूचना के बारे में कोई बिट सेट नहीं होगी. सिंक की गई सूची में, इसका मतलब यह होगा कि संबंधित writeBlocking() कॉल स्क्रीन तब तक नहीं खुलती है, जब तक कि इस बिट को कहीं और सेट न किया गया हो. सिंक नहीं की गई सूची में, writeBlocking() इंतज़ार नहीं करता (इसे सेट करने के लिए अब भी इसका इस्तेमाल किया जाना चाहिए सूचना बिट लिखें) और रीड के लिए कोई सेट न करें सूचना बिट. इसी तरह, writeblocking() काम नहीं करता अगर readNotification 0 है और सही तरीके से लिखने पर, writeNotification बिट.

एक बार में कई सूची पर इंतज़ार करने के लिए, EventFlag ऑब्जेक्ट का इस्तेमाल करें सूचनाओं के बिटमास्क पर इंतज़ार करने के लिए wait() तरीका. कॉन्टेंट बनाने wait() तरीका, उन बिट के साथ स्टेटस शब्द दिखाता है जिनकी वजह से जागना सेट. इसके बाद इस जानकारी का इस्तेमाल यह पुष्टि करने के लिए किया जाता है कि संबंधित सूची में मनमुताबिक लेखन/पढ़ें कार्रवाई के लिए काफ़ी जगह या डेटा होना चाहिए और ब्लॉक नहीं करने वाला write()/read(). पोस्ट से जुड़ी कार्रवाई करवाने के लिए नोटिफ़िकेशन, EventFlag की wake() तरीका. EventFlag की परिभाषा के लिए अमूर्त, system/libfmq/include/fmq/EventFlag.h.

शून्य कॉपी ऑपरेशन

कॉन्टेंट बनाने read/write/readBlocking/writeBlocking() एपीआई, इनपुट/आउटपुट बफ़र में पॉइंटर को आर्ग्युमेंट के तौर पर ले जाते हैं और memcpy(), उपयोगकर्ताओं को एक ही एफ़एमक्यू रिंग बफ़र. परफ़ॉर्मेंस को बेहतर बनाने के लिए, Android 8.0 और उसके बाद के वर्शन में ऐसे एपीआई जो रिंग बफ़र में पॉइंटर का सीधा ऐक्सेस देते हैं. इन एपीआई की मदद से, memcpy कॉल करने की ज़रूरत है.

एफ़एमक्यू से जुड़ी शून्य कॉपी वाली कार्रवाइयों के लिए, नीचे दिए गए सार्वजनिक एपीआई का इस्तेमाल करें:

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 तरीका, एफ़एमक्यू रिंग में बेस पॉइंटर देता है बफ़र. डेटा लिखे जाने के बाद, commitWrite() का इस्तेमाल करके उसे सेव करें. beginRead/commitRead तरीके इसी तरह से काम करते हैं.
  • इनपुट के तौर पर beginRead/Write तरीके पढ़े/लिखे जाने वाले संदेशों की संख्या और एक बूलियन प्राप्त होता है जो यह बताता है कि पढ़ना/लिखना संभव है. अगर पढ़ा या लिखा जा सकता है, तो memTx स्ट्रक्चर, बेस पॉइंटर से अपने-आप भर जाता है, जिसका इस्तेमाल डायरेक्ट पॉइंटर के लिए किया जा सकता है रिंग बफ़र की शेयर की गई मेमोरी का ऐक्सेस.
  • MemRegion स्ट्रक्चर में मेमोरी के ब्लॉक के बारे में जानकारी होती है, इसमें बेस पॉइंटर (मेमोरी ब्लॉक का बेस पता) और इसकी लंबाई शामिल है T के पद (HIDL-तय के हिसाब से मेमोरी ब्लॉक की लंबाई संदेश सूची का प्रकार).
  • MemTransaction स्ट्रक्चर में दो MemRegion हैं स्ट्रक्ट, first और second रीड या राइट के रूप में रिंग बफ़र को सूची की शुरुआत तक रैप करना पड़ सकता है. यह इसका मतलब यह होगा कि FMQ में डेटा पढ़ने/लिखने के लिए दो बेस पॉइंटर की ज़रूरत होगी रिंग बफ़र.

MemRegion स्ट्रक्चर से बेस का पता और उसकी लंबाई का पता लगाने के लिए:

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

इसमें पहले और दूसरे MemRegion के रेफ़रंस पाने के लिए MemTransaction ऑब्जेक्ट:

const MemRegion& getFirstRegion(); // get a reference to the first MemRegion
const MemRegion& getSecondRegion(); // get a reference to the second MemRegion

शून्य कॉपी एपीआई का इस्तेमाल करके एफ़एमक्यू पर लिखने का उदाहरण:

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);
    इसके अंदर स्लॉट idx पर पॉइंटर लौटाता है MemRegions जो इस MemTransaction का हिस्सा हैं ऑब्जेक्ट है. अगर MemTransaction ऑब्जेक्ट, मेमोरी को दिखा रहा है T प्रकार के N आइटम पढ़ने/लिखने के लिए क्षेत्र, फिर इसकी मान्य श्रेणी idx, 0 और N-1 के बीच है.
  • bool copyTo(const T* data, size_t startIdx, size_t nMessages = 1);
    मेमोरी की जगहों में T टाइप के nMessages आइटम लिखें startIdx इंडेक्स से शुरू करते हुए, ऑब्जेक्ट के ज़रिए बताया गया. यह तरीका memcpy() का इस्तेमाल करता है. हालांकि, इसे शून्य कॉपी के लिए इस्तेमाल नहीं किया जाना चाहिए कार्रवाई. अगर MemTransaction ऑब्जेक्ट, T प्रकार के N आइटम पढ़ें/लिखें, फिर idx की मान्य श्रेणी यह होगी वैल्यू 0 और N-1 के बीच होनी चाहिए.
  • bool copyFrom(T* data, size_t startIdx, size_t nMessages = 1);
    T प्रकार के nMessages आइटम पढ़ने के लिए सहायक विधि ऑब्जेक्ट के हिसाब से, startIdx से शुरू होने वाले मेमोरी के क्षेत्र. यह यह तरीका memcpy() का इस्तेमाल करता है. इसे शून्य कॉपी के लिए इस्तेमाल नहीं किया जाना चाहिए कार्रवाई.

HIDL पर सूची भेजें

कॉन्टेंट बनाने का तरीका:

  1. ऊपर बताए गए तरीके से, मैसेज सूची के लिए ऑब्जेक्ट बनाएं.
  2. पुष्टि करें कि ऑब्जेक्ट isValid() के साथ मान्य है.
  3. यदि आप EventFlag की लंबी अवधि readBlocking()/writeBlocking() है, तो आप इवेंट फ़्लैग पॉइंटर (getEventFlagWord() का इस्तेमाल करके) MessageQueue ऑब्जेक्ट जिसे फ़्लैग बनाने के लिए शुरू किया गया था और ज़रूरी EventFlag ऑब्जेक्ट बनाने के लिए, उस फ़्लैग का इस्तेमाल करें.
  4. पाने के लिए MessageQueue getDesc() तरीके का इस्तेमाल करें डिस्क्रिप्टर ऑब्जेक्ट.
  5. .hal फ़ाइल में, तरीके को fmq_sync या fmq_unsync जहां T, सही HIDL-परिभाषित प्रकार होना चाहिए. इसका इस्तेमाल करके ऑब्जेक्ट को वापस भेजें पाने की प्रोसेस में getDesc().

दाईं ओर:

  1. MessageQueue ऑब्जेक्ट बनाने के लिए, डिस्क्रिप्टर ऑब्जेक्ट का इस्तेमाल करें. होना एक ही क्यू फ़्लेवर और डेटा टाइप का इस्तेमाल करें. ऐसा न करने पर टेंप्लेट कंपाइल करें.
  2. अगर आपने कोई इवेंट फ़्लैग निकाला है, तो उससे जुड़े इवेंट फ़्लैग से फ़्लैग निकालें MessageQueue ऑब्जेक्ट, पाने की प्रोसेस में है.
  3. डेटा ट्रांसफ़र करने के लिए, MessageQueue ऑब्जेक्ट का इस्तेमाल करें.