2015-09-17 32 views
7

Wiem, że po naciśnięciu Ctrl + C, sygnał SIGINT zostanie podniesiony, a domyślna akcja zakończenia procesu zostanie wykonana przez jądro. Ale skąd pochodzi kod tego zakończenia? Czy jest to plik binarny ELF, czy jądro robi to za nas? Zakładam, że jest w jądrze i dlatego potrzebujemy niestandardowych procedur obsługi w naszym kodzie źródłowym, aby nadpisać zachowanie sygnału.Gdzie jest kod dla domyślnej obsługi sygnału w binarnym ELF?

Wszelkie wskazówki będą mile widziane.

Odpowiedz

5

To coś, co robi dla nas jądro. Możesz znaleźć wszystkie informacje czytając plik signal.c w źródłach jądra.

Punkt, w którym jądro próbuje znaleźć zarejestrowaną obsługi sygnału zaczyna się tutaj: http://lxr.free-electrons.com/source/kernel/signal.c#L2257

2257     ka = &sighand->action[signr-1]; 
2258 
2259     /* Trace actually delivered signals. */ 
2260     trace_signal_deliver(signr, &ksig->info, ka); 
2261 
2262     if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ 
2263       continue; 
2264     if (ka->sa.sa_handler != SIG_DFL) { 
2265       /* Run the handler. */ 
2266       ksig->ka = *ka; 
2267 
2268       if (ka->sa.sa_flags & SA_ONESHOT) 
2269         ka->sa.sa_handler = SIG_DFL; 
2270 
2271       break; /* will return non-zero "signr" value */ 
2272     } 

Tak więc, jeśli nie ma obsługi sygnału, a jeśli nie jest to „sygnał zignorować” (SIG_IGN), a jeśli jest to nie "domyślny" handler (SIG_DEF), jądro po prostu oznaczy go jako uruchamiany (i w zależności od tego, czy jest to jednorazowe przejście, ponownie przeniesie program obsługi do domyślnego programu obsługi).

Jednakże, jeśli nie ma obsługi sygnału zarejestrowany, lub jeżeli jest to SIG_DEF kontrole jądra, czy może ona potrzebuje, aby wstrzymać proces i wreszcie jądra stwierdza co następuje:

2330     /* 
2331     * Anything else is fatal, maybe with a core dump. 
2332     */ 

http://lxr.free-electrons.com/source/kernel/signal.c#L2330

+0

Więcej pytania - "JEŻELI" Dostarczam własny niestandardowy przewodnik? Kto wykona kod w niestandardowej funkcji obsługi? Czy logika zostanie wykonana przez system operacyjny w pierścieniu 0 lub proces w pierścieniu 3? – bawejakunal

+1

@bawejakunal: Zostanie wykonany w pierścieniu 3. Inaczej stanowiłoby to pełne zagrożenie bezpieczeństwa. – 3442

2

LET'S powiedzieć, że jesteś kill(theShell, SIGINT). Co się dzieje, jest coś takiego jak ... (nie pokazano kodu jądra, ponieważ nie jest faktycznie istotne)

  1. biblioteki C Runtime podejmie wszelkie argumenty do wywołania systemowego sys_kill() i wykona kod montaż, który wykonuje surowe wywołanie systemowe.
  2. Jądro odbiera argumenty, przeprowadza kontrole z uprawnieniami, etc, etc ...
  3. Jeśli proces posiada odpowiednie procedury obsługi sygnału ustawiony na SIG_DEF, jądro wykonuje odpowiednią akcję domyślną bezpośrednio i powroty. Jeśli proces ma odpowiednią funkcję obsługi sygnału ustawioną na SIG_IGN, sygnał jest ignorowany, a wywołanie systemowe powraca. W przeciwnym razie kontynuuj.
  4. Sygnał jest umieszczany w kolejce sygnału dla procesu docelowego, wraz z pewnymi informacjami, takimi jak nadawca.
  5. Po wybraniu wątku w procesie docelowym do odbierania sygnału i nie jest on maskowany, kontekst wątku (rejestry CPU, wskaźnik stosu itp.) Zostaje zapisany i wywoływana jest procedura obsługi sygnału. Jeśli wątek był w wywołaniu systemowym w momencie nadejścia sygnału, wywołanie systemowe zwraca -EINTR (dla uproszczenia) i wywoływacz jest wywoływany. Po przywróceniu programu obsługi wywołanie systemowe sys_sigreturn jest automatycznie wywoływane, przywracając stan wątku przed sygnałem.
  6. W międzyczasie krok 5 się dzieje, wywołanie systemowe procesu kill() zwraca.