सिग्नल आंतरिक रूप से कैसे काम करते हैं?


31

सामान्य तौर पर, प्रक्रियाओं को मारने के लिए हम जैसे सिग्नल उत्पन्न करते हैं SIGKILL, SIGTSTPआदि।

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


प्रश्न को समझना थोड़ा कठिन है। मैं माफी मांगता हूं और कोई अपमान नहीं करता। क्या आप जानना चाहते हैं कि कौन एक कमांड चला सकता है जिसने एक प्रक्रिया को मार दिया है या क्या आप SIGKILL और SIGSTP के बारे में अधिक जानना चाहते हैं?
पुलसुमो

@ मिस्टरमिस्टर मैं जानना चाहता हूं कि एक कमांड को किसने चलाया होगा जिसने एक प्रक्रिया को मार दिया और कैसे?
वरुण छंगाणी

जवाबों:


35

50,000 फुट का दृश्य है:

  1. एक संकेत या तो कर्नेल द्वारा आंतरिक रूप से उत्पन्न किया जाता है (उदाहरण के लिए, SIGSEGVजब एक अवैध पते तक पहुँचा जाता है, या SIGQUITजब आप हिट करते हैं Ctrl+ \), या एक प्रोग्राम द्वारा killsyscall (या कई संबंधित) का उपयोग करके ।

  2. यदि यह syscalls में से एक है, तो कर्नेल कॉलिंग प्रक्रिया की पुष्टि करता है कि सिग्नल भेजने के लिए पर्याप्त विशेषाधिकार हैं। यदि नहीं, तो एक त्रुटि लौटा दी जाती है (और संकेत नहीं होता है)।

  3. यदि यह दो विशेष संकेतों में से एक है, तो कर्नेल बिना किसी इनपुट के लक्ष्य प्रक्रिया से बिना किसी शर्त के उस पर कार्य करता है। दो विशेष संकेत SIGKILL और SIGSTOP हैं। डिफ़ॉल्ट क्रियाओं, अवरुद्ध संकेतों आदि के बारे में नीचे दिए गए सभी सामान इन दोनों के लिए अप्रासंगिक हैं।

  4. इसके बाद, कर्नेल ने संकेत के साथ क्या किया है:

    1. प्रत्येक प्रक्रिया के लिए, प्रत्येक सिग्नल से जुड़ी एक क्रिया होती है। चूक का एक समूह रहे हैं, और कार्यक्रमों अलग लोगों का उपयोग कर सेट कर सकते हैं sigaction, signalआदि ये "यह पूरी तरह से उपेक्षा", "प्रक्रिया को मारने के", "एक कोर डंप के साथ प्रक्रिया को मारने के", "प्रक्रिया को रोकने के" जैसी चीजों में शामिल हैं, आदि।

    2. सिग्नल-बाय-सिग्नल के आधार पर प्रोग्राम सिग्नल की डिलीवरी ("अवरुद्ध") को बंद भी कर सकते हैं। तब सिग्नल अनब्लॉक होने तक लंबित रहता है।

    3. प्रोग्राम अनुरोध कर सकते हैं कि कर्नेल के बजाय कुछ कार्रवाई खुद करने के लिए, यह सिग्नल को या तो तुल्यकालिक रूप से (साथ sigwait, एट अल। signalfd) या असिंक्रोनस (प्रक्रिया जो भी कर रही है, और एक निर्दिष्ट फ़ंक्शन को कॉल करके) को संकेत प्रदान करता है ।

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

गैर-50,000 फुट दृश्य के लिए, man 7 signalकर्नेल इंटर्नल डॉक्यूमेंटेशन (या स्रोत) को भी आज़माएँ ।


"दो विशेष संकेत SIGKILL और SIGSTOP हैं" तो SIGCONT क्या हो सकता है ...
Hauke ​​Laging

@HaLLaging SIGCONT सिग्नल है जो SIGSTOP को अनडू करता है। प्रलेखन इसे विशेष के रूप में सूचीबद्ध नहीं करता है ... इसलिए मुझे यकीन नहीं है कि यदि तकनीकी रूप से एक प्रक्रिया इसे अनदेखा कर सकती है, तो आप इसे फिर से शुरू नहीं कर पाएंगे (केवल इसे ही)।
व्युत्पन्न

22

सिग्नल कार्यान्वयन बहुत जटिल है और कर्नेल विशिष्ट है। दूसरे शब्दों में, विभिन्न गुठली संकेतों को अलग तरीके से लागू करेगी। एक सरलीकृत स्पष्टीकरण इस प्रकार है:

