2011-09-13 20 views
29

मैं लिनक्स के लिए यूनिक्स डोमेन सॉकेट सर्वर लिख रहा हूं।कैसे पता चलेगा कि कोई प्रक्रिया यूनिक्स डोमेन सॉकेट से जुड़ी है या नहीं?

यूनिक्स डोमेन सॉकेट की एक विशिष्टता मुझे जल्दी से पता चला कि, एक सुनवाई यूनिक्स सॉकेट बनाने के दौरान मेल खाने वाली फाइल सिस्टम प्रविष्टि बनाता है, सॉकेट बंद करना इसे हटा नहीं देता है। इसके अलावा, जब तक फाइल सिस्टम प्रविष्टि मैन्युअल रूप से हटा दी जाती है, तब तक bind() एक ही पथ पर एक सॉकेट को फिर से संभव नहीं है: bind()EADDRINUSE के साथ विफल रहता है यदि यह पथ फ़ाइल सिस्टम में पहले से मौजूद है।

परिणामस्वरूप, सर्वर पुनरारंभ पर EADDRINUSE प्राप्त करने से बचने के लिए सॉकेट की फाइल सिस्टम प्रविष्टि unlink() 'सर्वर शटडाउन पर एड होना आवश्यक है। हालांकि, यह हमेशा नहीं किया जा सकता है (यानी सर्वर सर्वर दुर्घटना)। अधिकतर अक्सर पूछे जाने वाले प्रश्न, फोरम पोस्ट, क्यू & bind() पर कॉल करने से पहले unlink() सॉकेट के लिए एक कार्यवाही के रूप में, मुझे केवल एक वेबसाइट के रूप में सलाह दी गई है। हालांकि, इस मामले में, यह जानना वांछनीय हो जाता है कि unlink() से पहले यह प्रक्रिया इस सॉकेट से जुड़ी है या नहीं।

दरअसल, unlink() 'एक यूनिक्स सॉकेट में है, जबकि एक प्रक्रिया अभी भी बाध्य है और फिर सुनवाई सॉकेट को फिर से बनाना कोई त्रुटि नहीं उठाता है। नतीजतन, हालांकि, पुरानी सर्वर प्रक्रिया अभी भी चल रही है लेकिन पहुंच योग्य नहीं है: पुराने सुनवाई सॉकेट को नए द्वारा "मुखौटा" किया जाता है। इस व्यवहार से बचा जाना चाहिए।

आदर्श रूप में, यूनिक्स डोमेन सॉकेट का उपयोग कर, सॉकेट एपीआई एक ही "पारस्परिक अपवर्जन" व्यवहार है कि सामने आ रहा है जब बंधन TCP या UDP सॉकेट अवगत कराया जाना चाहिए था: "मैं सॉकेट एस बाध्य करने के लिए एक समाधान करने के लिए चाहते हैं, अगर एक प्रक्रिया है पहले से ही इस पते से जुड़ा हुआ है, बस शिकायत करें! "दुर्भाग्यवश यह मामला नहीं है ...

क्या इस" आपसी बहिष्करण "व्यवहार को लागू करने का कोई तरीका है? या, एक फाइल सिस्टम पथ दिया गया है, सॉकेट एपीआई के माध्यम से जानने का कोई तरीका है, क्या सिस्टम पर किसी भी प्रक्रिया में यूनिक्स डोमेन सॉकेट इस पथ से बंधी है? क्या मुझे सॉकेट एपीआई (flock(), ...) के बाहर आदिम सिंक्रनाइज़ेशन का उपयोग करना चाहिए? या क्या मैं कुछ न कुछ भूल रहा हूं ?

आपके सुझावों के लिए धन्यवाद।

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

उत्तर

18

मुझे पता है कि मैं पार्टी के लिए बहुत देर हो चुकी हूं और यह बहुत समय पहले उत्तर दिया गया था, लेकिन मुझे बस कुछ और खोज करने का सामना करना पड़ा और मेरे पास एक वैकल्पिक प्रस्ताव है।

