Prozesshunger in Betriebssystemen: Ursachen, Mechanismen und produktionsreife Lösungen
Prozess-Starvation tritt auf, wenn einem Prozess die benötigte CPU-Zeit, der Arbeitsspeicher oder die I/O-Bandbreite auf unbestimmte Zeit verweigert wird, um Fortschritte zu erzielen – nicht weil die Ressourcen nicht vorhanden sind, sondern weil die Scheduling-Richtlinie konsequent andere Prozesse bevorzugt. Im Gegensatz zu Deadlocks, bei denen alle konkurrierenden Prozesse blockiert sind, ermöglicht Starvation, dass das System funktionsfähig erscheint, während es bestimmte Workloads still abbaut oder anhält.
Dieser Unterschied ist operativ bedeutsam: Ein ausgehungerter Prozess erzeugt keine Fehler auf Kernel-Ebene, generiert keine Crash-Dumps und löst möglicherweise keine Standard-Alarmschwellen aus – was ihn zu einer der heimtückischsten Performance-Pathologien in Multi-Tenant- und High-Concurrency-Serverumgebungen macht.
Was Starvation auf Kernel-Ebene tatsächlich bedeutet
Der Begriff ist der Ressourcenökologie entlehnt: Ein Prozess „verhungert”, wenn er dauerhaft um eine begrenzte Ressource überboten wird. In modernen Betriebssystemen implementieren der Linux Completely Fair Scheduler (CFS), Windows NT-Prioritätswarteschlangen und der BSD ULE-Scheduler alle Mechanismen zur Verhinderung von Starvation – dennoch tritt sie in der Produktion unter bestimmten Bedingungen auf.
Auf Kernel-Ebene manifestiert sich Starvation als Prozess, dessen virtuelle Laufzeit (in CFS-Terminologie) oder Wartezeit unbegrenzt wächst, ohne jemals für die Ausführung ausgewählt zu werden. Der Prozess verbleibt im TASK_RUNNING-Zustand – er ist bereit und berechtigt – aber der Scheduler gewährt ihm nie einen CPU-Slice, weil Tasks mit höherer Priorität oder häufiger ausführbare Tasks ihn immer verdrängen.
Wichtige technische Unterscheidung:
- Deadlock: Zwei oder mehr Prozesse sind gegenseitig blockiert, jeder wartet auf eine Ressource, die der andere hält. Das System macht bei diesen Tasks null Fortschritt.
- Starvation: Ein oder mehrere Prozesse werden vom Scheduler dauerhaft übergangen. Andere Prozesse laufen weiterhin normal.
- Livelock: Prozesse sind nicht blockiert, ändern aber kontinuierlich ihren Zustand als Reaktion aufeinander, ohne tatsächlichen Fortschritt zu erzielen.
Grundursachen von Prozess-Starvation
Das Verständnis von Starvation erfordert die Untersuchung der spezifischen Mechanismen, die sie erzeugen, nicht nur die Auflistung von „begrenzten Ressourcen” als Ursache.
1. Statische Prioritätsinversion ohne Aging
Die meisten prioritätsbasierten Scheduler weisen jedem Prozess eine feste oder halbfeste Priorität zu. Wenn ein Prozess mit niedriger Priorität immer von einem Strom mittel- und hochpriorisierter Tasks verdrängt wird, wird er nie ausgeführt. Der kritische Fehlermodus hier ist das Fehlen von Aging – einer Technik, bei der die effektive Priorität eines Prozesses schrittweise erhöht wird, je länger er wartet. Ohne Aging kann ein Hintergrundauftrag mit niedriger Priorität auf einem ausgelasteten Server unbegrenzt warten.
Unter Linux schaffen der nice-Wertebereich (-20 bis +19) und Echtzeit-Prioritäten (SCHED_FIFO, SCHED_RR) genau dieses Risiko. Ein Prozess, der unter SCHED_FIFO mit Priorität 99 läuft, verdrängt jeden SCHED_OTHER-Prozess auf demselben CPU-Kern, bis er freiwillig nachgibt oder blockiert.
2. Unfaire Warteschlangen in I/O-Schedulern
CPU-Starvation ist gut dokumentiert, aber I/O-Starvation ist ebenso destruktiv und wird oft übersehen. Der Linux I/O-Scheduler (historisch CFQ, jetzt BFQ oder mq-deadline je nach Kernel-Version und Speichertyp) verwaltet die Reihenfolge, in der Block-Device-Anfragen bedient werden. Bei hohen sequenziellen Schreib-Workloads – häufig bei Datenbankservern und log-intensiven Anwendungen – kann der I/O-Scheduler zufällige Leseanfragen anderer Prozesse deprioritisieren und sie effektiv vom Festplattenzugriff aushungern.
Dies ist ein häufiges Problem in VPS Hosting-Umgebungen, in denen mehrere Tenants die zugrunde liegende Speicherinfrastruktur teilen und I/O-Konkurrenz ein reales operatives Problem darstellt.
3. Speicherdruck und der OOM-Killer
Wenn der physische RAM erschöpft ist, wählt der Out-Of-Memory (OOM)-Killer des Linux-Kernels basierend auf einem oom_score einen Prozess zur Beendigung aus. Obwohl dies technisch gesehen eine Beendigung und keine Starvation ist, stellt der Vorzustand – bei dem ein Prozess wiederholt auf die Festplatte ausgelagert wird und nie genügend residenten Speicher erhält, um effizient zu arbeiten – Memory-Starvation dar. Der Prozess läuft technisch gesehen, macht aber aufgrund ständiger Page-Faults und Swap-I/O kaum Fortschritte.
4. Lock-Contention und Mutex-Starvation
In Multi-Thread-Anwendungen tritt Starvation auf der Ebene der Synchronisierungsprimitive auf. Wenn ein Mutex oder Semaphor eine unfaire Akquisitionsrichtlinie verwendet (Last-In-First-Out oder zufällige Auswahl unter wartenden Threads), kann ein bestimmter Thread dauerhaft übergangen werden, obwohl der Lock häufig freigegeben wird. Dies unterscheidet sich vom OS-Level-Scheduling und tritt vollständig im Userspace oder im Synchronisierungssubsystem des Kernels auf.
5. Netzwerkbandbreiten-Starvation
In containerisierten und virtualisierten Umgebungen kann ein Prozess oder Container, der die gesamte verfügbare Netzwerkbandbreite verbraucht, andere Prozesse von Netzwerk-I/O aushungern. Ohne Traffic-Shaping über tc (Traffic Control) und cgroups kann ein einzelner unkontrollierter Prozess den NIC-Durchsatz monopolisieren.
Starvation vs. Deadlock vs. Livelock: Technischer Vergleich
| Eigenschaft | Starvation | Deadlock | Livelock |
|---|---|---|---|
| Systemfortschritt | Ja (andere Prozesse laufen) | Nein (blockierte Prozesse halten an) | Scheinbar (kein echter Fortschritt) |
| Blockierter Zustand | Nein (Prozess ist ausführbar) | Ja (Prozess wartet auf Ressource) | Nein (Prozess ist aktiv) |
| Ressource gehalten | Nein | Ja (zirkuläres Hold-and-Wait) | Nein |
| Selbstauflösend | Manchmal (mit Aging) | Nie (erfordert Eingriff) | Selten |
| Erkennungsschwierigkeit | Hoch (kein expliziter Fehler) | Mittel (Zykluserkennung) | Hoch (erscheint als Aktivität) |
| Primäre Ursache | Unfaire Scheduling-Richtlinie | Zirkuläre Ressourcenabhängigkeit | Reaktive Zustandsänderungsschleifen |
| Linux-Kernel-Signal | Keines | Keines (Soft-Lockup möglich) | Keines |
Wie moderne Scheduler Starvation begegnen
Der Linux Completely Fair Scheduler (CFS)
CFS, eingeführt in Linux-Kernel 2.6.23, begegnet Starvation durch die Verfolgung der virtuellen Laufzeit (vruntime) für jeden Prozess. Der Scheduler wählt immer den Prozess mit der niedrigsten vruntime aus – das bedeutet, Prozesse, die weniger CPU-Zeit erhalten haben, werden systematisch priorisiert. Dieses Design macht reine CPU-Starvation unter CFS für SCHED_OTHER-Prozesse nahezu unmöglich.
CFS schützt jedoch nicht vor Starvation durch Echtzeit-Prozesse. Jeder Prozess, der unter SCHED_FIFO oder SCHED_RR geplant ist, verdrängt alle SCHED_OTHER-Tasks. Der Kernel-Parameter /proc/sys/kernel/sched_rt_runtime_us (Standard: 950.000 Mikrosekunden pro Sekunde) reserviert genau deshalb 5 % der CPU-Zeit für Nicht-Echtzeit-Tasks, um dies zu verhindern.
Prioritäts-Aging
Klassische Aging-Algorithmen erhöhen die effektive Priorität eines Prozesses um einen festen Betrag für jeden Scheduling-Zyklus, den er wartend verbringt. Sobald die effektive Priorität das höchste Niveau erreicht, ist die Ausführung des Prozesses garantiert. Nach seiner Ausführung wird seine Priorität auf den Basiswert zurückgesetzt. Dies ist die Lehrbuchlösung für prioritätsbasierte Starvation und ist in verschiedenen Formen in Windows NT, Solaris und älteren Linux-Schedulern implementiert.
Fair Queuing und Weighted Fair Queuing (WFQ)
Für Netzwerk- und I/O-Ressourcen weist Weighted Fair Queuing jedem Flow oder Prozess einen Bandbreitenanteil proportional zu seinem Gewicht zu. Selbst wenn ein Flow mit hohem Gewicht mehr Traffic erzeugt, wird Flows mit niedrigem Gewicht eine Mindestdienstrate garantiert. Linux implementiert dies über die Hierarchical Token Bucket (HTB)– und Stochastic Fair Queuing (SFQ)-Disziplinen im tc-Subsystem.
Diagnose von Starvation in produktiven Linux-Systemen
Die Identifizierung von Starvation erfordert die gleichzeitige Korrelation mehrerer Datenquellen.
CPU-Scheduling-Analyse
# Check per-process CPU wait time and scheduling statistics
cat /proc/<PID>/schedstat
# Monitor scheduler latency with perf
perf sched latency --sort max
# Identify processes with high voluntary/involuntary context switches
pidstat -w 1 10
# Check real-time process priorities that may be starving others
ps -eo pid,comm,cls,pri,ni --sort=-pri | head -20Die schedstat-Ausgabe liefert die kumulative Zeit, die der Prozess in der Run-Queue gewartet hat (run_delay in Nanosekunden) – ein direktes Maß für Scheduling-Starvation.
Memory-Starvation-Indikatoren
# Check swap activity — high si/so values indicate memory starvation
vmstat 1 10
# Identify processes with high major page fault rates
pidstat -r 1 10
# Check OOM kill history
dmesg | grep -i "oom|killed process"
# Inspect per-process memory pressure
cat /proc/<PID>/status | grep -E "VmRSS|VmSwap|VmPeak"I/O-Starvation-Erkennung
# Per-process I/O wait statistics
iotop -b -n 5
# Block device queue depth and wait times
iostat -x 1 5
# Check I/O scheduler in use for each block device
cat /sys/block/sda/queue/scheduler
# Identify processes blocked on I/O
ps aux | awk '$8 ~ /D/ {print}'Prozesse im D-Zustand (unterbrechungsfreier Schlaf) sind durch I/O blockiert. Eine anhaltende Population von D-Zustandsprozessen ist ein starker Indikator für I/O-Starvation oder Sättigung des Speichersubsystems.
Produktionsreife Lösungen und Mitigationsstrategien
cgroups v2 für Ressourcenisolierung implementieren
Control Groups (cgroups v2) bieten den robustesten Mechanismus zur Verhinderung von Starvation in Multi-Prozess- und containerisierten Umgebungen. Durch die Zuweisung expliziter CPU-, Speicher- und I/O-Kontingente zu Prozessgruppen werden Mindestressourcenzuweisungen unabhängig von der Systemlast garantiert.
# Create a cgroup with CPU weight (higher weight = more CPU share)
mkdir /sys/fs/cgroup/my_service
echo "100" > /sys/fs/cgroup/my_service/cpu.weight
# Set memory limit to prevent memory starvation of other groups
echo "2G" > /sys/fs/cgroup/my_service/memory.max
# Assign process to cgroup
echo <PID> > /sys/fs/cgroup/my_service/cgroup.procsDas CPU-Gewicht in cgroups v2 verwendet einen Bereich von 1–10000, wobei der Standard 100 ist. Eine Prozessgruppe mit Gewicht 200 erhält unter Konkurrenz doppelt so viel CPU-Anteil wie eine mit Gewicht 100.
Den Linux-Scheduler für Ihre Workload optimieren
# Increase scheduler migration cost to reduce cache thrashing (latency-sensitive workloads)
echo 500000 > /proc/sys/kernel/sched_migration_cost_ns
# Reduce scheduler granularity for more frequent preemption (throughput workloads)
echo 1000000 > /proc/sys/kernel/sched_min_granularity_ns
# Ensure real-time tasks cannot starve normal tasks
echo 950000 > /proc/sys/kernel/sched_rt_runtime_usGeeignete Scheduling-Richtlinien pro Prozess anwenden
# Set a process to batch scheduling (explicitly low-priority, won't starve interactive tasks)
chrt -b -p 0 <PID>
# Set a CPU-intensive background job to idle scheduling class
chrt -i -p 0 <PID>
# Adjust nice value for a running process
renice -n 10 -p <PID>
# Run a new command with reduced priority
nice -n 15 ./my_background_script.shDie SCHED_IDLE-Klasse (chrt -i) ist das richtige Werkzeug für wirklich Hintergrundaufgaben – sie läuft nur, wenn kein anderer ausführbarer Prozess existiert, und eliminiert damit vollständig ihre Fähigkeit, andere Workloads auszuhungern.
I/O-Scheduler-Auswahl
# For NVMe SSDs (low-latency, no rotational penalty): use none or mq-deadline
echo "mq-deadline" > /sys/block/nvme0n1/queue/scheduler
# For HDDs with mixed workloads: use bfq for fairness
echo "bfq" > /sys/block/sda/queue/scheduler
# Make persistent across reboots (add to /etc/udev/rules.d/)
echo 'ACTION=="add|change", KERNEL=="sda", ATTR{queue/scheduler}="bfq"'
> /etc/udev/rules.d/60-scheduler.rulesBFQ (Budget Fair Queuing) ist speziell darauf ausgelegt, I/O-Starvation zu verhindern, indem jedem Prozess ein proportionaler Anteil der Festplattenbandbreite garantiert wird. Es ist der empfohlene Scheduler für Shared-Hosting- und Datenbankserver-Umgebungen.
Netzwerkbandbreitenkontrolle mit tc
# Create a root HTB qdisc on the primary interface
tc qdisc add dev eth0 root handle 1: htb default 30
# Add a parent class with total bandwidth
tc class add dev eth0 parent 1: classid 1:1 htb rate 1gbit
# Add child classes with guaranteed minimums (prevents starvation)
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 100mbit ceil 1gbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 100mbit ceil 1gbit
# Add SFQ leaf to each class for per-flow fairness
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10Diese Konfiguration garantiert jeder Klasse ein Minimum von 100 Mbps, während Burst-Nutzung bis zur vollen 1 Gbps-Linkkapazität erlaubt wird, wenn Bandbreite verfügbar ist.
Memory-Overcommit und Swap-Optimierung
# Reduce swappiness to minimize swap-induced memory starvation
echo 10 > /proc/sys/vm/swappiness
# Enable memory overcommit accounting (prevents OOM from surprising processes)
echo 2 > /proc/sys/vm/overcommit_memory
# Set overcommit ratio (total allocatable = RAM * ratio + swap)
echo 80 > /proc/sys/vm/overcommit_ratioDas Setzen von vm.swappiness=10 weist den Kernel an, die Rückgewinnung des Page-Caches gegenüber dem Auslagern von Prozessspeicher zu bevorzugen, was die Wahrscheinlichkeit von Memory-Starvation unter moderater Last erheblich reduziert.
Starvation in virtualisierten und containerisierten Umgebungen
Auf Dedicated Servers, die Hypervisoren (KVM, VMware ESXi, Hyper-V) betreiben, kann Starvation auf zwei verschiedenen Ebenen auftreten:
Starvation auf Hypervisor-Ebene: Einer virtuellen Maschine werden CPU-Zyklen vom Hypervisor-Scheduler verweigert. KVM verwendet den CFS des Host-Kernels für vCPU-Scheduling, was bedeutet, dass eine VM mit einem niedrigeren CPU-Share-Gewicht von VMs mit höheren Gewichten unter Konkurrenz ausgehungert werden kann. VMwares DRS (Distributed Resource Scheduler) verwendet Shares, Reservierungen und Limits, um dies zu kontrollieren.
Starvation auf Gast-OS-Ebene: Innerhalb der VM selbst gelten dieselben OS-Level-Scheduling-Dynamiken. Eine containerisierte Workload, die unter Docker oder Kubernetes ohne explizite Ressourcenlimits läuft, kann die CPU und den Speicher des Gast-OS monopolisieren und co-lokalisierte Container aushungern.
Für Kubernetes-Umgebungen sollten immer sowohl requests als auch limits in Pod-Spezifikationen definiert werden:
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"Der requests-Wert bestimmt die Scheduling-Platzierung und das cgroup CPU-Share-Gewicht. Ohne ihn hat der Kubernetes-Scheduler keine Grundlage für eine faire Platzierung, und die Container-Runtime weist Standard-(gleiche) Gewichte zu – was dennoch Starvation ermöglicht, wenn ein Container konsequent sein CPU-Limit ausschöpft.
Starvation in Datenbank- und Anwendungsservern
Datenbank-Engines implementieren ihre eigenen internen Scheduler, die unabhängig vom OS-Scheduler sind. PostgreSQL verwendet ein Prozess-pro-Verbindung-Modell, bei dem jeder Backend-Prozess normal um OS-Ressourcen konkurriert, aber Lock-Contention innerhalb der Datenbank (Row-Level-Locks, Advisory-Locks) kann zu Starvation auf Anwendungsebene führen, bei der bestimmte Abfragen unbegrenzt auf die Lock-Akquisition warten.
MySQL/InnoDB verwendet einen Thread-Pool mit konfigurierbaren Concurrency-Limits (innodb_thread_concurrency). Ein zu niedriger Wert verursacht Query-Starvation, da Threads in der Warteschlange auf Ausführungsslots warten. Ein zu hoher Wert verursacht CPU-Thrashing. Der empfohlene Startwert ist 2 × number of CPU cores.
Bei Webservern haben Nginx und Apache unterschiedliche Starvation-Profile. Nginxs ereignisgesteuertes Modell ist von Natur aus resistent gegen Worker-Starvation, aber die Erschöpfung des Upstream-Verbindungspools (z. B. zu PHP-FPM oder einer Backend-API) erzeugt Starvation auf Anwendungsebene. Apaches Prefork-MPM kann sein MaxRequestWorkers-Limit erschöpfen, was dazu führt, dass neue Verbindungen unbegrenzt in der Warteschlange stehen – eine Form von Verbindungs-Starvation.
Diese Überlegungen sind direkt relevant bei der Konfiguration eines VPS mit cPanel für Shared-Web-Hosting-Workloads, bei denen mehrere Sites um PHP-FPM-Worker-Pools und MySQL-Verbindungslimits konkurrieren.
Monitoring-Infrastruktur zur Starvation-Prävention
Reaktive Diagnose ist für Produktionssysteme unzureichend. Ein proaktiver Monitoring-Stack sollte Folgendes umfassen:
Zu beobachtende Prometheus + Node Exporter-Metriken:
node_schedstat_waiting_seconds_total— kumulative CPU-Run-Queue-Wartezeit pro CPUnode_vmstat_pgmajfault— Major-Page-Faults als Indikator für Speicherdrucknode_disk_io_time_weighted_seconds_total— I/O-Queue-Sättigungnode_pressure_cpu_waiting_seconds_total— Linux PSI (Pressure Stall Information) CPU-Drucknode_pressure_memory_full_seconds_total— PSI-Memory-Full-Stall-Zeit
Linux PSI (verfügbar seit Kernel 4.20) ist der direkteste im Kernel verfügbare Starvation-Indikator. Es meldet den Prozentsatz der Zeit, in der Tasks auf CPU-, Speicher- oder I/O-Ressourcen gewartet haben:
# Real-time PSI monitoring
cat /proc/pressure/cpu
cat /proc/pressure/memory
cat /proc/pressure/ioAusgabeformat: some avg10=X.XX avg60=X.XX avg300=X.XX total=NNNN, wobei some anzeigt, dass mindestens ein Task blockiert war. Werte über 10–15 % bei avg60 erfordern sofortige Untersuchung.
Für Teams, die VPS Control Panels oder benutzerdefinierte Server-Stacks verwalten, bietet die Integration von PSI-Metriken in Grafana-Dashboards eine Frühwarnung, bevor Starvation die benutzerseitige Performance beeinträchtigt.
Praktische Entscheidungsmatrix: Die richtige Anti-Starvation-Maßnahme wählen
| Symptom | Ressourcentyp | Empfohlenes Werkzeug | Konfigurationsziel |
|---|---|---|---|
| Hintergrundaufträge werden nie abgeschlossen | CPU | SCHED_IDLE oder nice +19 | CPU-Konkurrenz im Hintergrund eliminieren |
| Interaktive Latenzspitzen unter Last | CPU | CFS-Tuning + cgroups v2 CPU-Gewicht | Interaktiven Prozessanteil garantieren |
| Datenbank-Abfragen laufen in Timeout | CPU + Lock | innodb_thread_concurrency, Lock-Timeout | Lock-Wartezeit begrenzen |
| Festplattenintensive Jobs blockieren Web-Serving | I/O | BFQ-Scheduler + cgroups v2 io.weight | Proportionale I/O-Zuweisung |
| Container-OOM-Kills unter Last | Memory | cgroups v2 memory.min + vm.swappiness | Minimalen residenten Speicher garantieren |
| Netzwerkintensiver Prozess hungert andere aus | Netzwerk | HTB + SFQ über tc | Bandbreitengarantie pro Klasse |
| VM durch Hypervisor ausgehungert | vCPU | Hypervisor-CPU-Reservierungen/Shares | Minimale vCPU-Zyklen reservieren |
Wichtige technische Erkenntnisse
- Verlassen Sie sich niemals auf Standard-Scheduling für Server mit gemischten Workloads. Klassifizieren Sie Prozesse explizit mit
chrt,niceund cgroups v2 basierend auf ihrer Latenzempfindlichkeit und Geschäftspriorität. - PSI-Monitoring aktivieren (
/proc/pressure/*) auf allen produktiven Linux-Systemen. Es ist der genaueste Echtzeit-Starvation-Indikator im Kernel und hat nahezu keinen Overhead. - BFQ für rotierende Festplatten verwenden und für jedes NVMe-Gerät, das gemischte zufällige/sequenzielle Workloads in Multi-Tenant-Umgebungen bedient. Die Fairness-Garantien sind den marginalen Durchsatz-Overhead wert.
- Kubernetes-Ressourcenanfragen ohne Ausnahme setzen. Ein nicht gesetzter
requests.cpuist nicht „unbegrenzt” – er ist eine Scheduling-Haftung, die CPU-Starvation auf Container-Ebene ermöglicht. - Starvation von Deadlock unterscheiden, bevor eingegriffen wird. Das Beenden und Neustarten eines ausgehungerten Prozesses behebt nicht das zugrunde liegende Scheduling-Ungleichgewicht; es entfernt nur vorübergehend das Symptom.
- Echtzeit-Prioritätszuweisungen prüfen (
SCHED_FIFO/SCHED_RR) auf jedem System, auf dem sie verwendet werden. Ein einzelner falsch konfigurierter Echtzeit-Prozess kann alle normal-priorisierten Workloads auf einem CPU-Kern auf unbestimmte Zeit aushungern. - Für Shared Web Hosting-Umgebungen sollten pro-Account CPU- und I/O-Kontingente auf cgroup-Ebene durchgesetzt werden, anstatt sich ausschließlich auf Rate-Limiting auf Anwendungsebene zu verlassen.
Häufig gestellte Fragen
Was ist der Unterschied zwischen Starvation und Deadlock in einem Betriebssystem?
Deadlock tritt auf, wenn zwei oder mehr Prozesse dauerhaft blockiert sind, wobei jeder eine Ressource hält, die der andere benötigt – kein Prozess macht Fortschritte. Starvation tritt auf, wenn ein Prozess trotz Ausführbarkeit dauerhaft vom Scheduler übergangen wird; andere Prozesse werden weiterhin normal ausgeführt. Deadlock erfordert das Aufbrechen einer zirkulären Abhängigkeit; Starvation erfordert die Korrektur der Scheduling-Richtlinie, typischerweise durch Implementierung von Aging oder Fair Queuing.
Wie verhindert der Linux CFS-Scheduler CPU-Starvation?
CFS verfolgt eine virtuelle Laufzeit (vruntime) für jeden Prozess und wählt immer den Prozess mit der niedrigsten vruntime zur Ausführung aus. Dies stellt sicher, dass Prozesse, die weniger CPU-Zeit erhalten, systematisch priorisiert werden, was eine unbegrenzte CPU-Starvation von SCHED_OTHER-Prozessen nahezu unmöglich macht. Echtzeit-Prozesse (SCHED_FIFO, SCHED_RR) umgehen CFS jedoch vollständig und können normale Prozesse weiterhin aushungern, wenn der sched_rt_runtime_us-Parameter nicht korrekt gesetzt ist.
Wie kann ich erkennen, ob ein Prozess auf einem Linux-Server ausgehungert wird?
Lesen Sie /proc/<PID>/schedstat, um die kumulative Run-Queue-Wartezeit zu prüfen. Überwachen Sie /proc/pressure/cpu auf PSI-Stall-Metriken. Verwenden Sie perf sched latency --sort max, um Prozesse mit ungewöhnlich hoher Scheduling-Latenz zu identifizieren. Prozesse im anhaltenden D-Zustand, die in der ps aux-Ausgabe sichtbar sind, weisen auf I/O-Starvation statt CPU-Starvation hin.
Beeinflusst Prozess-Starvation VPS- und Cloud-Server-Umgebungen anders als Bare-Metal?
Ja. Auf einem VPS kann Starvation sowohl auf der Hypervisor-Ebene (der Hypervisor-Scheduler verweigert Ihrer VM vCPU-Zeit) als auch innerhalb des Gast-OS auftreten. Starvation auf Hypervisor-Ebene ist für Standard-OS-Monitoring-Tools unsichtbar und erfordert hypervisor-spezifische Metriken oder merkliche Steal-Time (%st in der top-Ausgabe). Hohe Steal-Time – typischerweise über 5–10 % anhaltend – zeigt an, dass der Hypervisor die vCPU-Zyklen, auf die Ihre VM Anspruch hat, nicht liefert.
Was ist der schnellste Weg, um zu verhindern, dass ein bestimmter Prozess andere auf einem ausgelasteten Server aushungert?
Weisen Sie ihn der SCHED_IDLE-Scheduling-Klasse mit chrt -i -p 0 <PID> zu. Diese Klasse wird nur ausgeführt, wenn kein anderer ausführbarer Prozess existiert, und garantiert damit, dass sie keine andere Workload aushungern kann. Für I/O-intensive Hintergrundprozesse setzen Sie zusätzlich ihre I/O-Priorität auf die Idle-Klasse: ionice -c 3 -p <PID>. Die Kombination beider Maßnahmen eliminiert den Prozess als CPU- und I/O-Starvation-Quelle mit zwei Befehlen und ohne Anwendungsänderungen.
