POSIX धागे और संकेत


81

मैं कैसे POSIX धागे और POSIX संकेतों की बातचीत की पेचीदगियों को समझने की कोशिश कर रहा हूं। विशेष रूप से, मुझे इसमें दिलचस्पी है:

  • यह नियंत्रित करने का सबसे अच्छा तरीका क्या है कि किस धागे को संकेत दिया जाता है (यह मानते हुए कि यह पहली जगह पर घातक नहीं है)?
  • एक और धागा (जो वास्तव में व्यस्त हो सकता है) बताने के लिए सबसे अच्छा तरीका क्या है कि संकेत आ गया है? (मैं पहले से ही जानता हूं कि सिग्नल हैंडलर से pthread condition वेरिएबल्स का उपयोग करना एक बुरा विचार है।)
  • मैं उन सूचनाओं को पारित करने के लिए सुरक्षित रूप से कैसे संभाल सकता हूं जो एक संकेत अन्य थ्रेड्स को हुआ है? क्या सिग्नल हैंडलर में ऐसा होना जरूरी है? (मैं सामान्य रूप से अन्य धागों को नहीं मारना चाहता; मुझे एक दूर के उपागम दृष्टिकोण की आवश्यकता है।)

मैं ऐसा क्यों चाहता हूं, इसके संदर्भ में, मैं शोध कर रहा हूं कि थ्रेड्स का समर्थन करने के लिए टीएक्सएक्स पैकेज को कैसे कन्वर्ट किया जाए , या इसे विभाजित करने के लिए और कम से कम कुछ उपयोगी भागों को थ्रेड्स का समर्थन करने के लिए। सिग्नल उन हिस्सों में से एक है जो विशेष रुचि रखते हैं।

जवाबों:


48
  • संकेत को नियंत्रित करने के लिए सबसे अच्छा तरीका कौन सा है?

जैसा कि @ zoli2k ने संकेत दिया, स्पष्ट रूप से एक ही धागा नामांकित करना जो आप चाहते हैं कि सभी संकेतों को संभालने के लिए (या विशिष्ट संकेत जिम्मेदारियों के साथ प्रत्येक धागे का एक सेट), एक अच्छी तकनीक है।

  • एक और धागा (जो वास्तव में व्यस्त हो सकता है) को बताने का सबसे अच्छा तरीका है कि सिग्नल आ गया है? [...]
  • मैं सुरक्षित रूप से उन सूचनाओं को पारित करने से कैसे निपट सकता हूं जो एक संकेत अन्य थ्रेड्स के लिए हुई हैं? क्या सिग्नल हैंडलर में ऐसा होना जरूरी है?

मैं "सर्वश्रेष्ठ" नहीं कहूंगा, लेकिन यहां मेरी सिफारिश है:

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

ऐसा करने का सबसे सरल तरीका यह है कि थ्रेड को संकेतों का उपयोग लूप में स्वीकार किया जाए sigwaitinfoयाsigtimedwait । थ्रेड तब किसी भी तरह से संकेतों को परिवर्तित करता है, शायद एक प्रसारण pthread_cond_t, अन्य I / O के साथ अन्य थ्रेड्स को जागृत करते हुए, एप्लिकेशन-विशिष्ट थ्रेड-सुरक्षित कतार में एक कमांड को जोड़ते हुए, जो भी हो।

वैकल्पिक रूप से, विशेष थ्रेड संकेतों को सिग्नल हैंडलर को वितरित करने की अनुमति दे सकता है, केवल सिग्नल को संभालने के लिए तैयार होने पर डिलीवरी के लिए अनमास्किंग। (हैंडलर के माध्यम से सिग्नल डिलीवरी sigwait, परिवार के माध्यम से सिग्नल स्वीकृति की तुलना में अधिक त्रुटि-प्रवण होती है ।) इस मामले में, रिसीवर का सिग्नल हैंडलर कुछ सरल और एसिंक्स-सिग्नल-सुरक्षित कार्रवाई करता है: sig_atomic_tझंडे, कॉलिंग sigaddset(&signals_i_have_seen_recently, latest_sig), write() एक बाइट सेट करना। एक गैर-अवरुद्ध आत्म-पाइप , आदि के लिए फिर, अपने नकाबपोश मुख्य लूप में वापस, थ्रेड ऊपर के रूप में अन्य थ्रेड्स के लिए सिग्नल की प्राप्ति का संचार करता है।

