2008-10-23 17 views
104

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

उत्तर

124

sigaction() का उपयोग करें जब तक कि आपको ऐसा करने के लिए बहुत ही आकर्षक कारण नहीं मिलते हैं।

signal() इंटरफ़ेस में इसके पक्ष में पुरातनता (और इसलिए उपलब्धता) है, और इसे सी मानक में परिभाषित किया गया है। फिर भी, इसमें कई अवांछनीय विशेषताएं हैं जो sigaction() avoids - जब तक आप sigaction() में स्पष्ट रूप से जोड़े गए झंडे का उपयोग नहीं करते हैं, ताकि यह पुराने signal() व्यवहार को ईमानदारी से अनुकरण करने की अनुमति दे सके।

  1. signal() फ़ंक्शन वर्तमान हैंडलर निष्पादित होने पर आने वाले अन्य संकेतों को अवरुद्ध नहीं करता है (आवश्यक); sigaction() वर्तमान हैंडलर रिटर्न तक अन्य संकेतों को अवरुद्ध कर सकता है।
  2. signal() फ़ंक्शन (आमतौर पर) सिग्नल एक्शन को लगभग सभी सिग्नल के लिए SIG_DFL (डिफ़ॉल्ट) पर रीसेट करता है। इसका मतलब है कि signal() हैंडलर को अपनी पहली क्रिया के रूप में खुद को पुनर्स्थापित करना होगा। यह उस समय के बीच भेद्यता की एक खिड़की भी खुलता है जब सिग्नल का पता लगाया जाता है और हैंडलर को पुनर्स्थापित किया जाता है जिसके दौरान सिग्नल का दूसरा उदाहरण आता है, डिफ़ॉल्ट व्यवहार (आमतौर पर समाप्त होता है, कभी-कभी पूर्वाग्रह - उर्फ ​​कोर डंप के साथ) होता है।
  3. signal() का सटीक व्यवहार सिस्टम के बीच भिन्न होता है - और मानक उन भिन्नताओं को अनुमति देते हैं।

के बजाय sigaction() का उपयोग करने के लिए ये आमतौर पर अच्छे कारण हैं। हालांकि, sigaction() का इंटरफ़ेस निर्विवाद रूप से अधिक स्पष्ट रूप से है।

दो आपके द्वारा उपयोग की जो भी, जैसे sighold(), sigignore(), sigpause() और sigrelse() विकल्प संकेत इंटरफेस द्वारा की कोशिश नहीं करते। वे sigaction() के नाममात्र विकल्प हैं, लेकिन वे केवल मुश्किल से मानक हैं और गंभीर उपयोग के बजाए पीछे की संगतता के लिए पॉज़िक्स में मौजूद हैं। ध्यान दें कि POSIX मानक का कहना है कि बहु-थ्रेडेड प्रोग्रामों में उनका व्यवहार अपरिभाषित है।

बहु थ्रेडेड प्रोग्राम और संकेत एक अन्य जटिल कहानी है। AFAIK, signal() और sigaction() दोनों बहु-थ्रेडेड अनुप्रयोगों में ठीक हैं।

Cornstalksobserves:

signal() के लिए लिनक्स आदमी पृष्ठ बताता है: एक मल्टी-थ्रेडेड प्रक्रिया में signal() की

  प्रभाव अनिर्दिष्ट हैं।

इस प्रकार, मुझे लगता है कि sigaction() एकमात्र ऐसा है जिसे बहु-थ्रेडेड प्रक्रिया में सुरक्षित रूप से उपयोग किया जा सकता है।

यह दिलचस्प है। इस मामले में लिनक्स मैनुअल पेज POSIX से अधिक प्रतिबंधित है। POSIX signal() के लिए निर्दिष्ट करता है:

  • प्रक्रिया abort() बुला:

    तो प्रक्रिया मल्टी-थ्रेडेड है, या यदि प्रक्रिया एकल पिरोया है और एक संकेत हैंडलर अन्य की तुलना में के परिणाम के रूप निष्पादित किया जाता है , raise(), kill(), pthread_kill(), या sigqueue() एक संकेत है कि अवरुद्ध नहीं कर रहा है

  • एक लंबित संकेत का अवरोध हटा जा रहा है और कॉल कि अवरोध हटा यह रिटर्न
  • से पहले वितरित की जा रही उत्पन्न करने के लिए 10