सीपीयू, एक विशेष रजिस्टर मूल्य के आधार पर, स्मृति में एक पता है जहां यह "इंटरप्ट डिस्क्रिप्टर टेबल" खोजने की उम्मीद करता है जो वास्तव में एक वेक्टर टेबल है। हर संभव अपवाद के लिए एक वेक्टर है, जैसे शून्य द्वारा विभाजन, या INT 3 (डीबग) की तरह जाल। जब सीपीयू अपवाद का सामना करता है तो यह झंडे और वर्तमान अनुदेश सूचक को स्टैक पर सहेजता है और फिर संबंधित वेक्टर द्वारा निर्दिष्ट पते पर कूदता है। लिनक्स में यह वेक्टर हमेशा कर्नेल में इंगित करता है, जहां एक अपवाद हैंडलर है। सीपीयू अब किया जाता है, और लिनक्स कर्नेल पर कब्जा कर लेता है।

ध्यान दें, कि आप सॉफ़्टवेयर से एक अपवाद को भी ट्रिगर कर सकते हैं। उदाहरण के लिए, उपयोगकर्ता दबाता है CTRL- Cफिर यह कॉल कर्नेल पर जाता है जो अपने स्वयं के अपवाद हैंडलर को कॉल करता है। सामान्य तौर पर, हैंडलर को प्राप्त करने के लिए अलग-अलग तरीके होते हैं, लेकिन परवाह किए बिना एक ही मूल बात होती है: संदर्भ स्टैक पर सहेजा जाता है और कर्नेल के अपवाद हैंडलर को कूद जाता है।

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

यह संकेत भेजने के लिए कि कर्नेल क्या करता है, पहले संकेत के प्रकार SIGHUPया जो कुछ भी हो , एक मूल्य निर्धारित किया जाता है । यह सिर्फ एक पूर्णांक है। प्रत्येक प्रक्रिया में एक "लंबित सिग्नल" मेमोरी क्षेत्र होता है जहां यह मान संग्रहीत होता है। फिर कर्नेल सिग्नल की जानकारी के साथ एक डेटा संरचना बनाता है। इस संरचना में एक संकेत "स्वभाव" शामिल है जो डिफ़ॉल्ट, अनदेखा या संभाल सकता है। कर्नेल तब अपने स्वयं के फ़ंक्शन को कॉल करता है do_signal()। अगला चरण शुरू होता है।

do_signal()पहले यह तय करता है कि यह सिग्नल को संभालेगा या नहीं । उदाहरण के लिए, यदि यह एक हत्या है , तो do_signal()बस प्रक्रिया को मारता है, कहानी का अंत। अन्यथा, यह विवाद को देखता है। यदि विवाद डिफ़ॉल्ट है, तो do_signal()सिग्नल पर निर्भर होने वाली डिफ़ॉल्ट नीति के अनुसार सिग्नल को संभालता है। यदि स्वभाव संभाल है, तो इसका मतलब है कि उपयोगकर्ता कार्यक्रम में एक फ़ंक्शन है जिसे प्रश्न में संकेत को संभालने के लिए डिज़ाइन किया गया है और इस फ़ंक्शन के लिए सूचक उपरोक्त डेटा संरचना में होगा। इस स्थिति में do_signal () दूसरे कर्नेल फ़ंक्शन को कॉल करता है,handle_signal(), जो तब उपयोगकर्ता मोड पर वापस जाने और इस फ़ंक्शन को कॉल करने की प्रक्रिया से गुजरता है। इस हैंडऑफ का विवरण बेहद जटिल है। जब आप फ़ंक्शन का उपयोग करते हैं तो आपके प्रोग्राम में यह कोड आमतौर पर आपके प्रोग्राम में स्वचालित रूप से लिंक हो जाता है signal.h

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


15

यद्यपि इस प्रश्न का उत्तर दिया गया है, मुझे लिनक्स कर्नेल में घटनाओं के एक विस्तृत प्रवाह को पोस्ट करने दें।
इसे पूरी तरह से लिनक्स पोस्ट्स से कॉपी किया जाता है : लिनक्स सिग्नल - "लिनक्स पोस्ट्स" ब्लॉग पर sklinuxblog.blogspot.in।

सिग्नल यूजर स्पेस सी प्रोग्राम

