सी भाषा में सिग्नल हैंडलर का उपयोग कैसे करें?

How Use Signal Handlers C Language



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

संकेत

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







मानक संकेत

हेडर फ़ाइल में संकेतों को परिभाषित किया गया है सिग्नल.एच मैक्रो स्थिरांक के रूप में। सिग्नल का नाम SIG से शुरू होता है और उसके बाद सिग्नल का संक्षिप्त विवरण होता है। तो, प्रत्येक सिग्नल का एक अद्वितीय संख्यात्मक मान होता है। आपके प्रोग्राम को हमेशा सिग्नल के नाम का उपयोग करना चाहिए, सिग्नल नंबर का नहीं। कारण यह है कि सिग्नल नंबर सिस्टम के अनुसार अलग-अलग हो सकते हैं लेकिन नामों का अर्थ मानक होगा।



मैक्रो एनएसआईजी परिभाषित संकेत की कुल संख्या है। का मूल्य एनएसआईजी परिभाषित सिग्नल की कुल संख्या से एक अधिक है (सभी सिग्नल नंबर लगातार आवंटित किए जाते हैं)।



निम्नलिखित मानक संकेत हैं:





सिग्नल का नाम विवरण
उच्छ्वास करो प्रक्रिया को लटकाएं। SIGHUP सिग्नल का उपयोग उपयोगकर्ता के टर्मिनल के वियोग की रिपोर्ट करने के लिए किया जाता है, संभवत: क्योंकि रिमोट कनेक्शन खो जाता है या हैंग हो जाता है।
सिगिनट प्रक्रिया को बाधित करें। जब उपयोगकर्ता INTR वर्ण (सामान्यतः Ctrl + C) टाइप करता है तो SIGINT संकेत भेजा जाता है।
सिग्क्विट प्रक्रिया से बाहर निकलें। जब उपयोगकर्ता QUIT वर्ण (सामान्यतः Ctrl + ) टाइप करता है तो SIGQUIT संकेत भेजा जाता है।
सील अवैध निर्देश। जब कचरा या विशेषाधिकार प्राप्त निर्देश निष्पादित करने का प्रयास किया जाता है, तो सिगिल सिग्नल उत्पन्न होता है। इसके अलावा, जब स्टैक ओवरफ्लो हो जाता है, या जब सिस्टम को सिग्नल हैंडलर चलाने में परेशानी होती है, तो सिगिल उत्पन्न किया जा सकता है।
सिगट्रैप ट्रेस ट्रैप। एक ब्रेकपॉइंट निर्देश और अन्य ट्रैप निर्देश SIGTRAP सिग्नल उत्पन्न करेंगे। डीबगर इस सिग्नल का उपयोग करता है।
सिगब्रत गर्भपात। एबॉर्ट () फ़ंक्शन को कॉल करने पर SIGABRT सिग्नल उत्पन्न होता है। यह संकेत एक त्रुटि को इंगित करता है जो प्रोग्राम द्वारा ही पता लगाया जाता है और abort() फ़ंक्शन कॉल द्वारा रिपोर्ट किया जाता है।
SIGFPE फ़्लोटिंग-पॉइंट अपवाद। जब एक घातक अंकगणितीय त्रुटि हुई तो SIGFPE संकेत उत्पन्न होता है।
SIGUSR1 और SIGUSR2 सिग्नल SIGUSR1 और SIGUSR2 आपकी इच्छानुसार उपयोग किए जा सकते हैं। प्रोग्राम में उनके लिए सिग्नल हैंडलर लिखना उपयोगी है जो सरल इंटर-प्रोसेस संचार के लिए सिग्नल प्राप्त करता है।

सिग्नल की डिफ़ॉल्ट क्रिया

प्रत्येक सिग्नल में एक डिफ़ॉल्ट क्रिया होती है, निम्न में से एक:

अवधि: प्रक्रिया समाप्त हो जाएगी।
सार: प्रक्रिया समाप्त हो जाएगी और कोर डंप फ़ाइल तैयार करेगी।
आग लगाना: प्रक्रिया सिग्नल को अनदेखा कर देगी।
विराम: प्रक्रिया रुक जाएगी।
लेखा: प्रक्रिया रुकने से जारी रहेगी।



