2015-09-17 11 views
7

So che quando premiamo Ctrl + C, verrà generato un segnale SIGINT e l'azione predefinita di terminare il processo verrà eseguita dal kernel. Ma da dove viene il codice per questa terminazione? È nel binario ELF o il kernel lo fa per noi? Presumo che sia nel kernel ed è per questo che abbiamo bisogno di gestori personalizzati nel nostro codice sorgente per sovrascrivere il comportamento del segnale.Dov'è il codice per il gestore di segnali predefinito nel binario ELF?

Qualsiasi suggerimento sarà molto apprezzato.

risposta

5

È qualcosa che il kernel sta facendo per noi. Puoi trovare tutte le informazioni leggendo il file signal.c nei sorgenti del kernel.

Il punto in cui kernel sta cercando di trovare un gestore di segnale registrato comincia qui: 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     } 

Quindi, se c'è un gestore di segnale e se non lo è "ignore segnale" (SIG_IGN) e se è non il gestore "predefinito" (SIG_DEF), il kernel lo contrassegnerà semplicemente per essere eseguito (e, a seconda che sia di tipo unico, sposterà nuovamente il gestore sul gestore predefinito).

Tuttavia, se non c'è gestore di segnale registrato, o se si tratta di SIG_DEF, kernel controlla se magari ha bisogno di mettere in pausa il processo, e, infine, kernel stati i seguenti:

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

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

+0

Ulteriori domande - "SE" Fornisco il mio gestore personalizzato? Chi eseguirà il codice nel gestore personalizzato? La logica verrà eseguita dal sistema operativo nell'anello 0 o nell'anello 3? – bawejakunal

+1

@bawejakunal: verrà eseguito nell'anello 3. Fare altrimenti sarebbe un pericolo per la sicurezza completo. – 3442

2

Diamo Dì di te kill(theShell, SIGINT). Quello che succede è qualcosa di simile ... (non mostrando il codice del kernel, perché in realtà non è rilevante)

  1. La libreria di runtime C avrà tutti gli argomenti alla chiamata di sistema sys_kill(), e procedere per eseguire il codice assembly che esegue chiamata di sistema raw.
  2. Il kernel riceve argomenti, effettua autorizzazioni assegni, ecc, ecc ...
  3. Se il processo ha il gestore di segnale corrispondente impostato SIG_DEF, il kernel esegue direttamente e restituisce il corrispondente azione predefinita. Se il processo ha il corrispondente gestore di segnale impostato su SIG_IGN, il segnale viene ignorato e la chiamata di sistema ritorna. Altrimenti, continua.
  4. Il segnale viene inserito nella coda dei segnali per il processo di destinazione, insieme ad alcune informazioni come il mittente.
  5. Una volta che un thread nel processo di destinazione è selezionabile per ricevere il segnale e non viene nascosto, il contesto del thread (registri della CPU, puntatore dello stack, ecc.) Viene salvato e viene richiamato il gestore di segnale. Se il thread era in una chiamata di sistema al momento dell'arrivo del segnale, la chiamata di sistema restituisce -EINTR (per motivi di semplicità) e viene richiamato il gestore. Una volta restituito il gestore, viene richiamata automaticamente la chiamata di sistema sys_sigreturn, ripristinando lo stato del thread prima del segnale.
  6. Nel frattempo si verifica il passaggio 5, la chiamata di sistema del processo kill() restituisce.