आइए एक साधारण सिग्नल यूजर स्पेस C प्रोग्राम लिखने के साथ शुरू करें:

#include<signal.h>
#include<stdio.h>

/* Handler function */
void handler(int sig) {
    printf("Receive signal: %u\n", sig);
};

int main(void) {
    struct sigaction sig_a;

    /* Initialize the signal handler structure */
    sig_a.sa_handler = handler;
    sigemptyset(&sig_a.sa_mask);
    sig_a.sa_flags = 0;

    /* Assign a new handler function to the SIGINT signal */
    sigaction(SIGINT, &sig_a, NULL);

    /* Block and wait until a signal arrives */
    while (1) {
            sigsuspend(&sig_a.sa_mask);
            printf("loop\n");
    }
    return 0;
};

यह कोड SIGINT सिग्नल के लिए एक नया हैंडलर प्रदान करता है। SIGINT को Ctrl+ Cकुंजी संयोजन का उपयोग करके रनिंग प्रक्रिया में भेजा जा सकता है । जब Ctrl+ Cदबाया जाता है तब एसिंक्रोनस सिग्नल SIGINT को कार्य पर भेजा जाता है। यह kill -INT <pid>अन्य टर्मिनल में कमांड भेजने के बराबर भी है ।

यदि आप एक करते हैं kill -l(यह एक लोअरकेस है L, जो "सूची" के लिए खड़ा है) तो आपको विभिन्न संकेतों के बारे में पता चलेगा जिन्हें एक चल रही प्रक्रिया में भेजा जा सकता है।

[root@linux ~]# kill -l
 1) SIGHUP        2) SIGINT        3) SIGQUIT       4) SIGILL        5) SIGTRAP
 6) SIGABRT       7) SIGBUS        8) SIGFPE        9) SIGKILL      10) SIGUSR1
11) SIGSEGV      12) SIGUSR2      13) SIGPIPE      14) SIGALRM      15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD      18) SIGCONT      19) SIGSTOP      20) SIGTSTP
21) SIGTTIN      22) SIGTTOU      23) SIGURG       24) SIGXCPU      25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF      28) SIGWINCH     29) SIGIO        30) SIGPWR
31) SIGSYS       34) SIGRTMIN     35) SIGRTMIN+1   36) SIGRTMIN+2   37) SIGRTMIN+3
38) SIGRTMIN+4   39) SIGRTMIN+5   40) SIGRTMIN+6   41) SIGRTMIN+7   42) SIGRTMIN+8
43) SIGRTMIN+9   44) SIGRTMIN+10  45) SIGRTMIN+11  46) SIGRTMIN+12  47) SIGRTMIN+13
48) SIGRTMIN+14  49) SIGRTMIN+15  50) SIGRTMAX-14  51) SIGRTMAX-13  52) SIGRTMAX-12
53) SIGRTMAX-11  54) SIGRTMAX-10  55) SIGRTMAX-9   56) SIGRTMAX-8   57) SIGRTMAX-7
58) SIGRTMAX-6   59) SIGRTMAX-5   60) SIGRTMAX-4   61) SIGRTMAX-3   62) SIGRTMAX-2
63) SIGRTMAX-1   64) SIGRTMAX

विशेष संकेतों को भेजने के लिए मुख्य संयोजन का उपयोग भी किया जा सकता है:

  • Ctrl+ C- SIGINT भेजता है जो डिफ़ॉल्ट क्रिया अनुप्रयोग को समाप्त करने के लिए है।
  • Ctrl+ \  - SIGQUIT को भेजता है कि कौन सी डिफॉल्ट कार्रवाई एप्लिकेशन डंपिंग कोर को समाप्त करना है।
  • Ctrl+ Z- SIGSTOP भेजता है जो कार्यक्रम को निलंबित करता है।

यदि आप उपरोक्त C प्रोग्राम को संकलित और चलाते हैं तो आपको निम्न आउटपुट प्राप्त होंगे:

[root@linux signal]# ./a.out
Receive signal: 2
loop
Receive signal: 2
loop
^CReceive signal: 2
loop

Ctrl+ के साथ भी Cया kill -2 <pid>प्रक्रिया समाप्त नहीं होगी। इसके बजाय यह सिग्नल हैंडलर को निष्पादित करेगा और वापस लौटेगा।

प्रक्रिया को सिग्नल कैसे भेजा जाता है