हैंडलर फ़ंक्शन का उपयोग करके डिफ़ॉल्ट क्रिया को बदला जा सकता है। कुछ सिग्नल की डिफ़ॉल्ट क्रिया को बदला नहीं जा सकता। सिगकिल तथा सिगब्रत सिग्नल की डिफ़ॉल्ट क्रिया को बदला या अनदेखा नहीं किया जा सकता है।

सिग्नल हैंडलिंग

यदि कोई प्रक्रिया संकेत प्राप्त करती है, तो प्रक्रिया में उस प्रकार के संकेत के लिए कार्रवाई का विकल्प होता है। प्रक्रिया सिग्नल को अनदेखा कर सकती है, एक हैंडलर फ़ंक्शन निर्दिष्ट कर सकती है, या उस तरह के सिग्नल के लिए डिफ़ॉल्ट कार्रवाई स्वीकार कर सकती है।

  • यदि संकेत के लिए निर्दिष्ट कार्रवाई को अनदेखा किया जाता है, तो संकेत तुरंत त्याग दिया जाता है।
  • प्रोग्राम एक हैंडलर फ़ंक्शन को फ़ंक्शन का उपयोग करके पंजीकृत कर सकता है जैसे संकेत या संकेतन . इसे कहा जाता है कि एक हैंडलर सिग्नल को पकड़ता है।
  • यदि सिग्नल को न तो संभाला गया है और न ही अनदेखा किया गया है, तो इसकी डिफ़ॉल्ट कार्रवाई होती है।

हम सिग्नल का उपयोग करके संभाल सकते हैं संकेत या संकेतन समारोह। यहाँ हम देखते हैं कि कैसे सबसे सरल संकेत () सिग्नल को संभालने के लिए फ़ंक्शन का उपयोग किया जाता है।

NSसंकेत() (NSसंकेत, शून्य (*समारोह)(NS))

NS संकेत () कॉल करेंगे समारोह कार्य यदि प्रक्रिया को संकेत प्राप्त होता है संकेत . NS संकेत () कार्य करने के लिए एक सूचक देता है समारोह यदि सफल होता है या यह त्रुटि को त्रुटि देता है और -1 अन्यथा।

NS समारोह सूचक के तीन मान हो सकते हैं:

  1. एसआईजी_डीएफएल : यह सिस्टम डिफॉल्ट फंक्शन का सूचक है SIG_DFL () में घोषित एच शीर्ष लेख फ़ाइल। इसका उपयोग सिग्नल की डिफ़ॉल्ट कार्रवाई करने के लिए किया जाता है।
  2. SIG_IGN : यह सिस्टम इग्नोर फंक्शन का सूचक है SIG_IGN () में घोषित एच शीर्ष लेख फ़ाइल।
  3. उपयोगकर्ता परिभाषित हैंडलर फ़ंक्शन पॉइंटर : उपयोगकर्ता परिभाषित हैंडलर फ़ंक्शन प्रकार है शून्य (*) (इंट) , इसका मतलब है कि वापसी प्रकार शून्य है और एक प्रकार का तर्क int है।

बेसिक सिग्नल हैंडलर उदाहरण

#शामिल
#शामिल
#शामिल
शून्यsig_handler(NSसंकेत){

// हैंडलर फ़ंक्शन का रिटर्न प्रकार शून्य होना चाहिए
printf ('एनहैंडलर फ़ंक्शन के अंदरएन');
}

NSमुख्य(){
संकेत(सिगिनट,sig_handler); // रजिस्टर सिग्नल हैंडलर
के लिये(NSमैं=1;;मैं++){ //अनंत लूप
printf ('%d : मुख्य समारोह के अंदरएन',मैं);
नींद(1); // 1 सेकंड के लिए देरी
}
वापसी 0;
}

example1.c के आउटपुट के स्क्रीनशॉट में, हम देख सकते हैं कि मुख्य फ़ंक्शन में अनंत लूप निष्पादित हो रहा है। जब उपयोगकर्ता ने Ctrl + C टाइप किया, तो मुख्य फ़ंक्शन निष्पादन रुक जाता है और सिग्नल के हैंडलर फ़ंक्शन को लागू किया जाता है। हैंडलर फ़ंक्शन के पूरा होने के बाद, मुख्य फ़ंक्शन निष्पादन फिर से शुरू हुआ। जब उपयोगकर्ता ने Ctrl+ टाइप किया, तो प्रक्रिया बंद हो जाती है।