( अपडेट ठीक ही @caf बताते हैं कि sigwaitदृष्टिकोण बेहतर हैं।)


1
यह एक बहुत अधिक उपयोगी उत्तर है, विशेष रूप से इसका उपयोग गैर-घातक सिग्नल से निपटने के लिए भी किया जा सकता है। धन्यवाद!
डोनाल्ड फैलो

1
यह सबसे आसान है यदि सिग्नल हैंडलिंग थ्रेड सिग्नल हैंडलर को बिल्कुल भी स्थापित नहीं करता है - इसके बजाय, यह लगभग sigwaitinfo()(या sigtimedwait()) पर लूप करता है , और फिर अंतिम पैराग्राफ में वर्णित बाकी एप्लिकेशन पर उन्हें भेज देता है।
कैफे

@ कैफ, वास्तव में ऐसा है। अपडेट किया गया
पिल्रोव

14

POSIX मानक के अनुसार सभी थ्रेड्स सिस्टम पर एक ही PID के साथ दिखाई देने चाहिए और pthread_sigmask()आप प्रत्येक थ्रेड के लिए सिग्नल ब्लॉकिंग मास्क को परिभाषित कर सकते हैं।

चूंकि इसे पीआईडी ​​प्रति केवल एक सिग्नल हैंडलर को परिभाषित करने की अनुमति है, इसलिए मैं एक धागे में सभी संकेतों को संभालना पसंद करता हूं और pthread_cancel()अगर एक चल रहे धागे को रद्द करने की आवश्यकता है, तो भेजें । यह pthread_kill()थ्रेड्स के लिए सफाई कार्यों को परिभाषित करने की अनुमति देता है, क्योंकि यह पसंदीदा तरीका है ।

कुछ पुराने सिस्टम पर, उचित कर्नेल समर्थन की कमी के कारण, चल रहे थ्रेड्स में मूल थ्रेड के PID से भिन्न PID हो सकते हैं। लिनक्स 2.4 पर linuxThreads के साथ सिग्नल हैंडलिंग के लिए FAQ देखें ।


आप जो कहते हैं उसमें "कार्यान्वित" का अर्थ क्या है? इसके अलावा, सिग्नल के जवाब में हमेशा अन्य थ्रेड्स को न्यूक करना सही नहीं होता है (SIGHUP और SIGWINCH को अधिक सूक्ष्मता की आवश्यकता होती है) और फिर भी अन्य थ्रेड्स को बताने के लिए कंडीशन वैरिएबल का उपयोग करना असुरक्षित है। गरीब का जवाब।
डोनल फेलो

1
मेरे डाउन-वोट को हटा दिया, लेकिन यह अभी भी एक पर्याप्त जवाब नहीं है क्योंकि मैं केवल सिग्नल के जवाब में थ्रेड्स नहीं मार सकता। कुछ मामलों में मैं स्थानीय रूप से प्रतिक्रिया में घटनाओं को कतारबद्ध करने जा रहा हूं, दूसरों में मुझे थ्रेड्स को बहुत सावधानी से फाड़ने के लिए मिला है (बीटीडब्लू, मुझे उन हिस्सों को करने के लिए अधिकांश मशीनरी मिल गई है; यह ओएस के कनेक्शन हैं; संकेत जो गायब हैं)।
डोनल फैलो

1
@ zoli2k: मैंने अभी हाल ही में uClibc की make menuconfigताज़ा क्लोन मास्टर शाखा के साथ चलने की कोशिश की है । वहाँ है वर्ष 2012 के अभी भी NPTL चुनने खिलाफ सिफारिश की के रूप में वर्ष LinuxThreads और POSIX धागे कार्यान्वयन के रूप में नए NPTL, लेकिन मदद के बीच एक विकल्प। तो यह आधुनिक एम्बेडेड लिनक्स सिस्टम में अभी भी आम है कि अप्रचलित LinuxThreads कार्यान्वयन को देखने के लिए उपयोग किया जाता है, भले ही सिस्टम हाल ही में पर्याप्त लिनक्स कर्नेल चला रहा हो।
FooF