यदि हम सिग्नल के इंटर्नल को एक प्रक्रिया में भेजते हुए देखते हैं और Jprobe को डंप_स्टैक के साथ फ़ंक्शन पर रखते __send_signalहैं तो हम निम्नलिखित कॉल देखेंगे:

May  5 16:18:37 linux kernel: dump_stack+0x19/0x1b
May  5 16:18:37 linux kernel: my_handler+0x29/0x30 (probe)
May  5 16:18:37 linux kernel: complete_signal+0x205/0x250
May  5 16:18:37 linux kernel: __send_signal+0x194/0x4b0
May  5 16:18:37 linux kernel: send_signal+0x3e/0x80
May  5 16:18:37 linux kernel: do_send_sig_info+0x52/0xa0
May  5 16:18:37 linux kernel: group_send_sig_info+0x46/0x50
May  5 16:18:37 linux kernel: __kill_pgrp_info+0x4d/0x80
May  5 16:18:37 linux kernel: kill_pgrp+0x35/0x50
May  5 16:18:37 linux kernel: n_tty_receive_char+0x42b/0xe30
May  5 16:18:37 linux kernel:  ? ftrace_ops_list_func+0x106/0x120
May  5 16:18:37 linux kernel: n_tty_receive_buf+0x1ac/0x470
May  5 16:18:37 linux kernel: flush_to_ldisc+0x109/0x160
May  5 16:18:37 linux kernel: process_one_work+0x17b/0x460
May  5 16:18:37 linux kernel: worker_thread+0x11b/0x400
May  5 16:18:37 linux kernel: rescuer_thread+0x400/0x400
May  5 16:18:37 linux kernel:  kthread+0xcf/0xe0
May  5 16:18:37 linux kernel:  kthread_create_on_node+0x140/0x140
May  5 16:18:37 linux kernel:  ret_from_fork+0x7c/0xb0
May  5 16:18:37 linux kernel: ? kthread_create_on_node+0x140/0x140

तो सिग्नल भेजने के लिए प्रमुख फ़ंक्शन कॉल इस प्रकार है:

First shell send the Ctrl+C signal using n_tty_receive_char
n_tty_receive_char()
isig()
kill_pgrp()
__kill_pgrp_info()
group_send_sig_info() -- for each PID in group call this function
do_send_sig_info()
send_signal()
__send_signal() -- allocates a signal structure and add to task pending signals
complete_signal()
signal_wake_up()
signal_wake_up_state()  -- sets TIF_SIGPENDING in the task_struct flags. Then it wake up the thread to which signal was delivered.

अब सब कुछ सेट हो गया है और task_structप्रक्रिया में आवश्यक बदलाव किए गए हैं ।

संकेत का संचालन

सिग्नल को एक प्रक्रिया द्वारा जांचा / संभाला जाता है जब वह सिस्टम कॉल से वापस आता है या यदि व्यवधान से वापसी होती है। सिस्टम कॉल से रिटर्न फाइल में मौजूद है entry_64.S

फ़ंक्शन int_signal फ़ंक्शन को कहा जाता है entry_64.Sजिससे फ़ंक्शन को कॉल किया जाता है do_notify_resume()

चलिए फंक्शन को चेक करते हैं do_notify_resume()। यह फ़ंक्शन जाँचता है कि हमारे पास TIF_SIGPENDINGध्वज सेट है task_struct:

 /* deal with pending signal delivery */
 if (thread_info_flags & _TIF_SIGPENDING)
  do_signal(regs);
do_signal calls handle_signal to call the signal specific handler
Signals are actually run in user mode in function:
__setup_rt_frame -- this sets up the instruction pointer to handler: regs->ip = (unsigned long) ksig->ka.sa.sa_handler;

सिस्टम कॉल और सिग्नल

"धीमे" syscalls जैसे पढ़ना / लिखना अवरुद्ध करना, प्रतीक्षा की स्थिति में प्रक्रियाएँ डालना: TASK_INTERRUPTIBLEयाTASK_UNINTERRUPTIBLE

राज्य में एक कार्य को सिग्नल द्वारा राज्य में TASK_INTERRUPTIBLEबदल दिया जाएगा TASK_RUNNINGTASK_RUNNINGएक प्रक्रिया निर्धारित की जा सकती है।

यदि निष्पादित किया जाता है, तो इसका सिग्नल हैंडलर "धीमी" syscall पूरा होने से पहले चलाया जाएगा। syscallडिफ़ॉल्ट रूप से पूरा नहीं करता है।