व्यवहार करता है, तो संकेत हैंडलर एक वस्तु volatile sig_atomic_t के रूप में घोषित करने के लिए एक मूल्य बताए द्वारा की तुलना में स्थिर भंडारण अन्य अवधि के साथ errno के अलावा अन्य किसी भी वस्तु को संदर्भित करता है अपरिभाषित है, संकेत हैंडलर किसी भी समारोह इस मानक अन्य में परिभाषित कॉल या अगर Signal Concepts में सूचीबद्ध कार्यों में से एक से अधिक।

तो पॉज़िक्स स्पष्ट रूप से बहु-थ्रेडेड एप्लिकेशन में signal() के व्यवहार को स्पष्ट रूप से निर्दिष्ट करता है।

फिर भी, sigaction() अनिवार्य रूप से सभी परिस्थितियों में पसंद किया जा रहा है - और जब तक कि वहाँ एक भारी कारण नहीं है पोर्टेबल मल्टी-थ्रेडेड कोड sigaction() का उपयोग करना चाहिए क्यों यह नहीं कर सकते हैं (जैसे कि "केवल उपयोग कार्यों स्टैंडर्ड सी द्वारा परिभाषित" - और हाँ , सी 11 कोड बहु थ्रेडेड हो सकता है)। जो मूल रूप से इस उत्तर का उद्घाटन अनुच्छेद भी कहता है।

+9

'सिग्नल' का यह विवरण वास्तव में यूनिक्स सिस्टम वी व्यवहार का है। पीओएसईक्स या तो इस व्यवहार या बहुत अधिक बीएसडी व्यवहार की अनुमति देता है, लेकिन चूंकि आप यह सुनिश्चित नहीं कर सकते कि आपको कौन सा मिल जाएगा, यह अभी भी 'सिग्नेक्शन' का उपयोग करना सबसे अच्छा है। –

+1

जब तक आप पुराने सिग्नल() व्यवहार को ईमानदारी से अनुकरण करने की अनुमति देने के लिए सिग्नेशन() में स्पष्ट रूप से जोड़े गए झंडे का उपयोग नहीं करते हैं। वे क्या झंडे (निर्दिष्ट) होगा? – ChristianCuevas

+0

@AlexFritz: मुख्य रूप से 'SA_RESETHAND',' SA_NODEFER' भी। –

2

मैं सिग्नल() का उपयोग करता हूं क्योंकि यह कम से कम सिद्धांत में अधिक पोर्टेबल है। मैं किसी भी टिप्पणीकर्ता को वोट दूंगा जो आधुनिक प्रणाली के साथ आ सकता है जिसमें POSIX संगतता परत नहीं है और सिग्नल() का समर्थन करता है।

GLIBC documentation से हवाला देते हुए:

यह एक भी कार्यक्रम के भीतर दोनों संकेत और sigaction कार्यों का उपयोग करने के लिए संभव है, लेकिन आप क्योंकि वे थोड़ा अजीब तरीके में बातचीत कर सकते हैं सावधान रहना होगा।

sigaction समारोह संकेत समारोह की तुलना में अधिक जानकारी निर्दिष्ट करता है, तो संकेत से वापसी मान sigaction संभावनाओं से भरा रेंज व्यक्त नहीं कर सकते। इसलिए, यदि आप पर सिग्नल का उपयोग करते हैं और बाद में एक क्रिया को पुन: स्थापित करते हैं, तो यह को सिग्नेक्शन के साथ स्थापित एक हैंडलर को ठीक से स्थापित नहीं कर सकता है।

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

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

तो, आप एक या दूसरे तंत्र को लगातार एक प्रोग्राम के भीतर उपयोग करने से बेहतर हैं।

पोर्टेबिलिटी नोट: मूल सिग्नल फ़ंक्शन आईएसओ सी, की एक विशेषता है जबकि सिग्नेशन POSIX.1 मानक का हिस्सा है। यदि आप गैर-पॉज़िक्स सिस्टम के पोर्टेबिलिटी के बारे में चिंतित हैं, तो आपको इसके बजाय सिग्नल फ़ंक्शन का उपयोग करना चाहिए।

कॉपीराइट (सी) 1996-2008 फ्री सॉफ्टवेयर फाउंडेशन, Inc

अनुमति, कॉपी वितरित और/या GNU Free Documentation License की शर्तों के तहत इस दस्तावेज़ को संशोधित करने के प्रदान किया जाता है, संस्करण 1.2 या फ्री सॉफ्टवेयर फाउंडेशन द्वारा प्रकाशित किसी भी बाद के संस्करण; कोई इनवेरिएंट सेक्शन नहीं, बिना फ्रंट-कवर टेक्स्ट्स, और बिना बैक-कवर टेक्स्ट्स के। "जीएनयू मुक्त दस्तावेज़ीकरण लाइसेंस" नामक अनुभाग में लाइसेंस की एक प्रति में शामिल है।

