
नमस्ते यह आलेख थ्रेड्स के बीच संदेश भेजने के लिए FreeRTOS के लिए हैंडलर पैटर्न के एक संभावित कार्यान्वयन का वर्णन करता है। लेख मुख्य रूप से माइक्रोकंट्रोलर, DIY उत्साही और RTOS और माइक्रोकंट्रोलर का अध्ययन करने वाले लोगों के लिए परियोजनाओं में ऑपरेटिंग सिस्टम का उपयोग करने वाले लोगों के लिए है।
यह माना जाता है कि पाठक आरटीओएस से संबंधित मूल शब्दों से परिचित है, जैसे कि कतार और प्रवाह। आप FreeRTOS के बारे में अधिक सीख सकते हैं
qdx पदों में
FreeRTOS: परिचय और
FreeRTOS: इंटरप्रोसेस संचार ।
जिन लोगों ने FreeRTOS का उपयोग करके माइक्रोकंट्रोलर्स के लिए परियोजनाओं में भाग लिया, वे इस तथ्य से परिचित हो सकते हैं कि मानक एपीआई बल्कि खराब है, जिससे अतिरिक्त कोड लिखने की आवश्यकता होती है, जो काफी हद तक दोहराई जाती है। मेरे मामले में, प्रवाह के बीच बातचीत के लिए उपकरणों की कमी थी, अर्थात् एकीकृत संदेश प्रणाली की कमी। आमतौर पर, कतार के एक या दूसरे रूप का उपयोग थ्रेड्स और सिंक्रनाइज़ेशन के बीच सूचनाओं के आदान-प्रदान के लिए किया जाता है। इसके अलावा, कतार में निहित जानकारी का प्रकार हर बार अलग होता है, जो कोड के पुन: उपयोग की संभावना को कम करता है।
एक एकीकृत संदेश फ़ॉर्म का उपयोग करने से आप कई थ्रेड्स को एक वर्कर थ्रेड में संयोजित कर सकते हैं, जो एक कतार में संदेशों को प्राप्त करता है।
विचार एंड्रॉइड में हैंडलर वर्ग का उपयोग करने के समान है, इसलिए नाम (वर्ग फ़ील्ड और संरचनाओं के नाम सहित) बेशर्मी से वहां से उधार लिए गए हैं।
दृष्टिकोण कई प्रकार के संदेशों को संसाधित करने के लिए एक एकल थ्रेड के उपयोग पर आधारित है, जो कतार से संदेशों को निकालता है, संबंधित हैंडलर को कॉल करता है, और अगले संदेश पर आगे बढ़ता है।
थ्रेड कतार पर अवरुद्ध है, इसलिए यदि कोई संदेश नहीं है, तो नियंत्रण अन्य थ्रेड्स में स्थानांतरित किया जाता है। जैसे ही एक नया संदेश पंक्तिबद्ध होता है, थ्रेड अनलॉक हो जाता है और संदेश संसाधित होता है। संदेशों को हैंडलर, अन्य थ्रेड्स, अन्य हैंडलर या स्वयं के द्वारा पंक्तिबद्ध किया जा सकता है।
किसी भी धागे की तरह, वर्कर थ्रेड (या लूपर) को उच्च प्राथमिकता के साथ दूसरे धागे से बदला जा सकता है। विभिन्न प्राथमिकताओं के साथ कई लूपर्स का उपयोग करना सबसे महत्वपूर्ण संदेशों के समय पर प्रसंस्करण की अनुमति देता है। आदर्श रूप से, प्रत्येक हैंडलर के लिए एक अनूठी प्राथमिकता वाला एक धागा (दुर्भाग्य से, हमेशा एक समझौता होगा)।
यह सब क्यों जरूरी है?
सबसे पहले, यह दृष्टिकोण लचीलापन प्रदान करता है। यह आपको जटिल इनकैप्सुलेटेड ऑब्जेक्ट बनाने की अनुमति देता है जो कई घटनाओं का जवाब देता है। हालिया अभ्यास का एक उदाहरण आरएफआईडी रीडर क्लास है, जिसे शुरू में केवल कमांड लाइन के साथ काम करने के लिए माना जाता था। परिणामस्वरूप, हैंडलर एक राज्य मशीन में बदल गया, और कमांड लाइन से संदेशों में फ़ोल्डर, टाइमर, मोशन सेंसर और बैटरी स्तर की निगरानी के संदेश जोड़े गए।
चार्ट