यदि SA_RESTARTफ्लैग सेट, syscallसिग्नल हैंडलर खत्म होने के बाद फिर से चालू हो जाता है।

संदर्भ


साइट में योगदान करने के लिए एक प्रयास करने के लिए धन्यवाद, लेकिन (1) यदि आप किसी अन्य साइट से सामग्री की नकल करने जा रहे हैं (शब्द के लिए शब्द, पत्र के लिए पत्र, व्याकरण और विराम चिह्नों सहित), तो आपको कहना चाहिए कि आप कर रहे हैं इसलिए, बहुत अधिक स्पष्ट रूप से। स्रोत को "संदर्भ" के रूप में सूचीबद्ध करना, जबकि आवश्यक हो, पर्याप्त नहीं है। जब तक आप ब्लॉग (K_K = sk?) के लेखक नहीं हैं, तब तक आपको उससे लिंक करने की आवश्यकता नहीं है - लेकिन, यदि आप ऐसा करते हैं, तो आपको इसका खुलासा करना होगा (यानी, कहना होगा) यह आपका है। … (Cont'd)
जी-मैन का कहना है कि मोनिका '

(Cont'd)… (2) आपका स्रोत (आपके द्वारा कॉपी किया गया ब्लॉग) बहुत अच्छा नहीं है। प्रश्न पूछे जाने में चार साल हो गए हैं; क्या आपको इससे बेहतर संदर्भ नहीं मिल सकता है? (यदि आप मूल लेखक हैं, तो क्षमा करें।) उपर्युक्त व्याकरण और विराम चिह्नों (और आमतौर पर मैला शब्द, और खराब स्वरूपण) के अलावा, यह गलत है। (2a) Ctrl + Z SIGTSTP भेजता है, SIGSTOP नहीं। (SIGTSTP, SIGTERM की तरह, पकड़ा जा सकता है; SIGKOP, जैसे SIGKILL, नहीं।) ... (Cont'd)
G-Man Says 'Reinstate Monica'

(Cont'd)… (2b) शेल Ctrl + C सिग्नल नहीं भेजता है। सिग्नल भेजने में शेल की कोई भूमिका नहीं है (सिवाय इसके कि जब उपयोगकर्ता killकमांड का उपयोग करता है , जो शेल बिलिन है)। (2 सी) जबकि }एक समारोह के समापन के बाद अर्धविराम , सख्ती से बोलना, त्रुटियां नहीं हैं, वे अनावश्यक और अत्यधिक अपरंपरागत हैं। (३) सब कुछ सही होने पर भी यह प्रश्न का बहुत अच्छा उत्तर नहीं होगा। (३ अ) यह सवाल, जबकि कुछ अस्पष्ट है, इस बात पर ध्यान केंद्रित कर रहा है कि अभिनेता (उपयोगकर्ता और प्रक्रिया) कैसे आरंभ करते हैं (यानी, संकेत भेजें )। … (Cont'd)
G-Man कहते हैं मोनिका '

(Cont'd) ... उत्तर कर्नेल द्वारा उत्पन्न संकेतों (विशेष रूप से, कीबोर्ड-जनरेट सिग्नल) पर ध्यान केंद्रित करता है और प्राप्तकर्ता प्रक्रिया संकेतों पर प्रतिक्रिया कैसे करता है। (3 बी) प्रश्न के स्तर पर लगता है कि «किसी ने मेरी प्रक्रिया को मार दिया - किसने किया, और कैसे?» जवाब में सिग्नल-हैंडलिंग एपीआई, कर्नेल रूटीन, कर्नेल डिबगिंग (Jprobe?), कर्नेल निशान और कर्नेल डेटा संरचनाएँ। IMO, जो अनुचित रूप से निम्न स्तर का है - विशेष रूप से चूंकि यह कोई संदर्भ प्रदान नहीं करता है जहां एक पाठक इन आंतरिक कामकाज के बारे में अधिक जान सकता है।
जी-मैन का कहना है कि मोनिका '

1
यह मेरा अपना ब्लॉग है .. मेरे अपने निशान .. जो मैं चाहता हूँ .. हर कोई इस तरह के विस्तृत प्रवाह को जानता होगा .. हवा में बात करना कोई मतलब नहीं है .. भले ही इस समुदाय के दिशानिर्देशों का उल्लंघन करने के बाद कृपया मेरा जवाब उचित माध्यम से हटा दें चैनल .. यह कर्नेल आंतरिक उत्तर है व्याकरण के आंतरिक नहीं।
K_K
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.