सिग्नल पर ध्यान न दें उदाहरण

#शामिल
#शामिल
#शामिल
NSमुख्य(){
संकेत(सिगिनट,SIG_IGN); // सिग्नल को अनदेखा करने के लिए सिग्नल हैंडलर पंजीकृत करें

के लिये(NSमैं=1;;मैं++){ //अनंत लूप
printf ('%d : मुख्य समारोह के अंदरएन',मैं);
नींद(1); // 1 सेकंड के लिए देरी
}
वापसी 0;
}

यहां हैंडलर फ़ंक्शन पंजीकृत है SIG_IGN () सिग्नल कार्रवाई की अनदेखी के लिए कार्य। इसलिए, जब उपयोगकर्ता ने Ctrl+C टाइप किया, सिगिनट सिग्नल उत्पन्न हो रहा है लेकिन कार्रवाई को नजरअंदाज कर दिया गया है।

सिग्नल हैंडलर उदाहरण को फिर से पंजीकृत करें

#शामिल
#शामिल
#शामिल

शून्यsig_handler(NSसंकेत){
printf ('एनहैंडलर फ़ंक्शन के अंदरएन');
संकेत(सिगिनट,एसआईजी_डीएफएल); // डिफ़ॉल्ट कार्रवाई के लिए सिग्नल हैंडलर को फिर से पंजीकृत करें
}

NSमुख्य(){
संकेत(सिगिनट,sig_handler); // रजिस्टर सिग्नल हैंडलर
के लिये(NSमैं=1;;मैं++){ //अनंत लूप
printf ('%d : मुख्य समारोह के अंदरएन',मैं);
नींद(1); // 1 सेकंड के लिए देरी
}
वापसी 0;
}

उदाहरण3.c के आउटपुट के स्क्रीनशॉट में, हम देख सकते हैं कि जब उपयोगकर्ता ने पहली बार Ctrl+C टाइप किया, तो हैंडलर फ़ंक्शन लागू हो गया। हैंडलर फ़ंक्शन में, सिग्नल हैंडलर फिर से पंजीकृत होता है एसआईजी_डीएफएल सिग्नल की डिफ़ॉल्ट कार्रवाई के लिए। जब उपयोगकर्ता ने दूसरी बार Ctrl+C टाइप किया, तो प्रक्रिया समाप्त हो जाती है जो कि की डिफ़ॉल्ट क्रिया है सिगिनट संकेत।

सिग्नल भेजना:

एक प्रक्रिया भी स्पष्ट रूप से खुद को या किसी अन्य प्रक्रिया को संकेत भेज सकती है। सिग्नल भेजने के लिए उठाना () और किल () फ़ंक्शन का उपयोग किया जा सकता है। दोनों कार्यों को सिग्नल एच हेडर फ़ाइल में घोषित किया गया है।

NS चढ़ाई (NSसंकेत)

सिग्नल भेजने के लिए उपयोग किया जाने वाला बढ़ाएँ () फ़ंक्शन संकेत कॉलिंग प्रक्रिया (स्वयं) के लिए। सफल होने पर यह शून्य और विफल होने पर एक गैर-शून्य मान देता है।

NSमार(pid_t pid, NSसंकेत)

सिग्नल भेजने के लिए इस्तेमाल किया जाने वाला किल फंक्शन संकेत द्वारा निर्दिष्ट एक प्रक्रिया या प्रक्रिया समूह के लिए पीआईडी .

SIGUSR1 सिग्नल हैंडलर उदाहरण

#शामिल
#शामिल

