Linux-processtatussen

Wat gebeurt er in Linux met de status van een proces wanneer het blokken van een schijf moet lezen? Is het geblokkeerd? Zo ja, hoe wordt een ander proces gekozen om uit te voeren?


Antwoord 1, autoriteit 100%

Als een proces gegevens van een schijf moet ophalen, stopt het in feite met draaien op de CPU om andere processen te laten lopen, omdat de bewerking lang kan duren om te voltooien – een zoektijd van minimaal 5 ms voor een schijf is gebruikelijk, en 5 ms is 10 miljoen CPU-cycli, een eeuwigheid vanuit het oogpunt van het programma!

Vanuit het oogpunt van de programmeur (ook wel “in userspace” genoemd), wordt dit een blokkerende systeemaanroepgenoemd. Als je write(2)aanroept (wat een dunne libc-wrapper is rond de systeemaanroep met dezelfde naam), stopt je proces niet precies bij die grens; het blijft, in de kernel, de systeemaanroepcode uitvoeren. Meestal gaat het helemaal tot aan een specifiek stuurprogramma voor de schijfcontroller (bestandsnaam → bestandssysteem/VFS → blokapparaat → apparaatstuurprogramma), waar een opdracht om een ​​blok op schijf op te halen wordt verzonden naar de juiste hardware, wat een zeer snelle bediening meestal.

DAN wordt het proces in de slaapstandgebracht (in de kernelruimte wordt blokkeren ‘slapen’ genoemd – niets wordt ooit ‘geblokkeerd’ vanuit het oogpunt van de kernel). Het wordt geactiveerd zodra de hardware eindelijk de juiste gegevens heeft opgehaald, waarna het proces wordt gemarkeerd als uitvoerbaaren wordt gepland. Uiteindelijk zal de planner het proces uitvoeren.

Eindelijk, in de gebruikersruimte, keert de blokkerende systeemaanroepterug met de juiste status en gegevens, en gaat het programma verder.

Het is mogelijk om de meeste I/O-systeemaanroepen op te roepen in niet-blokkerende modus(zie O_NONBLOCKin open(2)en fcntl(2)). In dit geval keren de systeemaanroepen onmiddellijk terug en melden alleen het indienen van de schijfbewerking. De programmeur zal op een later tijdstip expliciet moeten controleren of de bewerking al dan niet succesvol is voltooid, en het resultaat ophalen (bijvoorbeeld met select(2)). Dit wordt asynchrone of op gebeurtenissen gebaseerde programmering genoemd.

De meeste antwoorden die de D-statusnoemen (die TASK_UNINTERRUPTIBLEwordt genoemd in de Linux-statusnamen) zijn onjuist. De D-status is een speciale slaapmodus die alleen wordt geactiveerd in een codepad in de kernelruimte, wanneer dat codepad niet kan worden onderbroken(omdat het te complex zou zijn om programma), met de verwachting dat het slechts voor een zeer korte tijd zou blokkeren. Ik geloof dat de meeste “D-toestanden” eigenlijk onzichtbaar zijn; ze zijn van zeer korte duur en kunnen niet worden waargenomen door bemonsteringstools zoals ‘top’.

Je kunt in een aantal situaties niet-killbare processen tegenkomen in de D-status. NFS staat daar bekend om, en ik ben het vaak tegengekomen. Ik denk dat er een semantische clash is tussen sommige VFS-codepaden, die ervan uitgaan dat ze altijd lokale schijven en snelle foutdetectie bereiken (op SATA zou een fouttime-out rond een paar 100 ms zijn), en NFS, dat feitelijk gegevens ophaalt van het netwerk dat is veerkrachtiger en heeft een langzaam herstel (een TCP-time-out van 300 seconden is gebruikelijk). Lees dit artikelvoor de coole oplossing die is geïntroduceerd in Linux 2.6.25 met de TASK_KILLABLEstaat. Vóór dit tijdperk was er een hack waarbij je signalen naar NFS-procesclients kon sturen door een SIGKILL naar de kernelthread rpciodte sturen, maar vergeet die lelijke truc.…


Antwoord 2, autoriteit 65%

Tijdens het wachten op read()of write()naar/van een bestandsdescriptor return, wordt het proces in een speciaal soort slaapstand gezet, bekend als ” D” of “Schijfslaap”. Dit is bijzonder, omdat het proces in zo’n toestand niet kan worden afgebroken of onderbroken. Een proces dat wacht op een terugkeer van ioctl() zou ook op deze manier in de slaapstand worden gezet.

Een uitzondering hierop is wanneer een bestand (zoals een terminal of ander tekenapparaat) wordt geopend in de modus O_NONBLOCK, en wordt doorgegeven wanneer wordt aangenomen dat een apparaat (zoals een modem) tijd nodig heeft te initialiseren. In uw vraag heeft u echter apparaten geblokkeerd. Ik heb ook nog nooit een ioctl()geprobeerd die waarschijnlijk blokkeert op een fd die is geopend in niet-blokkerende modus (althans niet bewust).

