Domanda

A volte ogni volta che scrivo un programma in Linux e si blocca a causa di un bug di qualche tipo, diventa un processo ininterrotto e continua a funzionare per sempre fino a quando non riavvio il computer (anche se esco). Le mie domande sono:

  • Che cosa rende un processo ininterrotto?
  • Come posso impedire che ciò accada?
  • Questa è probabilmente una domanda stupida, ma c'è un modo per interromperla senza riavviare il mio computer?
È stato utile?

Soluzione

Un processo ininterrotto è un processo che si trova in una chiamata di sistema (funzione kernel) che non può essere interrotto da un segnale.

Per capire cosa significhi, è necessario comprendere il concetto di una chiamata di sistema interrompibile. L'esempio classico è read () . Questa è una chiamata di sistema che può richiedere molto tempo (secondi) poiché può potenzialmente comportare la rotazione di un disco rigido o lo spostamento delle testine. Durante la maggior parte di questo tempo, il processo verrà sospeso, bloccando l'hardware.

Mentre il processo è in pausa nella chiamata di sistema, può ricevere un segnale asincrono unix (diciamo, SIGTERM), quindi si verifica quanto segue:

  • Le chiamate di sistema si chiudono prematuramente e sono impostate per restituire -EINTR allo spazio utenti.
  • Il gestore del segnale viene eseguito.
  • Se il processo è ancora in esecuzione, ottiene il valore restituito dalla chiamata di sistema e può ripetere la stessa chiamata.

Il ritorno anticipato dalla chiamata di sistema consente al codice dello spazio utente di modificare immediatamente il suo comportamento in risposta al segnale. Ad esempio, terminando in modo pulito in risposta a SIGINT o SIGTERM.

D'altra parte, alcune chiamate di sistema non possono essere interrotte in questo modo. Se il sistema chiama le bancarelle per qualche motivo, il processo può rimanere indefinitamente in questo stato invendibile.

LWN ha pubblicato un bell'articolo che ha toccato questo argomento a luglio.

Per rispondere alla domanda originale:

  • Come evitare che ciò accada: capire quale driver ti sta causando problemi e smettere di usarlo o diventare un hacker del kernel e risolverlo.

  • Come terminare un processo ininterrotto senza riavviare: in qualche modo far terminare la chiamata di sistema. Spesso il modo più efficace per farlo senza premere l'interruttore di alimentazione è quello di tirare il cavo di alimentazione. Puoi anche diventare un hacker del kernel e far usare al driver TASK_KILLABLE, come spiegato nell'articolo LWN.

Altri suggerimenti

Quando un processo è in modalità utente, può essere interrotto in qualsiasi momento (passando alla modalità kernel). Quando il kernel torna in modalità utente, controlla se ci sono segnali in sospeso (inclusi quelli che vengono usati per terminare il processo, come SIGTERM e SIGKILL ). Ciò significa che un processo può essere interrotto solo al ritorno in modalità utente.