2

signal(3) आदमी पृष्ठ से:

वर्णन

This signal() facility is a simplified interface to the more 
general sigaction(2) facility. 

दोनों एक ही अंतर्निहित सुविधा आह्वान। आपको संभवतः दोनों के साथ एक सिग्नल प्रतिक्रिया में हेरफेर नहीं करना चाहिए, लेकिन उन्हें मिलाकर कुछ भी तोड़ने का कारण नहीं बनना चाहिए ...

+0

यह मेरे मैन पेज में नहीं है! मुझे बस इतना मिलता है "वर्णन सिग्नल() सिस्टम कॉल सिग्नल के लिए सिग्नल के लिए एक नया सिग्नल हैंडलर स्थापित करता है।" मुझे _useful_ मैन पेज पैकेज में अपग्रेड करना होगा। – MattSmith

+1

यह मैक ओएस एक्स 10.5 पृष्ठों से बाहर है। – dmckee

+0

भी glibc के स्रोत कोड से सत्यापित किया गया। सिग्नल() सिग्नेशन को कॉल करता है() – bmdhacks

5

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

विवरण के लिए यह security note देखें।

+0

मैंने अभी glibc स्रोत कोड और सिग्नल() को देखा है सिग्नेशन() में बस कॉल करता है। ऊपर भी देखें जहां मैकोज़ मैन पेज का दावा है। – bmdhacks

+0

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

4

मेरे लिए, यह नीचे लाइन तय करने के लिए पर्याप्त था:

sigaction() फ़ंक्शन एक अधिक व्यापक और विश्वसनीय संकेतों को नियंत्रित करने के लिए तंत्र प्रदान करता है; नई अनुप्रयोगों sigaction() बजाय संकेत()

http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html#tag_03_690_07

का उपयोग करना चाहिए आप स्क्रैच से शुरू करने या एक पुराने कार्यक्रम को संशोधित कर रहे हैं, sigaction सही विकल्प होना चाहिए।

1

सिग्नल() मानक सी है, सिग्नेशन() नहीं है।

यदि आप या तो उपयोग करने में सक्षम हैं (यानी, आप एक पॉज़िक्स सिस्टम पर हैं), तो सिग्नेशन() का उपयोग करें; यह निर्दिष्ट नहीं है कि सिग्नल() हैंडलर रीसेट करता है, जिसका अर्थ है कि पोर्टेबल होने के लिए आपको हैंडलर के अंदर सिग्नल() को फिर से कॉल करना होगा। इससे भी बदतर यह है कि एक दौड़ है: यदि आपको त्वरित उत्तराधिकार में दो सिग्नल मिलते हैं, और दूसरे को हैंडलर को पुनर्स्थापित करने से पहले वितरित किया जाता है, तो आपके पास डिफ़ॉल्ट कार्रवाई होगी, जो शायद आपकी प्रक्रिया को मारने जा रही है। सिग्नेक्शन(), दूसरी तरफ, "विश्वसनीय" सिग्नल अर्थशास्त्र का उपयोग करने की गारंटी है। आपको हैंडलर को पुनर्स्थापित करने की आवश्यकता नहीं है, क्योंकि इसे कभी भी रीसेट नहीं किया जाएगा। SA_RESTART के साथ, आप स्वचालित रूप से पुनरारंभ करने के लिए कुछ सिस्टम कॉल भी प्राप्त कर सकते हैं (इसलिए आपको मैन्युअल रूप से EINTR की जांच करने की आवश्यकता नहीं है)। सिग्नेक्शन() में अधिक विकल्प हैं और विश्वसनीय है, इसलिए इसका उपयोग प्रोत्साहित किया जाता है।

Psst ... किसी को भी यह न बताएं कि मैंने आपको यह बताया है, लेकिन POSIX में वर्तमान में एक कार्य bsd_signal() है जो सिग्नल() की तरह कार्य करता है लेकिन बीएसडी अर्थशास्त्र देता है, जिसका अर्थ यह विश्वसनीय है। इसका मुख्य उपयोग पुराने अनुप्रयोगों को पोर्ट करने के लिए है जो विश्वसनीय संकेतों को मानते हैं, और POSIX इसका उपयोग करने की अनुशंसा नहीं करता है।

1

मैं संकेत() पर सिग्नेशन() का उपयोग करने का भी सुझाव दूंगा और एक और बिंदु जोड़ना चाहता हूं। सिग्नेक्शन() आपको अधिक विकल्प देता है जैसे प्रक्रिया की पिड जो मर गई (संभवतः siginfo_t संरचना का उपयोग कर)।