GNU/Linux >> Znalost Linux >  >> Linux

Co je nepřerušitelný proces?

Když je proces v uživatelském režimu, může být kdykoli přerušen (přepnutím do režimu jádra). Když se jádro vrátí do uživatelského režimu, zkontroluje, zda existují nějaké nevyřízené signály (včetně těch, které se používají k ukončení procesu, jako je SIGTERM a SIGKILL ). To znamená, že proces může být ukončen pouze při návratu do uživatelského režimu.

Důvodem, proč nelze proces v režimu jádra zabít, je to, že by mohl potenciálně poškodit struktury jádra používané všemi ostatními procesy na stejném počítači (stejným způsobem může zabití vlákna potenciálně poškodit datové struktury používané jinými vlákny ve stejném procesu) .

Když jádro potřebuje udělat něco, co by mohlo trvat dlouho (čekání na rouru napsanou jiným procesem nebo čekání, až něco udělá hardware), uspí se tak, že se označí jako spící a zavolá plánovač, aby přepnul na jiný proces (pokud neexistuje žádný neuspalý proces, přepne se na „fiktivní“ proces, který říká procesoru, aby se trochu zpomalil a seděl ve smyčce – nečinné smyčce).

Pokud je signál odeslán do spícího procesu, musí být probuzen, než se vrátí do uživatelského prostoru a zpracuje tak čekající signál. Zde je rozdíl mezi dvěma hlavními typy spánku:

  • TASK_INTERRUPTIBLE , přerušitelný spánek. Pokud je úkol označen tímto příznakem, spí, ale může být probuzen signály. To znamená, že kód, který označil úlohu jako spící, očekává možný signál a po probuzení jej zkontroluje a vrátí se ze systémového volání. Po zpracování signálu může být systémové volání potenciálně automaticky restartováno (a nebudu zabíhat do podrobností o tom, jak to funguje).
  • TASK_UNINTERRUPTIBLE , nepřerušitelný spánek. Pokud je úloha označena tímto příznakem, neočekává se, že bude probuzena něčím jiným, než tím, na co čeká, buď proto, že ji nelze snadno restartovat, nebo proto, že programy očekávají, že systémové volání bude atomické. To lze také použít pro spánky, o kterých je známo, že jsou velmi krátké.

TASK_KILLABLE (zmíněno v článku LWN, na který odkazuje odpověď ddaa) je nová varianta.

Toto odpovídá na vaši první otázku. K vaší druhé otázce:nepřerušitelným spánkům se nevyhnete, jsou normální (stává se to například pokaždé, když proces čte/zapisuje z/na disk); měly by však trvat jen zlomek vteřiny. Pokud trvají mnohem déle, obvykle to znamená problém s hardwarem (nebo problém s ovladačem zařízení, který se jádru jeví stejně), kdy ovladač zařízení čeká, až hardware udělá něco, co se nikdy nestane. Může to také znamenat, že používáte NFS a server NFS je mimo provoz (čeká na obnovení serveru; můžete také použít možnost "intr", abyste se vyhnuli problému).

A konečně, důvod, proč se nemůžete obnovit, je stejný důvod, proč jádro čeká, dokud se nevrátí do uživatelského režimu, aby vyslalo signál nebo ukončilo proces:potenciálně by to poškodilo datové struktury jádra (kód čekající v přerušitelném spánku může obdržet chybu, která mu řekne vrátit se do uživatelského prostoru, kde může být proces zabit; kód čekající v nepřerušitelném spánku neočekává žádnou chybu).


Nepřerušitelné procesy OBVYKLE čekají na I/O po chybě stránky.

Zvažte toto:

  • Vlákno se pokouší o přístup ke stránce, která není v jádře (buď spustitelný soubor, který je načten na vyžádání, stránka anonymní paměti, která byla odložena, nebo soubor mmap()'d, který je načten na vyžádání, což jsou v podstatě stejné)
  • Jádro se ho nyní (pokouší) načíst
  • Proces nemůže pokračovat, dokud nebude stránka dostupná.

Proces/úloha nemůže být v tomto stavu přerušena, protože nezvládá žádné signály; pokud by se tak stalo, došlo by k další chybě stránky a stránka by byla zpět tam, kde byla.

Když říkám „proces“, mám na mysli „úkol“, což v Linuxu (2.6) zhruba znamená „vlákno“, které může, ale nemusí mít individuální položku „skupina vláken“ v /proc

V některých případech to může čekat dlouhou dobu. Typickým příkladem toho může být případ, kdy je spustitelný soubor nebo soubor mmap'd na síťovém souborovém systému, kde selhal server. Pokud I/O nakonec uspěje, úloha bude pokračovat. Pokud to nakonec selže, úkol obvykle dostane SIGBUS nebo něco podobného.


Nepřerušitelný proces je proces, který se náhodou nachází v systémovém volání (funkce jádra), který nemůže být přerušen signálem.

Abyste pochopili, co to znamená, musíte pochopit koncept přerušitelného systémového volání. Klasickým příkladem je read() . Toto je systémové volání, které může trvat dlouho (sekundy), protože může potenciálně zahrnovat roztočení pevného disku nebo pohyb hlav. Po většinu této doby bude proces v režimu spánku a bude blokován na hardwaru.

Zatímco proces spí v systémovém volání, může přijímat unixový asynchronní signál (řekněme SIGTERM), pak se stane následující:

  • Systémové volání se předčasně ukončí a je nastaveno tak, aby vrátilo -EINTR do uživatelského prostoru.
  • Je spuštěn obslužný program signálu.
  • Pokud proces stále běží, získá návratovou hodnotu ze systémového volání a může provést stejné volání znovu.

Včasný návrat ze systémového volání umožňuje kódu uživatelského prostoru okamžitě změnit své chování v reakci na signál. Například čisté ukončení v reakci na SIGINT nebo SIGTERM.

Některá systémová volání naopak tímto způsobem přerušit nelze. Pokud systém z nějakého důvodu zablokuje volání, proces může zůstat v tomto stavu, který nelze zničit, donekonečna.

LWN vydal pěkný článek, který se tohoto tématu dotkl v červenci.

Odpověď na původní otázku:

  • Jak tomu zabránit:zjistěte, který ovladač vám způsobuje potíže, a buď přestaňte používat, nebo se staňte hackerem jádra a opravte to.

  • Jak zabít nepřerušitelný proces bez restartu:nějak ukončit systémové volání. Často nejúčinnějším způsobem, jak toho dosáhnout bez stisknutí vypínače, je vytáhnout napájecí kabel. Můžete se také stát hackerem jádra a přimět ovladač používat TASK_KILLABLE, jak je vysvětleno v článku LWN.


K vaší třetí otázce:Myslím, že můžete zastavit nepřerušitelné procesy spuštěnímsudo kill -HUP 1 .Restartuje init bez ukončení běžících procesů a po jeho spuštění byly mé nepřerušitelné procesy pryč.


Linux
  1. Jak zjistit, který proces vytváří soubor?

  2. Začít proces na jiném Tty?

  3. Který proces má Pid 0?

  1. Jak zkontrolovat, jaké signály proces poslouchá?

  2. Který proces požírá ptys na mém linuxovém serveru?

  3. Co je to příkaz k nalezení priority procesu v Linuxu?

  1. Zjistěte, který proces upravuje soubor

  2. Co jsou nevyřízené signály?

  3. Určete, ve které skupině (skupinách) je běžící proces?