C Language
सिग्नल से निपटने
खोज…
वाक्य - विन्यास
- void (* सिग्नल (int sig, void (* func) (int))) (int);
पैरामीटर
पैरामीटर | विवरण |
---|---|
sig | संकेत करने के लिए संकेत हैंडलर, में से एक स्थापित करने के लिए SIGABRT , SIGFPE , SIGILL , SIGTERM , SIGINT , SIGSEGV या कुछ कार्यान्वयन निर्धारित मान |
समारोह | संकेत हैंडलर, जो निम्न में से या तो है: SIG_DFL , डिफ़ॉल्ट हैंडलर के लिए, SIG_IGN संकेत, या हस्ताक्षर के साथ एक समारोह सूचक की अनदेखी करने के void foo(int sig); । |
टिप्पणियों
केवल सी मानक से गारंटी के साथ सिग्नल हैंडलर का उपयोग विभिन्न सीमाएं लगाता है जो उपयोगकर्ता द्वारा परिभाषित सिग्नल हैंडलर में नहीं किया जा सकता है या नहीं किया जा सकता है।
यदि उपयोगकर्ता परिभाषित फ़ंक्शन
SIGSEGV
,SIGFPE
,SIGILL
या किसी अन्य कार्यान्वयन-परिभाषित हार्डवेयर व्यवधान को हैंडल करते समय वापस लौटता है, तो व्यवहार C मानक द्वारा अपरिभाषित है। ऐसा इसलिए है क्योंकि C का इंटरफ़ेस दोषपूर्ण स्थिति को बदलने का साधन नहीं देता है (जैसे0
विभाजन के बाद) और इस प्रकार जब प्रोग्राम लौटाता है तो हार्डवेयर गड़बड़ी होने से पहले की तुलना में बिल्कुल गलत स्थिति में है।यदि उपयोगकर्ता परिभाषित फ़ंक्शन की कॉल का परिणाम के रूप में बुलाया गया था
abort
, याraise
, संकेत हैंडलर कॉल करने के लिए अनुमति नहीं हैraise
, फिर से।सिग्नल किसी भी ऑपरेशन के बीच में आ सकते हैं, और इसलिए ऑपरेशन की अविभाज्यता आमतौर पर गारंटी नहीं दे सकती है और न ही सिग्नल हैंडलिंग अनुकूलन के साथ अच्छी तरह से काम करती है। इसलिए सिग्नल हैंडलर में डेटा के सभी संशोधन चर के लिए होने चाहिए
- प्रकार के
sig_atomic_t
(सभी संस्करण) या एक लॉक-फ्री परमाणु प्रकार (C11 के बाद से, वैकल्पिक) - कि
volatile
योग्य हैं।
- प्रकार के
सी मानक पुस्तकालय से अन्य कार्य आमतौर पर इन प्रतिबंधों का सम्मान नहीं करेंगे, क्योंकि वे कार्यक्रम की वैश्विक स्थिति में चर बदल सकते हैं। C मानक केवल
abort
लिए गारंटी देता है,_Exit
(C99 के बाद से),quick_exit
(C11 के बाद से),signal
(समान संकेत संख्या के लिए), और कुछ परमाणु संचालन (C11 के बाद से)।
यदि ऊपर दिए गए किसी भी नियम का उल्लंघन किया गया तो व्यवहार C मानक द्वारा अपरिभाषित है। प्लेटफ़ॉर्म में विशिष्ट एक्सटेंशन हो सकते हैं, लेकिन ये आमतौर पर उस प्लेटफॉर्म से परे पोर्टेबल नहीं होते हैं।
आमतौर पर सिस्टम में कार्यों की अपनी सूची होती है जो एसिंक्रोनस सिग्नल सुरक्षित होते हैं , यह सी लाइब्रेरी फ़ंक्शन का होता है जो सिग्नल हैंडलर से उपयोग किया जा सकता है। जैसे अक्सर
printf
इन फंक्शन के बीच होता है।विशेष रूप से C मानक अपने थ्रेड इंटरफ़ेस (C11 के बाद से) या किसी भी प्लेटफ़ॉर्म विशिष्ट थ्रेड लाइब्रेरी जैसे POSIX थ्रेड्स के साथ सहभागिता के बारे में अधिक परिभाषित नहीं करता है। ऐसे प्लेटफार्मों को स्वयं द्वारा संकेतों के साथ इस तरह के थ्रेड लाइब्रेरी की बातचीत को निर्दिष्ट करना होगा।
"सिग्नल" () के साथ सिग्नल हैंडलिंग
सिग्नल संख्या सिंक्रोनस (जैसे SIGSEGV
- विभाजन दोष) हो सकती है जब वे प्रोग्राम के एक खराबी या ट्रिगर (जैसे SIGINT
- इंटरैक्टिव ध्यान) द्वारा प्रोग्राम के बाहर शुरू होने पर ट्रिगर होते हैं, जैसे कि Cntrl-C
रूप में एक keypress द्वारा।
signal()
फ़ंक्शन आईएसओ सी मानक का हिस्सा है और किसी विशिष्ट सिग्नल को संभालने के लिए फ़ंक्शन को असाइन करने के लिए उपयोग किया जा सकता है
#include <stdio.h> /* printf() */
#include <stdlib.h> /* abort() */
#include <signal.h> /* signal() */
void handler_nonportable(int sig)
{
/* undefined behavior, maybe fine on specific platform */
printf("Catched: %d\n", sig);
/* abort is safe to call */
abort();
}
sig_atomic_t volatile finished = 0;
void handler(int sig)
{
switch (sig) {
/* hardware interrupts should not return */
case SIGSEGV:
case SIGFPE:
case SIGILL:
/* quick_exit is safe to call */
quick_exit(EXIT_FAILURE);
/* use _Exit in pre-C11 */
_Exit(EXIT_FAILURE);
default:
/* Reset the signal to the default handler,
so we will not be called again if things go
wrong on return. */
signal(sig, SIG_DFL);
/* let everybody know that we are finished */
finished = sig;
return;
}
}
int main(void)
{
/* Catch the SIGSEGV signal, raised on segmentation faults (i.e NULL ptr access */
if (signal(SIGSEGV, &handler) == SIG_ERR) {
perror("could not establish handler for SIGSEGV");
return EXIT_FAILURE;
}
/* Catch the SIGTERM signal, termination request */
if (signal(SIGTERM, &handler) == SIG_ERR) {
perror("could not establish handler for SIGTERM");
return EXIT_FAILURE;
}
/* Ignore the SIGINT signal, by setting the handler to `SIG_IGN`. */
signal(SIGINT, SIG_IGN);
/* Do something that takes some time here, and leaves
the time to terminate the program from the keyboard. */
/* Then: */
if (finished) {
fprintf(stderr, "we have been terminated by signal %d\n", (int)finished);
return EXIT_FAILURE;
}
/* Try to force a segmentation fault, and raise a SIGSEGV */
{
char* ptr = 0;
*ptr = 0;
}
/* This should never be executed */
return EXIT_SUCCESS;
}
signal()
का उपयोग करना महत्वपूर्ण सीमाएं लगाता है जो आपको सिग्नल हैंडलर के अंदर करने की अनुमति है, आगे की जानकारी के लिए टिप्पणी देखें।
POSIX signal()
sigaction()
बजाय sigaction()
के उपयोग की सिफारिश करता है, इसके अंडरस्क्राइब किए गए व्यवहार और महत्वपूर्ण कार्यान्वयन भिन्नताओं के कारण। POSIX भी ISO C मानक की तुलना में SIGUSR1
और SIGUSR2
सहित कई और संकेतों को परिभाषित करता है, जिन्हें किसी भी उद्देश्य के लिए प्रोग्रामर द्वारा स्वतंत्र रूप से उपयोग किया जा सकता है।