หากต้องการการสนับสนุนเกี่ยวกับ AIDL โปรดดูข้อมูลเพิ่มเติมที่นี่ FMQ พร้อม AIDL
โครงสร้างพื้นฐานของการเรียกใช้โพรซีเยอร์ระยะไกล (RPC) ของ HIDL ใช้กลไกของ Binder ซึ่งหมายถึงการเรียกใช้มีค่าใช้จ่าย ต้องมีการดำเนินการเคอร์เนล และอาจทริกเกอร์ การทำงานของเครื่องจัดตารางเวลา อย่างไรก็ตาม ในกรณีที่ต้องโอนข้อมูลระหว่าง กระบวนการที่มีโอเวอร์เฮดน้อยกว่าและไม่เกี่ยวข้องกับเคอร์เนล คิวข้อความแบบรวดเร็ว ใช้ระบบ (FMQ)
FMQ สร้างคิวข้อความด้วยคุณสมบัติที่ต้องการ CANNOT TRANSLATE
MQDescriptorSync
หรือ MQDescriptorUnsync
ออบเจ็กต์ก็ได้
ที่ส่งผ่านการเรียกใช้ HIDL RPC และใช้โดยกระบวนการรับเพื่อเข้าถึง
คิวข้อความ
คิวข้อความด่วนรองรับเฉพาะใน C++ และในอุปกรณ์ ที่ใช้ Android 8.0 ขึ้นไป
ประเภท MessageQueue
Android รองรับคิว 2 ประเภท (เรียกว่ารสชาติ) ดังนี้
- คิวที่ไม่ซิงค์จะมีจำนวนต่อได้ และอาจมีหลายรายการ ผู้อ่าน; ผู้อ่านแต่ละคนต้องอ่านข้อมูลให้ทันเวลาหรือสูญหาย
- ไม่สามารถทำให้คิวข้อมูลตรงกัน เพิ่มได้ และจะมีได้เฉพาะคิว ผู้อ่าน 1 คน
ไม่อนุญาตให้จัดคิวทั้ง 2 ประเภทให้น้อยเกินไป (อ่านจากคิวว่าง ล้มเหลว) และมีผู้เขียนได้เพียงคนเดียว
ไม่ซิงค์แล้ว
คิวที่ไม่ได้ซิงค์จะมีผู้เขียนเพียง 1 คน แต่สามารถมีจำนวนกี่เพลงก็ได้ ผู้อ่าน คิวจะมีตำแหน่งการเขียน 1 ตำแหน่ง แต่ผู้อ่านแต่ละคน ติดตามตำแหน่งการอ่านอิสระ
การเขียนไปยังคิวจะสำเร็จเสมอ (ไม่ต้องทำเครื่องหมายสำหรับส่วนเกิน) ตราบใดที่ ไม่ใหญ่เกินความจุของคิวที่กำหนดค่าไว้ (เขียนที่ใหญ่กว่า ความจุของคิวล้มเหลวทันที) เนื่องจากผู้อ่านแต่ละคนอาจมีการอ่านที่ต่างกัน ของคุณ แทนที่จะต้องรอให้ผู้อ่านทุกคนอ่านข้อมูลทั้งหมด ได้รับอนุญาตให้หลุดออกจากคิวเมื่อใดก็ตามที่การเขียนใหม่จำเป็นต้องใช้ช่องว่าง
ผู้อ่านมีหน้าที่รับผิดชอบในการดึงข้อมูลก่อนที่จะตกเป็นเป้าหมายของ คิว การอ่านที่พยายามอ่านข้อมูลมากกว่าที่มีอยู่ ล้มเหลวทันที (หากไม่บล็อก) หรือรอให้มีข้อมูลมากพอ (หาก การบล็อก) การอ่านที่พยายามอ่านข้อมูลมากกว่าความจุของคิวอยู่เสมอ จะล้มเหลวทันที
ถ้าผู้อ่านตามผู้เขียนไม่ทัน ดังนั้นจำนวนข้อมูล ที่เขียนแล้ว แต่ผู้อ่านรายดังกล่าวยังไม่ได้อ่านมีปริมาณมากกว่า ความจุของคิว การอ่านถัดไปไม่แสดงข้อมูล แต่จะรีเซ็ตการอ่านของผู้อ่าน ตำแหน่งใหม่ให้เท่ากับตำแหน่งการเขียนล่าสุดแสดงว่าล้มเหลว หาก ข้อมูลที่อ่านได้จะถูกทำเครื่องหมายหลังจากรายการเพิ่มเติม แต่ก่อนที่จะอ่านครั้งถัดไป แสดงข้อมูลที่อ่านได้มากกว่าความจุคิว ซึ่งบ่งชี้ว่า เกิดการดำเนินการเพิ่มเติม (หากคิวเกิดการล้นระหว่างการตรวจสอบข้อมูลที่มีอยู่ และพยายามอ่านข้อมูลนั้น สิ่งเดียวที่บ่งชี้ถึงข้อมูลล้นก็คือ อ่านไม่สำเร็จ)
ผู้อ่านคิวที่ไม่ได้ซิงค์มักไม่ต้องการรีเซ็ต การอ่านและเขียนของคิว ดังนั้น เมื่อสร้างคิวจาก ผู้อ่านข้อบ่งชี้ควรใช้อาร์กิวเมนต์ "false" สำหรับ "resetPointers" พารามิเตอร์
ซิงค์แล้ว
คิวที่ซิงค์จะมีผู้เขียน 1 คนและผู้อ่าน 1 คนที่มีการเขียนครั้งเดียว และตำแหน่งการอ่านตำแหน่งเดียว เป็นไปไม่ได้ที่จะเขียนข้อมูลมากกว่า คิวมีพื้นที่สำหรับหรืออ่านข้อมูลมากกว่าที่คิวถูกระงับไว้ ขึ้นอยู่กับว่าฟังก์ชันการเขียนหรืออ่านการบล็อกหรือแบบไม่บล็อก เรียกใช้ มีความพยายามใช้พื้นที่เก็บข้อมูลเกินพื้นที่หรือข้อมูลอาจแสดงผลล้มเหลว ทันทีหรือบล็อกจนกว่าการดำเนินการที่ต้องการจะเสร็จสมบูรณ์ ความพยายามที่จะ อ่านหรือเขียนข้อมูลมากกว่าความจุคิวมักจะล้มเหลวทันที
ตั้งค่า FMQ
คิวข้อความต้องใช้ออบเจ็กต์ MessageQueue
หลายรายการ ดังนี้ 1 ถึง
และอย่างน้อย 1 แห่งให้อ่านได้ ไม่มีเนื้อหาที่ชัดเจน
การกำหนดค่าว่าจะใช้ออบเจ็กต์ใดสำหรับการเขียนหรืออ่าน ก็ขึ้นอยู่กับ
เพื่อให้มั่นใจว่าไม่มีการใช้ออบเจ็กต์ทั้งสำหรับการอ่านและการเขียน
มีผู้เขียนได้สูงสุด 1 คน และสำหรับคิวที่ซิงค์ มีผู้เขียนได้สูงสุด 1 คน
ผู้อ่าน
สร้างออบเจ็กต์ 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
สำหรับ คิวที่ซิงค์หรือkUnsynchronizedWrite
สำหรับรายการที่ไม่ได้ซิงค์ คิวuint16_t
(ในตัวอย่างนี้) สามารถเป็นอะไรก็ได้ ประเภทที่ HIDL กำหนดซึ่ง ไม่เกี่ยวข้องกับบัฟเฟอร์ที่ฝัง (ไม่มีstring
หรือvec
ประเภท) แฮนเดิล หรืออินเทอร์เฟซkNumElementsInQueue
ระบุขนาดของคิวเป็นจำนวน รายการ; กำหนดขนาดบัฟเฟอร์หน่วยความจำที่ใช้ร่วมกันซึ่งจัดสรรไว้ สำหรับคิว
สร้างออบเจ็กต์ MessageQueue รายการที่ 2
ด้านที่ 2 ของคิวข้อความจะสร้างโดยใช้
MQDescriptor
ออบเจ็กต์ที่ได้รับจากด้านแรก
มีการส่งออบเจ็กต์ MQDescriptor
ผ่านการเรียกใช้ HIDL หรือ AIDL RPC ไปยังกระบวนการ
ที่เก็บคิวข้อความปลายที่สองไว้
MQDescriptor
มีข้อมูลเกี่ยวกับคิว ดังนี้
- ข้อมูลสำหรับแมปบัฟเฟอร์และการเขียนตัวชี้
- ข้อมูลสำหรับแมปตัวชี้การอ่าน (หากซิงค์คิว)
- ข้อมูลเพื่อจับคู่คำที่แจ้งสำหรับกิจกรรม (หากคิวบล็อกอยู่)
- ประเภทออบเจ็กต์ (
<T, flavor>
) ซึ่งประกอบด้วย ประเภทที่กำหนดโดย HIDL ของ เอลิเมนต์คิวและเวอร์ชันของคิว (ซิงค์หรือไม่ซิงค์)
ออบเจ็กต์ MQDescriptor
สามารถใช้เพื่อสร้าง
ออบเจ็กต์ MessageQueue
รายการ:
MessageQueue<T, flavor>::MessageQueue(const MQDescriptor<T, flavor>& Desc, bool resetPointers)
พารามิเตอร์ resetPointers
ระบุว่าจะรีเซ็ตการอ่านหรือไม่
และเขียนตำแหน่งเป็น 0 ขณะสร้างออบเจ็กต์ MessageQueue
นี้
ในคิวที่ไม่ได้ซิงค์ ตำแหน่งการอ่าน (ซึ่งเป็นแบบระบุในระบบของแต่ละ
ออบเจ็กต์ MessageQueue
ในคิวที่ไม่ซิงค์) จะตั้งค่าเป็น 0 เสมอ
ระหว่างการสร้าง โดยปกติ MQDescriptor
จะเริ่มต้นในระหว่าง
การสร้างออบเจ็กต์คิวข้อความแรก สำหรับควบคุมพื้นที่ที่แชร์
หน่วยความจํา คุณสามารถตั้งค่า MQDescriptor
ด้วยตนเองได้
(MQDescriptor
กำหนดไว้ใน
system/libhidl/base/include/hidl/MQDescriptor.h
)
จากนั้นให้สร้างออบเจ็กต์ MessageQueue
ทั้งหมดตามที่อธิบายไว้ในส่วนนี้
บล็อกคิวและแฟล็กเหตุการณ์
โดยค่าเริ่มต้น คิวจะไม่รองรับการบล็อกการอ่าน/เขียน มี 2 ชนิด ของการบล็อกการเรียกอ่าน/เขียน:
- รูปแบบสั้นที่มีพารามิเตอร์ 3 ตัว (ตัวชี้ข้อมูล จำนวนรายการ
หมดเวลา) รองรับการบล็อกในการดำเนินการอ่าน/เขียนแต่ละรายการใน
คิว เมื่อใช้แบบฟอร์มนี้ คิวจะจัดการแฟล็กเหตุการณ์และบิตมาสก์
ภายใน และออบเจ็กต์คิวข้อความแรกจะต้อง
เริ่มต้นด้วยพารามิเตอร์ที่สองเป็น
true
ดังตัวอย่างต่อไปนี้// For an unsynchronized FMQ that supports blocking mFmqUnsynchronizedBlocking = new (std::nothrow) MessageQueue<uint16_t, kUnsynchronizedWrite> (kNumElementsInQueue, true /* enable blocking operations */);
- วิดีโอแบบยาว มีพารามิเตอร์ 6 รายการ (รวมถึง Flag เหตุการณ์และบิตมาสก์)
รองรับการใช้ออบเจ็กต์
EventFlag
ที่แชร์ระหว่างหลายคิว และอนุญาตให้ระบุมาสก์บิตการแจ้งเตือนที่จะใช้ได้ ในกรณีนี้ ค่า ต้องระบุแฟล็กเหตุการณ์และบิตมาสก์ให้กับการเรียกใช้การอ่านและเขียนแต่ละครั้ง
สำหรับวิดีโอแบบยาว สามารถระบุ EventFlag
อย่างชัดแจ้งใน
การโทร readBlocking()
และ writeBlocking()
แต่ละครั้ง หนึ่งใน
อาจเริ่มต้นคิวด้วยแฟล็กเหตุการณ์ภายใน ซึ่งต้อง
ดึงข้อมูลจากออบเจ็กต์ MessageQueue
ของคิวโดยใช้
getEventFlagWord()
และใช้เพื่อสร้างEventFlag
ในแต่ละกระบวนการเพื่อใช้กับ FMQ อื่นๆ อีกวิธีหนึ่งคือ
สามารถเริ่มต้น EventFlag
ออบเจ็กต์ด้วยการแชร์ที่เหมาะสมรายการใดก็ได้
ความทรงจำ
โดยทั่วไป แต่ละคิวควรใช้รูปแบบสั้นๆ แบบไม่บล็อกเพียง 1 รายการเท่านั้น การบล็อก หรือการบล็อก ในวิดีโอแบบยาว ไม่ใช่ข้อผิดพลาดที่จะผสมปนเปกัน แต่โปรดระวัง จะต้องเขียนโปรแกรมเพื่อให้ได้ผลลัพธ์ที่ต้องการ
ทำเครื่องหมายความทรงจำว่าอ่านอย่างเดียว
โดยค่าเริ่มต้น หน่วยความจำที่ใช้ร่วมกันจะมีสิทธิ์อ่านและเขียน สำหรับกรณีที่ไม่ซิงค์
คิว (kUnsynchronizedWrite
) ผู้เขียนอาจต้องการนำสิทธิ์การเขียนออก
ของผู้อ่านก่อนที่จะแจกออบเจ็กต์ MQDescriptorUnsync
ซึ่งช่วยให้มั่นใจได้
กระบวนการไม่สามารถเขียนลงในคิวได้ ซึ่งขอแนะนำให้ป้องกันข้อบกพร่องหรือลักษณะการทำงานที่ไม่ถูกต้องใน
ที่ผู้อ่านประมวลผล
หากผู้เขียนต้องการให้ผู้อ่านรีเซ็ตคิวได้ทุกครั้งที่ใช้
MQDescriptorUnsync
เพื่อสร้างด้านการอ่านของคิว จากนั้นจะทำเครื่องหมายความทรงจำไม่ได้
ว่าอ่านอย่างเดียว นี่คือลักษณะการทำงานเริ่มต้นของตัวสร้าง "MessageQueue" ดังนั้น หากมีอยู่แล้ว
ผู้ใช้ที่มีอยู่ของคิวนี้ จะต้องเปลี่ยนแปลงโค้ดของผู้ใช้เพื่อสร้างคิวด้วย
resetPointer=false
- ผู้เขียน: เรียก
ashmem_set_prot_region
ด้วยข้อบ่งชี้ไฟล์MQDescriptor
และภูมิภาคได้รับการตั้งค่าเป็นอ่านอย่างเดียว (PROT_READ
):int res = ashmem_set_prot_region(mqDesc->handle->data[0], PROT_READ)
- Reader: สร้างคิวข้อความด้วย
resetPointer=false
(the ค่าเริ่มต้นคือtrue
):mFmq = new (std::nothrow) MessageQueue(mqDesc, false);
ใช้ MessageQueue
API สาธารณะของออบเจ็กต์ 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()
จะรอ
จนกว่าการดำเนินการที่ร้องขอจะเสร็จสมบูรณ์ หรือจนกว่าจะหมดเวลา (
ค่า 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
ไม่มีการทำสำเนา
write
/read
/readBlocking
/writeBlocking()
API จะนำตัวชี้ไปยังบัฟเฟอร์อินพุต/เอาต์พุตเป็นอาร์กิวเมนต์และใช้
memcpy()
โทรภายในเพื่อคัดลอกข้อมูลระหว่าง
บัฟเฟอร์ริง FMQ เพื่อปรับปรุงประสิทธิภาพ Android 8.0 ขึ้นไปจะมีชุด
API ที่มอบการเข้าถึงตัวชี้โดยตรงในบัฟเฟอร์ริง ทำให้ไม่ต้องใช้ฟังก์ชัน
ต้องใช้การโทร memcpy
ใช้ API สาธารณะต่อไปนี้สำหรับการดำเนินการ FMQ ที่ไม่มีการคัดลอก:
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
มีMemRegion
2 รายการfirst
และsecond
เป็นการอ่านหรือเขียนลงใน บัฟเฟอร์ริงอาจต้องตัดรอบไปยังตอนต้นของคิว ช่วงเวลานี้ หมายความว่าจะต้องใช้ตัวชี้พื้นฐาน 2 ตัวเพื่ออ่าน/เขียนข้อมูลลงใน 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
ตัวอย่างการเขียนไปยัง FMQ โดยใช้ API การคัดลอกเป็นศูนย์
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
เป็นตัวแทนของหน่วยความจำ ภูมิภาคที่จะอ่าน/เขียน N รายการประเภท T ตามด้วยช่วงที่ถูกต้องของidx
มีค่าอยู่ระหว่าง 0 ถึง N-1bool copyTo(const T* data, size_t startIdx, size_t nMessages = 1);
เขียนรายการประเภท TnMessages
รายการลงในภูมิภาคหน่วยความจำ อธิบายโดยออบเจ็กต์ เริ่มต้นจากดัชนีstartIdx
วิธีนี้ ใช้memcpy()
และไม่ได้มีไว้เพื่อใช้สำหรับการทำสำเนา การดำเนินการ หากออบเจ็กต์MemTransaction
แสดงหน่วยความจำต่อ อ่าน/เขียน N รายการประเภท T ช่วงที่ถูกต้องคือidx
ระหว่าง 0 ถึง N-1bool copyFrom(T* data, size_t startIdx, size_t nMessages = 1);
เมธอดตัวช่วยในการอ่านnMessages
รายการในประเภท T จาก ภูมิภาคหน่วยความจำที่อธิบายโดยออบเจ็กต์เริ่มต้นจากstartIdx
ช่วงเวลานี้ เมธอดใช้memcpy()
และไม่ได้มีไว้สำหรับสำเนา 0 รายการ การดำเนินการ
ส่งคิวผ่าน HIDL
จากฝั่งของการสร้าง:
- สร้างออบเจ็กต์คิวข้อความตามที่อธิบายไว้ข้างต้น
- ตรวจสอบว่าออบเจ็กต์ถูกต้องด้วย
isValid()
- หากคุณรอหลายคิวโดยการส่ง
EventFlag
สำหรับวิดีโอแบบยาวreadBlocking()
/writeBlocking()
คุณสามารถดึงข้อมูล ตัวชี้สถานะเหตุการณ์ (โดยใช้getEventFlagWord()
) จากMessageQueue
ออบเจ็กต์ที่เริ่มต้นเพื่อสร้าง Flag และ ให้ใช้ Flag นั้นเพื่อสร้างออบเจ็กต์EventFlag
ที่จำเป็น - ใช้เมธอด
MessageQueue
getDesc()
เพื่อรับ ออบเจ็กต์ข้อบ่งชี้ - ในไฟล์
.hal
ให้กำหนดพารามิเตอร์ประเภทfmq_sync
หรือfmq_unsync
โดยที่T
เป็น ประเภทที่กำหนดโดย HIDL ที่เหมาะสม ใช้ค่านี้เพื่อส่งออบเจ็กต์ที่ส่งคืนโดยgetDesc()
ไปยังขั้นตอนการรับ
ฝั่งผู้รับ:
- ใช้ออบเจ็กต์ข้อบ่งชี้เพื่อสร้างออบเจ็กต์
MessageQueue
เป็น ให้ใช้รูปแบบและประเภทข้อมูลเดียวกันของคิว ไม่เช่นนั้นเทมเพลตไม่สามารถ คอมไพล์ - ถ้าคุณดึงค่าสถานะเหตุการณ์ ให้แยกค่าสถานะจาก
MessageQueue
ออบเจ็กต์ในกระบวนการรับ - ใช้ออบเจ็กต์
MessageQueue
เพื่อโอนข้อมูล