2010-11-02 13 views
6

मुझे पता होना चाहिए कि सी में संकेतों को संभालने के दौरान दौड़ की स्थिति से कैसे बचें। प्रत्येक बार जब मेरा प्रोग्राम सिग्नल प्राप्त करता है, तो मैं इसे एक (वैश्विक) लिंक सूची में बदलना चाहता हूं। यह बेहद जरूरी है कि मुझे सिग्नल याद न हो, और उतना ही महत्वपूर्ण है कि हैंडलर निष्पादित होने पर वैश्विक लिंक की गई सूची को मैं संशोधित नहीं कर रहा हूं।सी सिग्नल हैंडलर पहेली में रेस हालत

समस्या है, अगर मुझे संकेत मिलता है, और हैंडलर शुरू होता है, लेकिन फिर एक और सिग्नल द्वारा बाधित किया जाता है। यह (जैसा कि मैं इसे समझता हूं) सिग्नल हैंडलर का एक नया निष्पादन ट्रिगर करता है, जो एक ही वैश्विक डेटासेट पर काम करेगा - अनुमत नहीं है!

मैं लॉक का उपयोग नहीं कर सकता, क्योंकि अगर पहला हैंडलर कॉल बाधित हो जाता है, तो यह स्वाभाविक रूप से हस्तक्षेप करने वाले हैंडलर को लेने के लिए ताला मुक्त नहीं करेगा। तो मैं इसे कैसे करूं? कोई उपाय?

+0

ऐसा लगता है कि लॉक वास्तव में आपको जो चाहिए वह है, यह पहली कॉल समाप्त होने तक दूसरी कॉल को रोक देगा। क्या वह वही नहीं है जो आप चाहते हैं? – Doggett

+2

यह इस मामले में डेडलॉक होगा, क्योंकि नया बाधा अवरुद्ध होगा, और कभी भी निष्पादन धागे पर नियंत्रण वापस नहीं करेगा। यही है, पहला * कभी खत्म नहीं होगा। – Nate

+4

ध्यान रखें कि संकेत किसी भी तरह "मिस्ड" होंगे। यदि उदा। आपकी प्रक्रिया को समय में एक साथ बंद करने के लिए 2 सिग्नल मिलते हैं, वे ओएस द्वारा एक सिग्नल में विलय हो जाते हैं। – nos

उत्तर

1

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

बेशक, आपको अपने ओएस के संदेश को जंक पास करने पर भरोसा करना है, ताकि यह एक विकल्प न हो।

+0

आप एनक्यूइंग कैसे करते हैं? – JeremyP

+1

@ जेरेमीपी: परिपत्र बफर ;-) –

+0

@ स्टेव जेसॉप: बहुत अच्छा +1। – JeremyP

1

सिग्नल हैंडलर निष्पादित करते समय आप संकेतों को मुखौटा कर सकते हैं - sa_maskstruct sigaction का क्षेत्र sigaction() syscall पर जाएं।

+0

कोई अच्छा नहीं है क्योंकि तब मैं संकेतक याद करता हूं जो हैंडलर निष्पादित करते समय आते हैं - जैसा कि मैंने कहा, यह बेहद जरूरी है कि मुझे सिग्नल याद न हो। – Benubird

+1

सिग्नल अनमास्क्ड होने के बाद सिग्नल डिलीवर किया जाएगा, इसलिए सिग्नल हैंडलर से वापस आने के तुरंत बाद हैंडलर को फिर से बुलाया जाएगा। – qrdl

+0

@qrdl एक महत्वपूर्ण बिंदु। शायद यह सब में 'शास्त्रीय प्रशिक्षण' की कमी है, लेकिन यह मेरे लिए सहज नहीं था, इसलिए जब मैंने पहली बार इसका सामना किया ('gtkmm' के साथ काम करना), मुझे यह समझने में थोड़ी देर लग गई कि क्या हो रहा था! यह एक आदर्श प्रतीत होता है।स्पष्ट रूप से एक अच्छा विचार है क्योंकि यह आपके सुझाव जैसे पैटर्न को सक्षम बनाता है, यह मुझे एक बेहतर आर्किटेक्चर लिखने के लिए 'मेरे रास्ते में आया', इसलिए किसी भी सिग्नल के लिए हैंडलर ने एक और संभाल सिग्नल उत्सर्जित नहीं किया। –

1

http://users.evtek.fi/~tk/rtp/signals-programming.html से:

तरह से सभी में कोई दौड़ गारंटी करने के लिए, प्रणाली संकेत हमारे लिए मास्किंग सेट से पहले यह संकेत हैंडलर कॉल देना है। यह किया जा सकता है अगर हम सिग्नल हैंडलर फ़ंक्शन और हैंडलर निष्पादित होने पर सिग्नल मास्क दोनों को परिभाषित करने के लिए सिग्नेशन() सिस्टम कॉल का उपयोग करते हैं। आप शायद सिग्नेशन() के लिए मैन्युअल पेज को पढ़ने में सक्षम होंगे, अब आप सिग्नल हैंडलिंग की विभिन्न अवधारणाओं से परिचित हैं। पुराने सिस्टम पर, आपको यह सिस्टम कॉल नहीं मिलेगी, लेकिन आपको अभी भी sigvec() कॉल मिल सकती है, जो समान कार्यक्षमता को सक्षम करती है।

0

मुझे लगता है कि आपको सिग्नल को सही करना चाहिए। कार्य कतार E.g. सभी संकेतों को एक कार्य कतार (एफआईएफओ) में रखा जाना चाहिए, और उसके बाद निष्पादन धागा कतार को हर समय मतदान करता है। यदि कतार खाली नहीं है, तो यह धागा शीर्ष सिग्नल उठाएगा और इसे हैंडलर शुरू करेगा। ऐसा करने के लिए, कतार खाली होने तक ऐसा करते रहें।

+0

कतार में डाल सुरक्षित – Andrey

+0

कतार परियोजना के लिए ताला उपयोग कर सकते हैं थ्रेड नहीं है। –

संबंधित मुद्दे