2011-02-05 18 views
6

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

मेरे कार्यक्रम में, दो प्रक्रियाएं एक कोड को संवाद करती हैं, और फिर एक दूसरे को एक संदेश स्थानांतरित करता है। SIGUSR1 0 का प्रतिनिधित्व करता है, SIGUSR2 का प्रतिनिधित्व करता है 1. विचार यह है कि संदेश भेजने की प्रक्रिया में मारने के लिए जो भी सिगसआर संदेश प्राप्त करने के लिए हत्या कार्य का उपयोग करेगा, और प्राप्त करने की प्रक्रिया में कोड की व्याख्या करने के लिए सिग्नल हैंडलर होगा।

तो यहां समस्या है। मेरे पास प्रेषक शुरू हो गया है। यह सोता है जब यह कोड भेजने के लिए इंतजार कर रहा है। प्रेषक प्रेषक के ढक्कन को खोजने के लिए pidof(8) का उपयोग करके 'पासवर्ड' को इंगित करने के लिए दो SIGINT भेजता है।

प्रेषक के सिग्नल हैंडलर ने इन संकेतों को पढ़ लिया है, यह पहचानता है कि यह उचित पासवर्ड है, फिर यह संदेश भेजने के लिए आगे बढ़ता है।

रिसीवर अब कुछ कार्यों के माध्यम से चला गया है, और प्रत्येक बिट के लिए हर दूसरे इंतजार के लिए हर दूसरे इंतजार कर रहा है। समस्या यह है कि यह कभी नहीं होता है।

मैं इसे स्थापित किया है ऊपर ऐसी है कि इस तरह तो थोड़ा (0 इस मामले में) भेज रहा है:

kill(SIGUSR1,washingtonPID); 

जहां washingtonPID रिसीवर की पीआईडी ​​है, और मैं इस को सत्यापित किया है सही है पीआईडी।

रिसीवर के हैंडलर इसलिए की तरह झुका है:

//IN MAIN 
    signal(SIGINT,bitReceiver); 
    signal(SIGUSR1,bitReceiver); 
    signal(SIGUSR2,bitReceiver); 
//OUTSIDE MAIN 

    void bitReceiver(int signum) 
{ 
    if(signum == SIGUSR1) 
    { 
     fprintf(stderr,"SIGUSR1 - 0"); 
     bit = 0; 
    } 
    else if (signum == SIGUSR2) 
    { 
     fprintf(stderr,"SIGUSR2 - 1"); 
     bit = 1; 
    } 
    else //sigint 
    raise(SIGINT); 

    return; 
} 

जहां बिट एक वैश्विक चर रहा है। यह शुरू में -1 पर सेट है।

int receiveBit() 
{ 
    while(bit == -1) 
    { 
     sleep(1); 
    } 
    fprintf(stderr,"%d",bit); 
    int bit2 = bit; 
    bit = -1; 
    return bit2; 
} 

तो बुनियादी रन के माध्यम से यह है:: कोड भेजने वाले को रिसीवर से भेज दिया गया है के बाद, इस की मार संकेत भेजने के लिए शुरू होता है

यहाँ समारोह जो बिट्स पढ़ता है यूएसआर 1 और यूएसआर 2 रिसीवर को, जो अंततः एक बाइनरी संदेश बनाना चाहिए।

रिसीवर बस इस बिंदु पर प्रतीक्षा कर रहा है, हर सेकेंड सो रहा है। जब यह बाधित हो जाता है, तो हैंडलर 0 या 1 पर सेट करेगा, इसे नींद से मार देगा, थोड़ा प्रिंट करेगा, और इसे वापस कर देगा।

