Erlang 21 - 9. Drivers

9 ड्राइवर




erlang

9 ड्राइवर

यह अनुभाग कुशल ड्राइवरों को लिखने के तरीके पर एक संक्षिप्त अवलोकन प्रदान करता है।

यह माना जाता है कि आपको ड्राइवरों की अच्छी समझ है।

9.1 ड्राइवर्स और कंजेंसी

रनटाइम सिस्टम हमेशा ड्राइवर में किसी भी कोड को चलाने से पहले एक लॉक लेता है।

डिफ़ॉल्ट रूप से, यह लॉक ड्राइवर स्तर पर है, अर्थात, यदि कई पोर्ट एक ही ड्राइवर के लिए खोले गए हैं, तो केवल उसी समय एक पोर्ट के लिए कोड चल सकता है।

इसके बजाय प्रत्येक पोर्ट के लिए एक लॉक करने के लिए ड्राइवर को कॉन्फ़िगर किया जा सकता है।

यदि ड्राइवर का उपयोग एक कार्यात्मक तरीके से किया जाता है (जो कि कोई राज्य नहीं रखता है, लेकिन केवल कुछ भारी गणना करता है और परिणाम देता है), पंजीकृत नामों वाले कई पोर्ट पहले से खोले जा सकते हैं और उपयोग किए जाने वाले पोर्ट को इसके आधार पर चुना जा सकता है अनुसूचक आईडी इस प्रकार है:

-define(PORT_NAMES(),
	{some_driver_01, some_driver_02, some_driver_03, some_driver_04,
	 some_driver_05, some_driver_06, some_driver_07, some_driver_08,
	 some_driver_09, some_driver_10, some_driver_11, some_driver_12,
	 some_driver_13, some_driver_14, some_driver_15, some_driver_16}).

client_port() ->
    element(erlang:system_info(scheduler_id) rem tuple_size(?PORT_NAMES()) + 1,
	    ?PORT_NAMES()).

जब तक 16 से अधिक शेड्यूल नहीं होते हैं, तब तक ड्राइवर के लिए पोर्ट लॉक पर कोई लॉक विवाद नहीं होगा।

9.2 चालक को बुलाते समय बायनेरिज़ की नकल करने से बचना

एक ड्राइवर को भेजे जाने वाले द्विआधारी की नकल से बचने के लिए मूल रूप से दो तरीके हैं:

  • यदि port_control/3 लिए Data तर्क एक बाइनरी है, तो ड्राइवर को बाइनरी की सामग्री के लिए एक पॉइंटर पारित किया जाएगा और बाइनरी कॉपी नहीं किया जाएगा। यदि Data तर्क एक आईओलिस्ट (बायनेरिज़ और सूचियों की सूची) है, तो आईओलिस्ट के सभी बायनेरिज़ की नकल की जाएगी।

    इसलिए, यदि आप बाइनरी को कॉपी किए बिना ड्राइवर को पहले से मौजूद बाइनरी और कुछ अतिरिक्त डेटा दोनों भेजना चाहते हैं, तो आपको दो बार port_control/3 कॉल करना होगा; एक बार बाइनरी के साथ और एक बार अतिरिक्त डेटा के साथ। हालाँकि, यह केवल तभी काम करेगा जब पोर्ट के साथ संचार करने की केवल एक प्रक्रिया हो (क्योंकि अन्यथा एक अन्य प्रक्रिया ड्राइवर को कॉल के बीच में कॉल कर सकती है)।

  • ड्राइवर में एक output कॉलबैक ( output कॉलबैक के बजाय) लागू करें। यदि ड्राइवर के पास outputv कॉलबैक है, तो port_command/2 लिए Data तर्क में एक आईओलिस्ट में पारित रिफाइनरी बायनेरिज़ को ड्राइवर के संदर्भ के रूप में पारित किया जाएगा।

9.3 एक ड्राइवर से छोटे बायनेरिज़ लौटना

रनटाइम सिस्टम 64 बाइट्स तक के बायनेरिज़ को हीप बायनेरीज़ के रूप में प्रदर्शित कर सकता है। संदेशों में भेजे जाने पर उन्हें हमेशा कॉपी किया जाता है, लेकिन उन्हें कम मेमोरी की आवश्यकता होती है यदि उन्हें किसी अन्य प्रक्रिया में नहीं भेजा जाता है और कचरा संग्रह सस्ता होता है।

यदि आप जानते हैं कि आपके द्वारा लौटाए गए बायनेरिज़ हमेशा छोटे होते हैं, तो आपको ड्राइवर API कॉल का उपयोग करने की सलाह दी जाती है, जिनके लिए पूर्व-आवंटित बाइनरी की आवश्यकता नहीं होती है, उदाहरण के लिए, driver_output() या erl_drv_output_term() , ERL_DRV_BUF2BINARY प्रारूप का उपयोग करके, रनटाइम की अनुमति देने के लिए। एक ढेर बाइनरी का निर्माण करने के लिए।

9.4 एक चालक से नकल किए बिना बड़े बायनेरिज़ लौटना

बड़े बाइनरी भेजे जाने या ड्राइवर से एर्लांग प्रक्रिया में लौटने पर डेटा की प्रतिलिपि बनाने से बचने के लिए, ड्राइवर को पहले बाइनरी को आवंटित करना होगा और फिर किसी तरह एर्लांग प्रक्रिया में भेजना होगा।

बाइनरी को आवंटित करने के लिए driver_alloc_binary() का उपयोग करें।

driver_alloc_binary() के साथ बनाए गए बाइनरी भेजने के कई तरीके हैं:

  • control कॉलबैक से, एक बाइनरी लौटाया जा सकता है यदि set_port_control_flags() को ध्वज मान PORT_CONTROL_FLAG_BINARY साथ कहा जाता है।
  • एक एकल बाइनरी को driver_output_binary() साथ भेजा जा सकता है।
  • erl_drv_output_term() या erl_drv_send_term() का उपयोग करके, एक बाइनरी को एक erl_drv_send_term() शब्द में शामिल किया जा सकता है।