कार्यान्वयन का उदाहरण
एक साधारण C ++ प्रोग्राम के उदाहरण पर उपरोक्त पर विचार करें। मैं थ्रेड क्लास का विवरण नहीं दूंगा, यह उल्लेख करने के लिए पर्याप्त है कि थ्रेड के वंशज रन () विधि को ओवरराइड करना चाहिए, जो थ्रेड का शरीर है।
प्रत्येक संदेश एक संरचना है:
struct MESSAGE { Handler *handler; char what; char arg1; char arg2; void *ptr; };
लूप स्ट्रीम कार्यान्वयन उदाहरण:
Looper::Looper(uint8_t messageQueueSize, const char *name, unsigned short stackDepth, char priority): Thread(name, stackDepth, priority) { messageQueue = xQueueCreate(messageQueueSize, sizeof(Message)); } void Looper::run() { Message msg; for (;;) { if (xQueueReceive(messageQueue, &msg, portMAX_DELAY)) {
सार हैंडलर के कार्यान्वयन का एक उदाहरण (सभी विधियाँ नहीं):
Handler::Handler(Looper *looper) { messageQueue = looper->getMessageQueue(); } bool Handler::sendMessage(char what, char arg1, char arg2, void *ptr) { Message msg; msg.handler = this; msg.what = what; msg.arg1 = arg1; msg.arg2 = arg2; msg.ptr = ptr; return xQueueSend(messageQueue, &msg, 0); }
हैंडलर कार्यान्वयन उदाहरण:
आपको एक आभासी विधि को ओवरराइड करने की आवश्यकता है, जिसे लूपर कॉल करेगा।
void ExampleHandler::handleMessage(Message msg) { #ifdef DEBUG
मुख्य का एक उदाहरण कार्यान्वयन:
मुख्य का उपयोग थ्रेड्स, हैंडलर और अन्य इनिशियलाइज़ेशन बनाने के लिए किया जाता है।
int main( void ) {
नमूना स्रोतोंनिष्कर्ष
इस दृष्टिकोण का उपयोग करने के कई फायदे हैं:
- आप पुन: उपयोग के लिए कई घटक लिख सकते हैं, जैसे कि कमांड लाइन दुभाषिया या बटन के लिए एक इंटरप्ट हैंडलर जो पंजीकृत वॉर्नर को संदेश भेजेगा
- संदेश कोड के साथ प्रत्येक हैंडलर को एक अलग फाइल में वर्णित किया गया है
- एक मौजूदा हैंडलर का विस्तार करना या एक नया जोड़ना एक नया धागा बनाने की तुलना में आसान है
- चूंकि संदेशों को एक ही थ्रेड पर निष्पादित किया जाता है, इसलिए रेसिंग की कोई संभावना नहीं है
- एकल थ्रेड का उपयोग प्रति स्टैक प्रति मेमोरी लागत को काफी कम करता है
- विकास प्रक्रिया के दौरान, हैंडलर को आसानी से एक राज्य मशीन से बदला जा सकता है, जिसमें कई हैंडलर (प्रत्येक राज्य के लिए) होते हैं
- यदि एक प्रकार के संदेश को संदर्भ स्विच की अनुपस्थिति के कारण अलग थ्रेड में संसाधित किया गया था, तो एक थ्रेड में कई संदेशों को संसाधित करने में लगने वाला समय कम है
संदेश संचालकों (हैंडलर) की कुछ सीमाएँ हैं:
- हैंडलर को स्ट्रीम को ब्लॉक नहीं करना चाहिए (यदि ब्लॉक होता है, तो पूरी संदेश कतार प्रतीक्षा करेगी, और स्ट्रीम निष्क्रिय हो जाएगी)
- संदेश प्रसंस्करण में बहुत अधिक समय नहीं लगना चाहिए
- इस तथ्य के कारण घटना के लिए प्रतिक्रिया समय की भविष्यवाणी करना अधिक कठिन है कि संदेश प्रसंस्करण बारी-बारी से होता है, बजाय छद्म-साथ-साथ (समय के अनुसार स्लाइस)
बेशक, सभी धागे प्रस्तावित मॉडल का उपयोग नहीं कर सकते हैं। यदि आपको कठिन वास्तविक समय प्रदान करने की आवश्यकता है, तो आप एक ही धागे (एक संभव है) पर कई हैंडलर नहीं कर पाएंगे। हालांकि, अभ्यास से पता चलता है कि अन्य सभी प्रवाह काफी सरल हैं और व्यावहारिक रूप से अन्य प्रवाह के साथ बातचीत की आवश्यकता नहीं है। ये या तो धाराएँ हैं जो कुछ पढ़ती हैं (एक धारावाहिक बंदरगाह या यूएसबी से) और जिम्मेदार प्रोसेसर को संदेश भेजते हैं, या धाराएं जो समय लेने वाले संचालन (प्रदर्शन) करती हैं। फर्मवेयर के मुख्य तर्क को हैंडलर की मदद से सफलतापूर्वक वर्णित किया जा सकता है।
आपका ध्यान देने के लिए धन्यवाद।