2011-05-24 15 views
51

मैं समझने की कोशिश कर रहा हूं कि CTRL + सी एक बच्चे को समाप्त करता है लेकिन माता-पिता की प्रक्रिया नहीं। मैं इस व्यवहार को bash जैसे कुछ स्क्रिप्ट शैल में देखता हूं, जहां आप कुछ लंबी चलने वाली प्रक्रिया शुरू कर सकते हैं और फिर CTRL - सी पर नियंत्रण करके इसे नियंत्रित कर सकते हैं और नियंत्रण खोल पर वापस आ जाता है।Ctrl-C कैसे एक बाल प्रक्रिया को समाप्त करता है?

क्या आप समझा सकते हैं कि यह कैसे काम करता है और विशेष रूप से माता-पिता (खोल) प्रक्रिया क्यों समाप्त नहीं होती है?

खोल CTRL + सी घटना के कुछ विशेष हैंडलिंग करने के लिए है और यदि हाँ क्या वास्तव में यह क्या करता है?

+1

बच्चे को समाप्त करने से माता-पिता को समाप्त क्यों किया जाएगा? और नहीं, कोई विशेष हैंडलिंग की आवश्यकता नहीं है। –

+3

@ नील बटरवर्थ: मैं नहीं पूछ रहा हूं कि एक बच्चे को समाप्त करने से माता-पिता को समाप्त नहीं किया जा रहा है। प्रश्न यह है कि बाल प्रक्रिया को Ctrl-C ईवेंट क्यों मिलता है, न कि माता-पिता? – vitaut

उत्तर

48

सिग्नल डिफ़ॉल्ट रूप से गिरी द्वारा नियंत्रित किया जाता है। ओल्ड यूनिक्स सिस्टम में 15 सिग्नल थे; अब उनके पास और अधिक है। आप </usr/include/signal.h> (या kill -l) देख सकते हैं। CTRL + सी नाम SIGINT नाम के साथ संकेत है।

प्रत्येक सिग्नल को संभालने के लिए डिफ़ॉल्ट कार्रवाई को भी कर्नेल में परिभाषित किया गया है, और आमतौर पर यह सिग्नल प्राप्त करने वाली प्रक्रिया को समाप्त करता है।

सभी सिग्नल (लेकिन SIGKILL) प्रोग्राम द्वारा प्रबंधित किए जा सकते हैं।

और यही खोल करता है:

  • खोल चल इंटरैक्टिव मोड में, यह एक विशेष संकेत इस विधा के लिए से निपटने है जब।
  • आप, खोल उदाहरण find के लिए एक कार्यक्रम चलाते हैं,:
    • fork रों ही
    • और बच्चे के लिए डिफ़ॉल्ट संकेत से निपटने
    • दिया कमांड के साथ बच्चे की जगह सेट (उदाहरण के लिए खोज के साथ)
    • आप जब प्रेस CTRL + सी, माता पिता खोल इस संकेत को संभालने लेकिन बच्चे इसे प्राप्त होगा - डिफ़ॉल्ट कार्रवाई के साथ - समाप्त। (बच्चे संकेत हैंडलिंग भी लागू कर सकते हैं)

आप कर सकते हैं अपने खोल स्क्रिप्ट भी में trap संकेत ...

और तुम संकेत भी अपने इंटरैक्टिव खोल के लिए से निपटने के सेट कर सकते हैं, पर यह दर्ज कोशिश आप के शीर्ष ~/.profile। , हर बार जब आप अपने खोल में CTRL + सी प्रेस

trap 'echo "Dont do this"' 2 

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

यदि रुचि है, तो आप स्रोत कोड here में सादे पुराने /bin/sh सिग्नल हैंडलिंग की जांच कर सकते हैं।

उपरोक्त में टिप्पणियों में कुछ गलत जानकारी थी (अब हटा दी गई), इसलिए अगर यहां रुचि रखने वाला कोई व्यक्ति बहुत अच्छा लिंक है - how the signal handling works

+1

स्पष्टीकरण और लिंक के लिए धन्यवाद। "टीटीवी डिमस्टिफाइड" मैंने कभी देखा है सबसे अच्छा परिचय है। – vitaut

+3

सिगस्टॉप भी अचूक है। –

+1