जब आप EADDRINUSEbind() से वापस आते हैं तो आप सॉकेट से कनेक्ट होने वाली एक नियमित जांच जांच दर्ज कर सकते हैं। यदि कनेक्शन सफल होता है, तो एक चलती प्रक्रिया है जो कम से कम जीवित है accept() करने के लिए पर्याप्त है। यह मुझे प्राप्त करने के लिए सबसे सरल और सबसे पोर्टेबल तरीका होने के रूप में हमला करता है। इसमें कमी है कि जिस सर्वर ने यूडीएस को पहली जगह बनाया है वह वास्तव में अभी भी चल रहा है लेकिन किसी भी तरह "अटक गया" और accept() करने में असमर्थ है, इसलिए यह समाधान निश्चित रूप से मूर्ख-प्रमाण नहीं है, लेकिन यह एक कदम है सही दिशा मुझे लगता है।

यदि connect() विफल रहता है तो आगे बढ़ें और unlink() एंडपॉइंट पर जाएं और bind() फिर से प्रयास करें।

9

मुझे नहीं लगता कि उन चीजों से परे बहुत कुछ किया जाना है जिन्हें आपने पहले ही माना है। ऐसा लगता है कि आपने इसे अच्छी तरह से खोजा है।

यह निर्धारित करने के तरीके हैं कि सॉकेट यूनिक्स सॉकेट (स्पष्ट रूप से lsof और netstat इसे करने के लिए बाध्य है) लेकिन वे जटिल हैं और सिस्टम पर्याप्त निर्भर है कि मैं सवाल करता हूं कि वे आपके द्वारा उठाए गए समस्याओं से निपटने के प्रयास के लायक हैं या नहीं ।

आप वास्तव में दो समस्याओं को उठा रहे हैं - अन्य अनुप्रयोगों के साथ नाम टकराव से निपटने और अपने स्वयं के ऐप के पिछले उदाहरणों से निपटने।

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

टकराव बनाने वाले अन्य कार्यक्रमों को नियंत्रित करने के लिए आप AFAIK को इतना कुछ नहीं कर सकते हैं। फ़ाइल अनुमतियां सही नहीं हैं, लेकिन यदि विकल्प आपके लिए उपलब्ध है, तो आप अपने ऐप को अपने उपयोगकर्ता/समूह में डाल सकते हैं। यदि कोई मौजूदा सॉकेट पथ है और आपके पास इसका स्वामित्व नहीं है तो इसे अनलिंक न करें और एक त्रुटि संदेश डालें और उपयोगकर्ता या sysadmin को इसे सॉर्ट करने दें। इसे आसानी से बदलने योग्य बनाने के लिए कॉन्फ़िगरेशन फ़ाइल का उपयोग करना - और ग्राहकों के लिए उपलब्ध - काम कर सकता है। इसके अलावा आपको लगभग किसी प्रकार की खोज सेवा जाना है, जो कि बड़े पैमाने पर ओवरकिल की तरह लगता है जब तक कि यह वास्तव में एक महत्वपूर्ण अनुप्रयोग नहीं है।

पूरी तरह से आप कुछ आराम ले सकते हैं कि यह वास्तव में अक्सर नहीं होता है।

+0

आपके उत्तर के लिए धन्यवाद। पारंपरिक लॉकफाइल सिस्टम का उपयोग करना स्वीकार्य रूप से जाने का सबसे सुरक्षित तरीका है। साथ ही, एक सेवा खोज प्रणाली अधिक है या नहीं: विडंबना यह है कि, इस सर्वर को स्वयं सेवा सेवा प्रणाली का हिस्सा बनने की योजना है (सेवा "पंजीकरण" प्रणाली अधिक उचित लगती है)। यह आपके प्रश्न का उत्तर देना चाहिए ;-) –