तो मैं दो कार्यक्रमों सामान्य रूप से चलाने, रिसीवर सिर्फ नींद में बैठता है, और हैंडलर कभी नहीं कहा जाता है (भले ही मैं देख सकता हूँ कॉल अन्य प्रक्रिया द्वारा किया जा रहा है।

तो मैं इस रोक , और मैन्युअल रूप से किल सिग्नल भेजते हैं, मैं एक भेज सकता हूं, शायद दो सिग्नल, दोनों ठीक तरह से संभाले जा सकते हैं। उसके बाद कोई भी, और मुझे टर्मिनल पर 'यूजर सिग्नल 2' जैसे मुद्रित संदेश मिलता है। मेरे प्रोग्राम में जो कुछ नहीं है , और कार्यक्रम तुरंत क्यों मेरे हैंडलर envoked नहीं किया जा रहा है के रूप में बंद हो जाता है।

किसी भी अंतर्दृष्टि, और कारण है कि मैं मैन्युअल रूप से नहीं भेज सकते अधिक तो एक या दो संकेत बहुत सराहना की जाएगी।

012,351,

आपके समय के लिए धन्यवाद।

संपादित करें: ऐसा लगता है जैसे लोग इस पर फंस गए हैं। क्या कोई डीबगिंग युक्तियाँ मैं कोशिश कर सकता हूं?

+0

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

+3

यदि आप पहले पैराग्राफ में नोट करेंगे, तो मैंने उल्लेख किया है कि यह एक असाइनमेंट है और असली दुनिया की समस्या नहीं है। यह अक्षम है, और पिडोफ़ का उपयोग सुरक्षित नहीं है। लेकिन मैं इसके बारे में चिंतित नहीं हूं। – Blackbinary

+1

क्या 'बिट' घोषित 'अस्थिर' है? वैश्विक नामस्थान में –

उत्तर

5

जैसा कि कई ने पहले ही टिप्पणी की है, आपको सिग्नल के साथ ऐसा नहीं करना चाहिए। जब यह गलत हो जाता है (और ऐसा होगा, जैसा कि किया गया था) यह पता लगाने की कोशिश कर रहा है कि क्या गलत है जब अपरिभाषित व्यवहार पीछे है तो यह असंभव नहीं है।

सिग्नल हैंडलर के अंदर fprintf जैसे गैर एसिंक-सुरक्षित सिस्टम कॉल का उपयोग डेटा को भ्रष्ट कर सकता है क्योंकि fprintf उसी स्ट्रीम पर चल रहा है। साझा चर के साथ ही।

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

यही कारण है कि सिग्नल डिफ़ॉल्ट रूप से रीसेट होने से पहले आप उसी प्रकार के अधिकतम 1 सिग्नल भेज सकते हैं और "उपयोगकर्ता सिग्नल xx" के साथ प्रोग्राम को समाप्त कर सकते हैं।

मैं आपको कोड के साथ खुद को पीड़ित करना बंद कर दूंगा और कुछ पाठ्यपुस्तक या ट्यूटोरियल ले जाऊंगा और उसका पालन करने का प्रयास करूंगा।

अगर यह जाता है तो सिग्नल कॉल से बचा जाना चाहिए। आदमी पृष्ठों से:

संकेत के व्यवहार() यूनिक्स संस्करणों में भिन्न होती है, और यह भी विभिन्न ऐतिहासिक दृष्टि से विभिन्न संस्करणों लिनक्स की भर में है। इसके उपयोग से बचें: इसके बजाय सिग्नेक्शन (2) का उपयोग करें।

+2

मैं ईमानदारी की सराहना करता हूं। मुझे एहसास है कि मुझे सिग्नल के बजाए विभिन्न कार्यों और सिग्नेशन का उपयोग करना चाहिए, लेकिन यह coursework है और मुझे खुद को दिशानिर्देशों को सीमित करने की जरूरत है। क्या एक ही प्रकार के संकेतों को एक पंक्ति में भेजने का कोई तरीका है? क्या होगा अगर मैं संकेतों के बीच लंबे समय तक सो जाऊं, तो क्या इससे मदद मिलेगी? या क्या मुझे शायद एक फिलर सिग्नल का उपयोग करना चाहिए, मैं हमेशा हर नियमित सिग्नल के बीच में अनदेखा करता हूं? – Blackbinary

+1

आपने वास्तव में मुझे जवाब दिया है, मुझे बस अधिक विस्तार से पढ़ना पड़ा। जैसा कि आपने कहा था, सिग्नल पकड़ा जाने के बाद, यह SIG_DFL पर वापस आ जाता है, इसलिए इसका मतलब है कि हर बार जब मैं अपना फ़ंक्शन दर्ज करता हूं जो सो जाएगा, तो मैं यह सुनिश्चित करने के लिए कि सिग्नल SIG_DFL नहीं है, मैं बस सिग्नल (SIGUSR1, हैंडलर) सेट करता हूं। – Blackbinary

0

कुछ चीजें जो मुझे नोटिस करती हैं।

  • सिग्नल हैंडलर में उपयोग किए गए किसी भी साझा चर को volatile के रूप में सेट किया जाना चाहिए।
  • fprintf() सिग्नल हैंडलर में उपयोग करने के लिए एक सुरक्षित कार्य नहीं है। सुरक्षित कार्यों की सूची प्राप्त करने के लिए signal() के लिए अपने मैन पेज को देखें।
  • भी, सिग्नल() में कुछ अलग-अलग कार्यान्वयन हैं यदि सिग्नल हैंडलर को ट्रिगर होने के बाद SIG_DFL पर रीसेट कर दिया गया है। अधिकांश यूनिक्स आपको यह सुनिश्चित करने के लिए sigaction() का उपयोग करने का सुझाव देते हैं कि आप जो व्यवहार चाहते हैं उसे प्राप्त करें। या परीक्षण करने के लिए आप हैंडलर के अंदर सिग्नल हैंडलर को रीसेट कर सकते हैं, देखें कि क्या यह आपको एक अलग व्यवहार देता है।
+0

क्यों आपका प्रेषक काम नहीं कर रहा है, मैं यह देखने के लिए कुछ डीबग लिखूंगा कि ए) आपका "वाशिंगटन पीआईडी" वैरिएबल वह है जो आपको लगता है, और हत्या() दिनचर्या की वापसी की जांच करें। सुनिश्चित करें कि आप उन्हें एक ही उपयोगकर्ता के रूप में चला रहे हैं और न ही किसी अन्य उपयोगकर्ता को सेट किया गया है। – CoreyStup

+1

मुझे अपना प्रेषक काम कर रहा है, यह सिर्फ 1 या दो संकेतों के बाद डिफ़ॉल्ट हैंडलर संकेतों को पकड़ने के साथ ही बग है। – Blackbinary

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