इसके अलावा alk's answer रहे हैं:
आप एक प्रति-धागा समारोह का उपयोग कर सकते एक निश्चित सिग्नल वितरित होने पर, प्रति-थ्रेड तरीके से, कौन सा फ़ंक्शन निष्पादित किया जाता है, यह चुनने के लिए सूचक।
नोट: सिग्नल पर धागा वितरित किए जाते हैं जो स्पष्ट रूप से इसकी डिलीवरी को अवरुद्ध नहीं कर रहा है। यह उसमें बदलाव नहीं करता है। आपको अभी भी pthread_kill()
या सिग्नल को एक विशिष्ट थ्रेड पर निर्देशित करने के लिए समान तंत्र का उपयोग करने की आवश्यकता है; सिग्नल जो उठाए जाते हैं या प्रक्रिया में भेजे जाते हैं (एक विशिष्ट थ्रेड के बजाए), अभी भी एक यादृच्छिक धागे द्वारा नियंत्रित किए जाएंगे (उनमें से जो इसे अवरुद्ध नहीं करते हैं)।
मैं किसी भी उपयोग के मामले के बारे में नहीं सोच सकता जहां मैं व्यक्तिगत रूप से इस दृष्टिकोण को प्राथमिकता दूंगा; इस प्रकार अब तक कुछ और तरीका रहा है, कुछ और आसान और बेहतर है।इसलिए, यदि आप वास्तविक एप्लिकेशन के लिए ऐसा कुछ लागू करने पर विचार कर रहे हैं, तो कृपया वापस जाएं और अपने एप्लिकेशन तर्क पर पुनर्विचार करें।
लेकिन, के बाद से तकनीक संभव है, यहाँ मैं इसे कैसे लागू हो सकता है:
#include <signal.h>
/* Per-thread signal handler function pointer.
* Always use set_thread_SIG_handler() to change this.
*/
static __thread void (*thread_SIG_handler)(int, siginfo_t *, void *) = (void *)0;
/* Process-wide signal handler.
*/
static void process_SIG_handler(int signum, siginfo_t *info, void *context)
{
void (*func)(int, siginfo_t *, void *);
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
func = __atomic_load_n(&thread_SIG_handler, __ATOMIC_SEQ_CST);
#else
func = __sync_fetch_and_add(&thread_SIG_handler, (void *)0);
#endif
if (func)
func(signum, info, context);
}
/* Helper function to set new per-thread signal handler
*/
static void set_thread_SIG_handler(void (*func)(int, siginfo_t *, void *))
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
__atomic_store_n(&thread_SIG_handler, func, __ATOMIC_SEQ_CST);
#else
void (*oldfunc)(int, siginfo_t *, void *);
do {
oldfunc = thread_SIG_handler;
} while (!__sync_bool_compare_and_swap(&thread_SIG_handler, oldfunc, func));
#endif
}
/* Install the process-wide signal handler.
*/
int install_SIG_handlers(const int signum)
{
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_sigaction = process_SIG_handler;
act.sa_flags = SA_SIGACTION;
if (sigaction(signum, &act, NULL))
return errno;
return 0;
}
मैं ऊपर की तरह है, क्योंकि यह pthreads की आवश्यकता नहीं है, और बहुत मजबूत और विश्वसनीय है। उस प्रीप्रोसेसर तर्क के कारण दृश्य गड़बड़ी के अलावा, परमाणु बिल्ट-इन्स की कौन सी शैली का चयन किया जाता है, यह बहुत आसान है, अगर आप इसे ध्यान से देखते हैं।
जीसीसी 4.7 और बाद में सी ++ 11-जैसे __atomic built-ins, पुराने जीसीसी संस्करण और अन्य कंपाइलर्स (आईसीसी, पाथस्केल, पोर्टलैंड समूह) प्रदान करते हैं __sync legacy built-ins प्रदान करते हैं। थ्रेड-लोकल स्टोरेज के लिए __thread
keyword समान रूप से सभी मौजूदा POSIX-y सिस्टम में उपलब्ध होना चाहिए।
#include <pthread.h>
#include <signal.h>
#include <errno.h>
static pthread_key_t thread_SIG_handler_key;
static void process_SIG_handler(int signum, siginfo_t *info, void *context)
{
void (*func)(int, siginfo_t *, void *);
*((void **)&func) = pthread_getspecific(thread_SIG_handler_key);
if (func)
func(signum, info, context);
}
static int set_thread_SIG_handler(void (*func)(int, siginfo_t *, void *))
{
sigset_t block, old;
int result;
sigemptyset(&block);
sigaddset(&block, SIG); /* Use signal number instead of SIG! */
result = pthread_sigmask(SIG_BLOCK, &block, &old);
if (result)
return errno = result;
result = pthread_setspecific(thread_SIG_handler_key, (void *)func);
if (result) {
pthread_sigmask(SIG_SETMASK, &old, NULL);
return errno = result;
}
result = pthread_sigmask(SIG_SETMASK, &old, NULL);
if (result)
return errno = result;
return 0;
}
int install_SIG_handlers(const int signum)
{
struct sigaction act;
int result;
result = pthread_key_create(&thread_SIG_handler_key, NULL);
if (result)
return errno = result;
sigemptyset(&act.sa_mask);
act.sa_sigaction = process_SIG_handler;
act.sa_flags = SA_SIGACTION;
if (sigaction(signum, &act, NULL))
return errno;
return 0;
}
मुझे लगता है कि इस तरह से कोड करने के लिए निकटतम वास्तविक जीवन बराबर है कि मैं वास्तव कर दिया है:
आप एक प्राचीन प्रणाली है, या मानक अनुपालन पर जोर देते हैं, तो निम्न कोड बराबर व्यवहार करना चाहिए था कभी भी इस्तेमाल किया जाता है, वह एक है जहां मैंने एक रीयलटाइम सिग्नल (SIGRTMIN+0
) को एक थ्रेड के रूप में अवरुद्ध किया है, एक परावर्तक के रूप में: यह अवरोधक I/O को बाधित करने के लिए, कई कार्यकर्ता थ्रेडों में एक और रीयलटाइम सिग्नल (SIGRTMIN+1
) भेजा गया है। (यह एक वास्तविक समय संकेत के साथ ऐसा करना संभव है, लेकिन दो संकेत मॉडल को लागू करने और आसान करने के लिए बनाए रखने के लिए आसान है।)
इस तरह के संकेत प्रतिबिंब या फैनआउट कभी कभी उपयोगी है, और यह से अलग नहीं है यह दृष्टिकोण। अपने स्वयं के प्रश्न की गारंटी देने के लिए काफी अलग, हालांकि, अगर कोई दिलचस्पी लेता है।
सिग्नल प्रति प्रक्रिया कॉल है, प्रति थ्रेड एक नहीं, अगर आप इसे कॉल करते हैं तो यह प्रक्रिया में सभी धागे के लिए हैंडलर सेट करता है। संकेत और धागे एक जटिल विषय है। आप वास्तव में क्या करना चाहते हैं इसके बारे में पूछने से बेहतर हो सकता है। –
एक बहुप्रचारित कार्यक्रम में 'सिग्नल' का उपयोग करना अनिवार्य रूप से अपरिभाषित व्यवहार है। यह मैनुअल में ऐसा कहता है। –
स्रोत कोड कृपया। –