2012-07-26 18 views
87

लिनक्स में, क्या होता है जब एक प्रोग्राम (जिसमें संभवतः एकाधिक धागे होते हैं) सिग्टरएम या SIGHUP जैसे सिग्नल प्राप्त करते हैं?लिनक्स में कई धागे के साथ सिग्नल हैंडलिंग

कौन सा धागा सिग्नल को रोकता है? क्या एकाधिक धागे एक ही सिग्नल प्राप्त कर सकते हैं? सिग्नल को संभालने के लिए पूरी तरह समर्पित एक विशेष धागा है? यदि नहीं, सिग्नल को संभालने के लिए धागे के अंदर क्या होता है? सिग्नल हैंडलर दिनचर्या समाप्त होने के बाद निष्पादन फिर से शुरू कैसे होता है?

उत्तर

30

यह थोड़ा सा ज्ञान है, जो कि आप लिनक्स कर्नेल का उपयोग कर रहे हैं के संस्करण के आधार पर।

2.6 पॉज़िक्स धागे मानते हैं, और यदि आप ओईएस के बारे में बात कर रहे हैं तो सिगरेट या SIGHUP भेजना, सिग्नल प्रक्रिया को भेजा जाता है, जिसे रूट थ्रेड द्वारा प्राप्त किया जाता है और संभाला जाता है। POSIX धागे का उपयोग करके, आप SIGTERM को अलग-अलग थ्रेडों पर भी भेज सकते हैं, लेकिन मुझे संदेह है कि आप इस बारे में पूछ रहे हैं कि ओएस प्रक्रिया को सिग्नल भेजता है तो क्या होता है।

2.6 में, SIGTERM बच्चे के धागे को "साफ-सफाई" से बाहर निकलने का कारण बनता है, जहां 2.4 के रूप में, बाल धागे अनिश्चित स्थिति में छोड़े जाते थे।

+0

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

+1

यदि आपके पास हैंडलर सेटअप है, तो इसे एक बाधा के रूप में माना जाएगा, और प्रोग्राम प्रवाह रोक दिया जाएगा और आपका कस्टम हैंडलर निष्पादित किया जाएगा। एक बार इसे निष्पादित करने के बाद, नियंत्रण वापस आ जाएगा, मान लीजिए कि आपने सामान्य प्रवाह (बाहर निकलने आदि) को बदलने के लिए कुछ भी नहीं किया है। – Alan

+0

ध्यान दें कि यह SIGUSR1 के लिए विशिष्ट है, जो आईआईआरसी सिस्टम कॉल को बाधित नहीं करता है। यदि आपने उदाहरण के लिए SIGINT के साथ ऐसा करने की कोशिश की है, तो यह एक स्ट्रीम को पढ़ने में बाधा डाल सकता है, और जब आप पढ़ने के लिए वापस लौटते हैं, तो स्ट्रीम एक त्रुटि लौटा सकती है जिसे बाधित किया गया था। – Alan

102

pthreads(7) का वर्णन करता है कि POSIX.1 एक प्रक्रिया शेयर विशेषताओं के सारे सूत्र, सहित की आवश्यकता है:

  • संकेत स्वभाव

POSIX.1 भी कुछ विशेषताओं की आवश्यकता है प्रत्येक थ्रेड के लिए अलग होने के लिए , जिनमें शामिल हैं:

  • सिग्नल मास्क (pthread_sigmask(3))

  • वैकल्पिक संकेत ढेर (sigaltstack(2))

लिनक्स कर्नेल के complete_signal() दिनचर्या निम्नलिखित कोड ब्लॉक किया गया है - टिप्पणी काफी उपयोगी होते हैं:

/* 
    * Now find a thread we can wake up to take the signal off the queue. 
    * 
    * If the main thread wants the signal, it gets first crack. 
    * Probably the least surprising to the average bear. 
    */ 
    if (wants_signal(sig, p)) 
      t = p; 
    else if (!group || thread_group_empty(p)) 
      /* 
      * There is just one thread and it does not need to be woken. 
      * It will dequeue unblocked signals before it runs again. 
      */ 
      return; 
    else { 
      /* 
      * Otherwise try to find a suitable thread. 
      */ 
      t = signal->curr_target; 
      while (!wants_signal(sig, t)) { 
        t = next_thread(t); 
        if (t == signal->curr_target) 
          /* 
          * No thread needs to be woken. 
          * Any eligible threads will see 
          * the signal in the queue soon. 
          */ 
          return; 
      } 
      signal->curr_target = t; 
    } 

    /* 
    * Found a killable thread. If the signal will be fatal, 
    * then start taking the whole group down immediately. 
    */ 
    if (sig_fatal(p, sig) && 
     !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && 
     !sigismember(&t->real_blocked, sig) && 
     (sig == SIGKILL || !t->ptrace)) { 
      /* 
      * This signal will be fatal to the whole group. 
      */ 

तो, आप देख आप सिग्नल वितरित किए जाने के प्रभारी हैं:

यदि आपका प्रक्रिया ने सिग्नल के स्वभाव को SIG_IGN या SIG_DFL पर सेट किया है, तो सिग्नल को सभी धागे के लिए अनदेखा किया जाता है (या डिफ़ॉल्ट - मार, कोर, या अनदेखा)।

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

कुछ संकेत है, तथापि, विशेष कर रहे हैं:

A signal may be generated (and thus pending) for a process as 
    a whole (e.g., when sent using kill(2)) or for a specific 
    thread (e.g., certain signals, such as SIGSEGV and SIGFPE, 
    generated as a consequence of executing a specific machine- 
    language instruction are thread directed, as are signals 
    targeted at a specific thread using pthread_kill(3)). A 
    process-directed signal may be delivered to any one of the 
    threads that does not currently have the signal blocked. If 
    more than one of the threads has the signal unblocked, then 
    the kernel chooses an arbitrary thread to which to deliver 
    the signal. 
+6

कर्नेल कोड उद्धृत करने की परेशानी के माध्यम से जाने के लिए धन्यवाद! बहुत उपयोगी। – cheshirekow

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

  • कोई संबंधित समस्या नहीं^_^