शून्यsig_handler(NSसंकेत){
printf ('हैंडलर फ़ंक्शन के अंदर'एन');
}

NSमुख्य(){
संकेत(सिगुसर1,sig_handler); // रजिस्टर सिग्नल हैंडलर
printf ('मुख्य समारोह के अंदर'एन');
चढ़ाई (सिगुसर1);
printf ('मुख्य समारोह के अंदर'एन');
वापसी 0;
}

यहां, प्रक्रिया raise() फ़ंक्शन का उपयोग करके स्वयं को SIGUSR1 सिग्नल भेजती है।

किल उदाहरण कार्यक्रम के साथ उठाएँ

#शामिल
#शामिल
#शामिल
शून्यsig_handler(NSसंकेत){
printf ('हैंडलर फ़ंक्शन के अंदर'एन');
}

NSमुख्य(){
pid_t pid;
संकेत(सिगुसर1,sig_handler); // रजिस्टर सिग्नल हैंडलर
printf ('मुख्य समारोह के अंदर'एन');
पीआईडी=गेटपीड(); // स्वयं की प्रक्रिया आईडी
मार(पीआईडी,सिगुसर1); // खुद को SIGUSR1 भेजें
printf ('मुख्य समारोह के अंदर'एन');
वापसी 0;
}

यहां, प्रक्रिया भेजें सिगुसर1 खुद के लिए संकेत का उपयोग कर मारो () समारोह। गेटपिड () स्वयं की प्रक्रिया आईडी प्राप्त करने के लिए उपयोग किया जाता है।

अगले उदाहरण में हम देखेंगे कि माता-पिता और बच्चे की प्रक्रिया कैसे संचार करती है (इंटर प्रोसेस कम्युनिकेशन) का उपयोग करके मारो () और संकेत समारोह।

संकेतों के साथ अभिभावक बाल संचार

#शामिल
#शामिल
#शामिल
#शामिल
शून्यsig_handler_parent(NSसंकेत){
printf ('माता-पिता: बच्चे से प्रतिक्रिया संकेत प्राप्त हुआ'एन');
}

शून्यsig_handler_child(NSसंकेत){
printf ('बच्चा: माता-पिता से संकेत मिला'एन');
नींद(1);
मार(गेटपीड(),सिगुसर1);
}

NSमुख्य(){
pid_t pid;
अगर((पीआईडी=कांटा())<0){
printf ('कांटा विफल'एन');
बाहर जाएं (1);
}
/* बाल प्रक्रिया */
अन्यथा अगर(पीआईडी==0){
संकेत(सिगुसर1,sig_handler_child); // रजिस्टर सिग्नल हैंडलर
printf ('बच्चा: सिग्नल की प्रतीक्षा में'एन');
ठहराव();
}
/* मूल प्रक्रिया */
अन्यथा{
संकेत(सिगुसर1,sig_handler_parent); // रजिस्टर सिग्नल हैंडलर
नींद(1);
printf ('माता-पिता: बच्चे को सिग्नल भेजना'एन');
मार(पीआईडी,सिगुसर1);
printf ('माता-पिता: प्रतिक्रिया की प्रतीक्षा कर रहा है'एन');
ठहराव();
}
वापसी 0;
}

यहां, कांटा() फ़ंक्शन चाइल्ड प्रोसेस बनाता है और चाइल्ड प्रोसेस में ज़ीरो लौटाता है और चाइल्ड प्रोसेस आईडी पैरेंट प्रोसेस में। तो, माता-पिता और बच्चे की प्रक्रिया तय करने के लिए pid की जाँच की गई है। मूल प्रक्रिया में, यह 1 सेकंड के लिए सोया जाता है ताकि बाल प्रक्रिया सिग्नल हैंडलर फ़ंक्शन को पंजीकृत कर सके और माता-पिता से सिग्नल की प्रतीक्षा कर सके। 1 सेकंड की मूल प्रक्रिया के बाद भेजें सिगुसर1 बच्चे की प्रक्रिया को संकेत और बच्चे से प्रतिक्रिया संकेत की प्रतीक्षा करें। चाइल्ड प्रोसेस में, पहले यह पैरेंट से सिग्नल की प्रतीक्षा कर रहा है और जब सिग्नल प्राप्त होता है, तो हैंडलर फ़ंक्शन को लागू किया जाता है। हैंडलर फ़ंक्शन से, चाइल्ड प्रोसेस दूसरे को भेजती है सिगुसर1 माता-पिता को संकेत। यहां गेटपीड () फ़ंक्शन का उपयोग मूल प्रक्रिया आईडी प्राप्त करने के लिए किया जाता है।

निष्कर्ष

Linux में Signal एक बड़ा विषय है। इस लेख में हमने देखा है कि सिग्नल को बहुत बुनियादी से कैसे हैंडल किया जाता है, और यह भी ज्ञान प्राप्त किया जाता है कि सिग्नल कैसे उत्पन्न होता है, कैसे एक प्रक्रिया खुद को और अन्य प्रक्रिया को सिग्नल भेज सकती है, इंटर-प्रोसेस संचार के लिए सिग्नल का उपयोग कैसे किया जा सकता है।