3

मैं अब तक कहां हूं:

  • सिग्नल विभिन्न प्रमुख वर्गों में आते हैं, जिनमें से कुछ को आम तौर पर वैसे भी (SIGILL) प्रक्रिया को मारना चाहिए और जिनमें से कुछ को कभी भी कुछ भी करने की आवश्यकता नहीं है (SIGIO; वैसे भी async IO करना आसान है)। उन दो वर्गों को कार्रवाई की आवश्यकता नहीं है।
  • कुछ संकेतों को तुरंत निपटाए जाने की आवश्यकता नहीं है; SIGWINCH की पसंद को तब तक कतारबद्ध किया जा सकता है जब तक कि यह सुविधाजनक नहीं है (बस X11 से एक घटना की तरह)।
  • मुश्किल वाले वे हैं जहाँ आप उन पर प्रतिक्रिया देना चाहते हैं जो आप कर रहे हैं, लेकिन एक धागा को मिटाए बिना आप क्या कर रहे हैं। विशेष रूप से, इंटरैक्टिव मोड में SIGINT चीजों को उत्तरदायी छोड़ने के लिए चाहिए।

मैं अभी भी के माध्यम से सॉर्ट करने के लिए मिल गया है signalबनाम sigaction, pselect, sigwait, sigaltstack, और अन्य बिट्स और POSIX (और गैर POSIX) एपीआई के टुकड़े की एक पूरी गुच्छा।


3

आईएमएचओ, यूनिक्स वी सिग्नल और पॉज़िक्स थ्रेड अच्छी तरह से मिश्रण नहीं करते हैं। यूनिक्स वी 1970 है। पोसिक्स 1980 है;)

रद्दीकरण अंक हैं और यदि आप एक आवेदन में संकेतों और pthreads अनुमति देते हैं, तो आप अंततः प्रत्येक कॉल के चारों ओर लूप लिखना समाप्त कर देंगे, जो आश्चर्यजनक रूप से EINTR वापस कर सकते हैं।

तो मैंने (कुछ) मामलों में क्या किया, जहां मुझे लिनक्स या QNX पर मल्टीथ्रेडेड प्रोग्राम करना था, सभी (लेकिन एक) थ्रेड्स के लिए सभी सिग्नलों को मास्क करने के लिए।

जब एक यूनिक्स वी सिग्नल आता है, तो प्रक्रिया स्टैक को स्विच करती है (जो कि यूनिक्स वी में उतना ही निर्णायक था जितना आप एक प्रक्रिया के भीतर प्राप्त कर सकते हैं)।

जैसा कि यहां अन्य पोस्ट संकेत देते हैं, अब यह संभव हो सकता है, सिस्टम को यह बताने के लिए कि कौन सा पॉज़िक्स थ्रेड उस स्टैक स्विचिंग का शिकार होगा।

एक बार, आप अपने सिग्नल हैंडलर थ्रेड को काम में लाने में कामयाब रहे, सवाल यह है कि सिग्नल की जानकारी को कुछ सभ्य बनाने के लिए कैसे बदलना है, अन्य थ्रेड्स का उपयोग कर सकते हैं। अंतर-धागा संचार के लिए एक बुनियादी ढांचे की आवश्यकता है। एक पैटर्न, उपयोगी अभिनेता पैटर्न है, जहां आपके प्रत्येक थ्रेड कुछ इन-प्रोसेस मैसेजिंग तंत्र के लिए एक लक्ष्य है।

इसलिए, अन्य थ्रेड्स को रद्द करने या उन्हें मारने (या अन्य अजीब सामान) के बजाय, आपको सिग्नल के संदर्भ में सिग्नल को सिग्नल हैंडलर थ्रेड से जोड़ने की कोशिश करनी चाहिए, फिर अपने अभिनेता पैटर्न संचार तंत्र का उपयोग उन अभिनेताओं को शब्दार्थ भेजने के लिए करें। जिन्हें सिग्नल से संबंधित जानकारी की आवश्यकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.