Hoe een ander proces wordt gekozen, hangt volledig af van de planner die u gebruikt, en ook van wat andere processen mogelijk hebben gedaan om hun gewicht binnen die planner te wijzigen.

Het is bekend dat sommige gebruikersruimteprogramma’s onder bepaalde omstandigheden voor altijd in deze staat blijven, totdat ze opnieuw worden opgestart. Deze worden meestal gegroepeerd met andere ‘zombies’, maar de term zou niet correct zijn omdat ze technisch gezien niet ter ziele zijn.


Antwoord 3, autoriteit 6%

Een proces dat I/O uitvoert, wordt in de D-status (uninterruptable sleep)gezet, waardoor de CPU wordt vrijgemaakt totdat er een hardware-interrupt is die de CPU vertelt om terug te keren naar het uitvoeren van het programma. Zie man psvoor de andere processtatussen.

Afhankelijk van je kernel is er een procesplanner, die een reeks processen bijhoudt die klaar zijn om uit te voeren. Het vertelt, samen met een planningsalgoritme, de kernel welk proces aan welke CPU moet worden toegewezen. Er zijn kernelprocessen en gebruikersprocessen om te overwegen. Elk proces krijgt een tijdsdeel toegewezen, wat een deel van de CPU-tijd is die het mag gebruiken. Zodra het proces alle tijdsdelen heeft gebruikt, wordt het gemarkeerd als verlopen en krijgt het een lagere prioriteit in het planningsalgoritme.

In de 2.6-kernelis er een O(1) tijdcomplexiteitsplanner, dus hoeveel processen je ook hebt draaien, het zal constant CPU’s toewijzen tijd. Het is echter ingewikkelder, aangezien 2.6 preëmptie introduceerde en CPU-taakverdeling geen eenvoudig algoritme is. Het is in ieder geval efficiënt en CPU’s zullen niet inactief blijven terwijl u wacht op de I/O.


Antwoord 4, autoriteit 2%

Zoals al door anderen is uitgelegd, zijn processen in de “D”-status (ononderbroken slaap) verantwoordelijk voor het vastlopen van het ps-proces. Bij mij is het vaak gebeurd met RedHat 6.x en automatisch aangekoppelde NFS-thuismappen.

Om processen in D-status weer te geven, kunt u de volgende opdrachten gebruiken:

cd /proc
for i in [0-9]*;do echo -n "$i :";cat $i/status |grep ^State;done|grep D

Om de huidige map van het proces te kennen en, mogelijk, de gekoppelde NFS-schijf die problemen heeft, kunt u een opdracht gebruiken die lijkt op het volgende voorbeeld (vervang 31134 door het slaapprocesnummer):

# ls -l /proc/31134/cwd
lrwxrwxrwx 1 pippo users 0 Aug  2 16:25 /proc/31134/cwd -> /auto/pippo

Ik ontdekte dat het geven van het umount-commando met de -f (force) -schakelaar, aan het gerelateerde gekoppelde nfs-bestandssysteem, het slaapproces kon activeren:

umount -f /auto/pippo

het bestandssysteem was niet ontkoppeld, omdat het druk was, maar het gerelateerde proces werd wakker en ik kon het probleem oplossen zonder opnieuw op te starten.


Antwoord 5

Ervan uitgaande dat uw proces een enkele thread is en dat u I/O blokkeert, blokkeert uw proces het wachten tot de I/O is voltooid. De kernel zal een ander proces kiezen om in de tussentijd uit te voeren op basis van aardigheid, prioriteit, laatste runtime, enz. Als er geen andere uitvoerbare processen zijn, zal de kernel er geen draaien; in plaats daarvan vertelt het de hardware dat de machine inactief is (wat resulteert in een lager stroomverbruik).

Processen die wachten tot I/O is voltooid, worden meestal weergegeven in status D in, bijvoorbeeld psen top.


Antwoord 6

Ja, de taak wordt geblokkeerd in de read() systeemaanroep. Een andere taak die gereed is, wordt uitgevoerd, of als er geen andere taken gereed zijn, wordt de inactieve taak (voor die CPU) uitgevoerd.

Een normale, blokkerende schijflezing zorgt ervoor dat de taak naar de “D”-status gaat (zoals anderen al hebben opgemerkt). Dergelijke taken dragen bij aan het gemiddelde van de belasting, ook al verbruiken ze geen CPU.

Enkele andere typen IO, met name TTYS en netwerk gedragen zich niet hetzelfde – het proces belandt in “S” -staat en kan worden onderbroken en telt niet tegen het laadgemiddelde.


Antwoord 7

Ja, taken die wachten op IO zijn geblokkeerd en andere taken worden uitgevoerd. De volgende taak selecteren gebeurt door de Linux-planner .


Antwoord 8

Over het algemeen blokkeert het proces. Als de leesbewerking op een bestandsdescriptor is gemarkeerd als niet-blokkering of als het proces gebruik maakt van asynchrone IO, zal het niet blokkeren. Ook als het proces andere threads heeft die niet geblokkeerd zijn, kunnen ze doorgaan met werken.

De beslissing met betrekking tot welk proces wordt uitgevoerd, is aan de schedurer in de kernel.

Other episodes