* जब आप 'CTRL + C' दबाते हैं, तो पैरेंट खोल इस सिग्नल को संभालता है * - यह सादा गलत है क्योंकि शैल को इस परिदृश्य में यह सिग्नल भी प्राप्त नहीं होता है; @ जेडीबीपी का [उत्तर] देखें (http://stackoverflow.com/a/6110213/95735)। –

7

टर्मिनल टर्मिनल से जुड़ी प्रक्रिया में आईएनटी (इंटरप्ट) सिग्नल भेजता है। कार्यक्रम तब प्राप्त करता है, और इसे अनदेखा करना या छोड़ना चुन सकता है।

कोई प्रक्रिया आवश्यक रूप से जबरन बंद नहीं है (हालांकि डिफ़ॉल्ट रूप से, यदि आप सिग्ंट को संभाल नहीं पाते हैं, तो मेरा मानना ​​है कि व्यवहार abort() पर कॉल करना है, लेकिन मुझे इसे देखना होगा)।

बेशक, चल रही प्रक्रिया को खोलने वाले खोल से अलग किया जाता है।

आप तो माता पिता खोल जाना, exec के साथ अपने कार्यक्रम शुरू करना चाहता था: इस तरह

exec ./myprogram 

, माता पिता खोल बच्चे प्रक्रिया

+0

क्या मैं सही ढंग से समझता हूं कि जब मैं एक खोल से कुछ प्रक्रिया शुरू करता हूं तो यह टर्मिनल से जुड़ा होता है और यही कारण है कि यह आईएनटी सिग्नल प्राप्त करता है? – vitaut

+1

आम तौर पर, हाँ। लोकप्रिय खोल में अग्रभूमि नौकरियों के लिए, हाँ। यह खोल पर निर्भर करेगा, और क्या टर्मिनल भी है। – sehe

+1

@ कोबामेम: तो आप कह रहे हैं कि सिग्नल को पहले खोल में भेजा जाता है जो उसके बाद इसे बाल प्रक्रिया में भेज देता है? फिर खोलने के लिए मैन्युअल रूप से SIGINT को भेजने से बच्चे को नहीं मारता है, उदा। 'हत्या -2 ' बच्चे की प्रक्रिया में कुछ भी नहीं करता है जबकि Ctrl-C इसे मारता है? – vitaut

3

CTRL + सी द्वारा प्रतिस्थापित हो हत्या आदेश के लिए एक नक्शा है। जब आप उन्हें दबाते हैं, तो हत्या एक सिगिनट सिग्नल भेजती है, जो प्रक्रिया को बाधित करती है।

को मार डालो: http://en.wikipedia.org/wiki/Kill_(command)

SIGINT: http://en.wikipedia.org/wiki/SIGINT_(POSIX)

+1

लिंक के लिए धन्यवाद, लेकिन SIGINT सिग्नल के लिए लक्षित प्रक्रिया कैसे निर्धारित की जाती है? और मैपिंग लागू करता है, खोल खुद ही? – vitaut

+1

लक्ष्य प्रक्रिया वर्तमान प्रक्रिया है जिसे आप निष्पादित कर रहे हैं। मानचित्रण टर्मिनल में सेट है, आप इसे stty के साथ बदल सकते हैं। –

+1

एक और लिंक: http://www.devdaily.com/unix/edu/IntroToUnix/node4.shtml#SECTION004120000000000000000 –

19

सबसे पहले, the Wikipedia article on the POSIX terminal interface सभी तरह से पढ़ें।

SIGINT सिग्नल टर्मिनल लाइन अनुशासन द्वारा उत्पन्न होता है, और टर्मिनल के अग्रभूमि प्रक्रिया समूह में सभी प्रक्रियाओं को प्रसारित करता है। आपके खोल ने आपके द्वारा चलाए गए आदेश (या कमांड पाइपलाइन) के लिए पहले से ही एक नया प्रक्रिया समूह बनाया है, और टर्मिनल को बताया कि वह प्रक्रिया समूह (टर्मिनल) अग्रभूमि प्रक्रिया समूह है। प्रत्येक समवर्ती कमांड पाइपलाइन का अपना प्रोसेस ग्रुप होता है, और फोरग्राउंड कमांड पाइपलाइन प्रक्रिया समूह के साथ एक है जिसे खोल टर्मिनल के अग्रभूमि प्रक्रिया समूह के रूप में टर्मिनल में प्रोग्राम किया गया है। अग्रभूमि और पृष्ठभूमि के बीच "नौकरियां" स्विच करना (कुछ विवरण अलग-अलग हैं) शेल का एक मामला टर्मिनल को बताता है जो प्रक्रिया समूह अब अग्रभूमि है।

शैल प्रक्रिया स्वयं ही एक और प्रक्रिया समूह में है और इसलिए सिग्नल प्राप्त नहीं होता है जब उनमें से एक प्रक्रिया समूह अग्रभूमि में होता है। यह इत्ना आसान है।

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