Il motivo per cui un processo non può essere interrotto in modalità kernel è che potrebbe potenzialmente danneggiare le strutture del kernel utilizzate da tutti gli altri processi nella stessa macchina (allo stesso modo l'uccisione di un thread può potenzialmente danneggiare le strutture dati utilizzate da altri thread nel stesso processo).

Quando il kernel deve fare qualcosa che potrebbe richiedere molto tempo (aspettando su una pipe scritta da un altro processo o aspettando che l'hardware faccia qualcosa, per esempio), dorme contrassegnandosi come sleep e chiamando lo scheduler a passa a un altro processo (se non esiste un processo non inattivo, passa a un processo "fittizio" che dice alla cpu di rallentare un po 'e si trova in un ciclo & # 8212; il ciclo inattivo).

Se un segnale viene inviato a un processo di sospensione, deve essere svegliato prima che ritorni nello spazio utente e quindi elabori il segnale in sospeso. Qui abbiamo la differenza tra i due principali tipi di sonno:

  • TASK_INTERRUPTIBLE , il sonno interrompibile. Se un'attività è contrassegnata con questa bandiera, sta dormendo, ma può essere svegliata dai segnali. Ciò significa che il codice che ha contrassegnato l'attività come inattiva è in attesa di un possibile segnale e, dopo essersi svegliato, lo verificherà e tornerà dalla chiamata di sistema. Dopo che il segnale è stato gestito, la chiamata di sistema può essere potenzialmente riavviata automaticamente (e non entrerò nei dettagli su come funziona).
  • TASK_UNINTERRUPTIBLE , il sonno ininterrotto. Se un'attività è contrassegnata con questo flag, non si aspetta che venga svegliata da qualcosa di diverso da quello che sta aspettando, sia perché non può essere riavviata facilmente, sia perché i programmi si aspettano che la chiamata di sistema sia atomica. Questo può essere usato anche per dormire noti per essere molto brevi.

TASK_KILLABLE (menzionato nell'articolo LWN collegato alla risposta di ddaa) è una nuova variante.

Questo risponde alla tua prima domanda. Per quanto riguarda la tua seconda domanda: non puoi evitare di dormire ininterrottamente, sono una cosa normale (succede, ad esempio, ogni volta che un processo legge / scrive da / sul disco); tuttavia, dovrebbero durare solo una frazione di secondo. Se durano molto più a lungo, di solito significa un problema hardware (o un problema del driver del dispositivo, che sembra lo stesso per il kernel), in cui il driver del dispositivo è in attesa che l'hardware faccia qualcosa che non accadrà mai. Può anche significare che stai utilizzando NFS e il server NFS è inattivo (è in attesa che il server si ripristini; puoi anche utilizzare l'opzione "quot" per evitare il problema).

Infine, il motivo per cui non è possibile ripristinare è lo stesso motivo che il kernel attende fino al ritorno in modalità utente per inviare un segnale o uccidere il processo: potrebbe corrompere potenzialmente le strutture di dati del kernel (il codice in attesa di un sonno interrompibile potrebbe ricevere un errore che gli dice di tornare nello spazio utente, dove il processo può essere interrotto; il codice in attesa di un sonno ininterrotto non prevede errori).

I processi ininterrotti normalmente stanno aspettando l'I / O a seguito di un errore di pagina.

Considera questo:

  • Il thread tenta di accedere a una pagina che non è nel core (o un eseguibile che è caricato a richiesta, una pagina di memoria anonima che è stata scambiata, o un file mmap () che è caricato a richiesta, che sono più o meno la stessa cosa)
  • Il kernel ora (sta provando a) caricarlo in
  • Il processo non può continuare fino a quando la pagina non è disponibile.

Il processo / task non può essere interrotto in questo stato, perché non può gestire alcun segnale; in tal caso, si verificherebbe un altro errore di pagina e tornerebbe dove si trovava.

Quando dico "process", intendo davvero "task", che sotto Linux (2.6) si traduce approssimativamente in "thread" che può avere o meno un singolo "gruppo di thread" entrata in / proc

In alcuni casi, potrebbe essere in attesa da molto tempo. Un tipico esempio di ciò sarebbe dove il file eseguibile o mmap'd si trova su un filesystem di rete in cui il server non è riuscito. Se l'I / O alla fine ha esito positivo, l'attività continuerà. Se alla fine fallisce, l'attività otterrà generalmente un SIGBUS o qualcosa del genere.

Alla tua terza domanda: Penso che tu possa uccidere i processi ininterrotti eseguendo sudo kill -HUP 1 . Riavvia init senza terminare i processi in esecuzione e dopo averlo eseguito, i miei processi ininterrotti erano spariti.

Se stai parlando di " zombie " processo (che è designato come "zombie" nell'output ps), questo è un record innocuo nell'elenco dei processi in attesa che qualcuno raccolga il suo codice di ritorno e possa essere tranquillamente ignorato.

Potresti descrivere cosa e "processo ininterrotto" è per te? Sopravvive alla "uccisione -9"? e allegramente si trascina? Se questo è il caso, allora è bloccato su alcuni syscall, che sono bloccati in alcuni driver, e sei bloccato con questo processo fino al riavvio (e talvolta è meglio riavviare presto) o scaricare il driver rilevante (che è improbabile che accada) . Puoi provare a utilizzare " strace " per scoprire dove è bloccato il processo ed evitarlo in futuro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top