İşletim Sistemlerinde Süreç Açlığı: Nedenler, Mekanizmalar ve Üretim Düzeyinde Çözümler
Süreç açlığı (process starvation), bir sürecin ilerleme kaydetmesi için ihtiyaç duyduğu CPU zamanından, bellekten veya I/O bant genişliğinden süresiz olarak yoksun bırakılması durumunda ortaya çıkar — kaynakların mevcut olmaması nedeniyle değil, zamanlama politikasının sürekli olarak diğer süreçleri tercih etmesi nedeniyle. Tüm rekabet eden süreçlerin engellendiği kilitlenmenin (deadlock) aksine, açlık sistemin işlevsel görünmesine izin verirken belirli iş yüklerini sessizce bozar veya durdurur.
Bu ayrım operasyonel açıdan önemlidir: açlığa uğrayan bir süreç çekirdek düzeyinde hata üretmez, çökme dökümü oluşturmaz ve standart uyarı eşiklerini tetiklemeyebilir — bu da onu çok kiracılı ve yüksek eşzamanlılıklı sunucu ortamlarındaki en sinsi performans patolojilerinden biri haline getirir.
Açlık Çekirdek Düzeyinde Gerçekte Ne Anlama Gelir
Bu terim kaynak ekolojisinden ödünç alınmıştır: bir süreç, sınırlı bir kaynak için sürekli olarak rekabette yenildiğinde “açlığa” uğrar. Modern işletim sistemlerinde Linux Completely Fair Scheduler (CFS), Windows NT öncelik kuyrukları ve BSD ULE zamanlayıcısının tümü açlığı önlemek için mekanizmalar uygular — ancak belirli koşullar altında üretim ortamında yine de ortaya çıkar.
Çekirdek düzeyinde açlık, sanal çalışma süresi‘nin (CFS terminolojisinde) veya bekleme süresinin hiçbir zaman yürütme için seçilmeden sınırsız biçimde büyüdüğü bir süreç olarak kendini gösterir. Süreç
TASK_RUNNINGTemel teknik ayrım:
- Kilitlenme (Deadlock): İki veya daha fazla süreç karşılıklı olarak engellenir; her biri diğerinin tuttuğu bir kaynağı bekler. Sistem bu görevlerde sıfır ilerleme kaydeder.
- Açlık (Starvation): Bir veya daha fazla süreç zamanlayıcı tarafından sürekli olarak atlanır. Diğer süreçler normal şekilde çalışmaya devam eder.
- Canlı Kilit (Livelock): Süreçler engellenmez ancak gerçek ilerleme kaydetmeden birbirlerine yanıt olarak sürekli durum değiştirir.
Süreç Açlığının Temel Nedenleri
Açlığı anlamak, yalnızca “sınırlı kaynaklar”ı bir neden olarak listelemek yerine onu üreten belirli mekanizmaları incelemeyi gerektirir.
1. Yaşlandırma Olmaksızın Statik Öncelik Tersine Çevirme
Öncelik tabanlı zamanlayıcıların çoğu, her sürece sabit veya yarı sabit bir öncelik atar. Düşük öncelikli bir süreç her zaman orta ve yüksek öncelikli görev akışı tarafından öncelenirse hiçbir zaman yürütülmez. Buradaki kritik başarısızlık modu, yaşlandırmanın yokluğudur — bir sürecin etkin önceliğinin beklediği süre uzadıkça artımlı olarak artırıldığı bir tekniktir. Yaşlandırma olmadan, yoğun bir sunucudaki düşük öncelikli bir arka plan işi süresiz olarak bekleyebilir.
Linux’ta
niceSCHED_FIFOSCHED_RRSCHED_FIFOSCHED_OTHER2. I/O Zamanlayıcılarında Haksız Kuyruklama
CPU açlığı iyi belgelenmiştir, ancak I/O açlığı eşit derecede yıkıcıdır ve çoğunlukla göz ardı edilir. Linux I/O zamanlayıcısı (tarihsel olarak CFQ, şimdi çekirdek sürümüne ve depolama türüne bağlı olarak BFQ veya mq-deadline), blok aygıtı isteklerinin sunulma sırasını yönetir. Veritabanı sunucularında ve günlük yoğun uygulamalarda yaygın olan ağır sıralı yazma iş yükleri altında, I/O zamanlayıcısı diğer süreçlerden gelen rastgele okuma isteklerini düşük önceliklendirebilir ve bu süreçleri disk erişiminden etkin biçimde yoksun bırakabilir.
Bu, birden fazla kiracının temel depolama altyapısını paylaştığı ve I/O çekişmesinin gerçek bir operasyonel endişe olduğu VPS Hosting ortamlarında sık karşılaşılan bir sorundur.
3. Bellek Baskısı ve OOM Killer
Fiziksel RAM tükendiğinde, Linux çekirdeğinin Bellek Yetersizliği (OOM) killer‘ı bir
oom_score4. Kilit Çekişmesi ve Mutex Açlığı
Çok iş parçacıklı uygulamalarda açlık, senkronizasyon ilkel düzeyinde ortaya çıkar. Bir mutex veya semafor, son giren ilk çıkar veya bekleyen iş parçacıkları arasında rastgele seçim gibi adil olmayan bir edinim politikası kullanıyorsa, kilit sık sık serbest bırakılsa bile belirli bir iş parçacığı sürekli olarak atlanabilir. Bu, işletim sistemi düzeyindeki zamanlamadan farklıdır ve tamamen kullanıcı alanında veya çekirdeğin senkronizasyon alt sisteminde gerçekleşir.
5. Ağ Bant Genişliği Açlığı
Konteynerleştirilmiş ve sanallaştırılmış ortamlarda, mevcut ağ bant genişliğinin tamamını tüketen bir süreç veya konteyner, diğer süreçleri ağ I/O’sundan yoksun bırakabilir. tc (trafik kontrolü) ve cgroups aracılığıyla trafik şekillendirme olmadan, tek bir kontrolden çıkmış süreç NIC verimini tekelleştirebilir.
Açlık vs. Kilitlenme vs. Canlı Kilit: Teknik Karşılaştırma
| Özellik | Açlık | Kilitlenme | Canlı Kilit |
|---|---|---|---|
| Sistem ilerlemesi | Evet (diğer süreçler çalışır) | Hayır (engellenen süreçler durur) | Görünürde (gerçek ilerleme yok) |
| Engellenmiş durum | Hayır (süreç çalıştırılabilir) | Evet (süreç kaynak bekler) | Hayır (süreç aktif) |
| Tutulan kaynak | Hayır | Evet (döngüsel tut-ve-bekle) | Hayır |
| Kendiliğinden çözülme | Bazen (yaşlandırma ile) | Hiçbir zaman (müdahale gerektirir) | Nadiren |
| Tespit zorluğu | Yüksek (açık hata yok) | Orta (döngü tespiti) | Yüksek (aktivite olarak görünür) |
| Birincil neden | Haksız zamanlama politikası | Döngüsel kaynak bağımlılığı | Reaktif durum değişikliği döngüleri |
| Linux çekirdek sinyali | Yok | Yok (soft lockup mümkün) | Yok |
Modern Zamanlayıcılar Açlığı Nasıl Ele Alır
Linux Completely Fair Scheduler (CFS)
Linux çekirdek 2.6.23’te tanıtılan CFS, her süreç için sanal çalışma süresini (vruntime) izleyerek açlığı ele alır. Zamanlayıcı her zaman en düşük vruntime’a sahip süreci seçer — yani daha az CPU süresi almış süreçler sistematik olarak önceliklendirilir. Bu tasarım,
SCHED_OTHERAncak CFS, gerçek zamanlı süreçlerden kaynaklanan açlığa karşı koruma sağlamaz.
SCHED_FIFOSCHED_RRSCHED_OTHER/proc/sys/kernel/sched_rt_runtime_usÖncelik Yaşlandırma
Klasik yaşlandırma algoritmaları, bir sürecin beklediği her zamanlama döngüsü için etkin önceliğini sabit bir miktarda artırır. Etkin öncelik en yüksek seviyeye ulaştığında, sürecin yürütülmesi garanti edilir. Çalıştıktan sonra önceliği temel değerine sıfırlanır. Bu, öncelik tabanlı açlığa yönelik ders kitabı çözümüdür ve Windows NT, Solaris ve eski Linux zamanlayıcılarında çeşitli biçimlerde uygulanmaktadır.
Adil Kuyruklama ve Ağırlıklı Adil Kuyruklama (WFQ)
Ağ ve I/O kaynakları için Ağırlıklı Adil Kuyruklama, her akışa veya sürece ağırlığıyla orantılı bir bant genişliği payı atar. Yüksek ağırlıklı bir akış daha fazla trafik üretse bile, düşük ağırlıklı akışlara minimum hizmet oranı garanti edilir. Linux bunu
tcÜretim Linux Sistemlerinde Açlığı Teşhis Etme
Açlığı tespit etmek, birden fazla veri kaynağının eş zamanlı olarak ilişkilendirilmesini gerektirir.
CPU Zamanlama Analizi
# 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 -20schedstatrun_delayBellek Açlığı Göstergeleri
# 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 Açlığı Tespiti
# 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}'DDÜretim Kalitesinde Çözümler ve Azaltma Stratejileri
Kaynak İzolasyonu için cgroups v2 Uygulama
Kontrol Grupları (cgroups v2), çok süreçli ve konteynerleştirilmiş ortamlarda açlığı önlemek için en sağlam mekanizmayı sağlar. Süreç gruplarına açık CPU, bellek ve I/O kotaları atayarak sistem yükünden bağımsız olarak minimum kaynak tahsislerini garanti edersiniz.
# 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.procscgroups v2’deki CPU ağırlığı 1–10000 aralığını kullanır; varsayılan değer 100’dür. 200 ağırlıklı bir süreç grubu, çekişme altında 100 ağırlıklı bir grubun iki katı CPU payını alır.
Linux Zamanlayıcısını İş Yükünüze Göre Ayarlama
# 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_usSüreç Başına Uygun Zamanlama Politikaları Uygulama
# 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.shSCHED_IDLEchrt -iI/O Zamanlayıcı Seçimi
# 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), her sürece orantılı bir disk bant genişliği payı garanti ederek I/O açlığını önlemek için özel olarak tasarlanmıştır. Paylaşımlı hosting ve veritabanı sunucusu ortamları için önerilen zamanlayıcıdır.
tc ile Ağ Bant Genişliği Kontrolü
# 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 10Bu yapılandırma, bant genişliği mevcut olduğunda tam 1 Gbps bağlantı kapasitesine kadar ani kullanıma izin verirken her sınıfa minimum 100 Mbps garanti eder.
Bellek Aşırı Taahhüt ve Takas Ayarı
# 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_ratiovm.swappiness=10Sanallaştırılmış ve Konteynerleştirilmiş Ortamlarda Açlık
Hipervizörler (KVM, VMware ESXi, Hyper-V) çalıştıran Dedicated Servers‘da açlık iki farklı katmanda ortaya çıkabilir:
Hipervizör düzeyinde açlık: Bir sanal makine, hipervizör zamanlayıcısı tarafından CPU döngülerinden yoksun bırakılır. KVM, vCPU zamanlaması için ana çekirdeğin CFS’ini kullanır; bu, daha düşük CPU payı ağırlığına sahip bir VM’nin çekişme altında daha yüksek ağırlıklı VM’ler tarafından açlığa uğratılabileceği anlamına gelir. VMware’in DRS’si (Distributed Resource Scheduler) bunu kontrol etmek için paylar, rezervasyonlar ve limitler kullanır.
Misafir işletim sistemi düzeyinde açlık: VM’nin kendisinde, aynı işletim sistemi düzeyindeki zamanlama dinamikleri geçerlidir. Açık kaynak limitleri olmadan Docker veya Kubernetes altında çalışan konteynerleştirilmiş bir iş yükü, misafir işletim sisteminin CPU’sunu ve belleğini tekelleştirebilir ve birlikte konumlanan konteynerleri açlığa uğratabilir.
Kubernetes ortamları için pod özelliklerinde her zaman hem
requestslimitsresources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"requestsVeritabanı ve Uygulama Sunucularında Açlık
Veritabanı motorları, işletim sistemi zamanlayıcısından bağımsız kendi dahili zamanlayıcılarını uygular. PostgreSQL, her arka uç sürecinin işletim sistemi kaynaklarını normal şekilde rekabet ettiği bağlantı başına süreç modeli kullanır; ancak veritabanı içindeki kilit çekişmesi (satır düzeyinde kilitler, danışma kilitleri) belirli sorguların kilit edinimi için süresiz olarak beklediği uygulama düzeyinde açlığa neden olabilir.
MySQL/InnoDB, yapılandırılabilir eşzamanlılık limitlerine sahip bir iş parçacığı havuzu kullanır (
innodb_thread_concurrency2 × number of CPU coresWeb sunucuları için Nginx ve Apache‘nin farklı açlık profilleri vardır. Nginx’in olay güdümlü modeli doğası gereği çalışan açlığına karşı dirençlidir; ancak yukarı akış bağlantı havuzu tükenmesi (örneğin PHP-FPM veya bir arka uç API’sine) uygulama düzeyinde açlık yaratır. Apache’nin prefork MPM’i
MaxRequestWorkersBu değerlendirmeler, birden fazla sitenin PHP-FPM çalışan havuzları ve MySQL bağlantı limitleri için rekabet ettiği paylaşımlı web hosting iş yükleri için VPS with cPanel yapılandırırken doğrudan ilgilidir.
Açlık Önleme için İzleme Altyapısı
Reaktif teşhis, üretim sistemleri için yetersizdir. Proaktif bir izleme yığını şunları içermelidir:
İzlenecek Prometheus + Node Exporter metrikleri:
- — CPU başına kümülatif CPU çalışma kuyruğu bekleme süresi
node_schedstat_waiting_seconds_total - — bellek baskısını gösteren büyük sayfa hataları
node_vmstat_pgmajfault - — I/O kuyruk doygunluğu
node_disk_io_time_weighted_seconds_total - — Linux PSI (Pressure Stall Information) CPU baskısı
node_pressure_cpu_waiting_seconds_total - — PSI bellek tam durma süresi
node_pressure_memory_full_seconds_total
Linux PSI (çekirdek 4.20’den itibaren mevcut), çekirdekte mevcut olan en doğrudan açlık göstergesidir. Görevlerin CPU, bellek veya I/O kaynakları için beklerken durduğu sürenin yüzdesini raporlar:
# Real-time PSI monitoring
cat /proc/pressure/cpu
cat /proc/pressure/memory
cat /proc/pressure/ioÇıktı biçimi:
some avg10=X.XX avg60=X.XX avg300=X.XX total=NNNNsomeavg60VPS Control Panels veya özel sunucu yığınlarını yöneten ekipler için PSI metriklerini Grafana panolarına entegre etmek, açlık kullanıcıya yönelik performansı düşürmeden önce erken uyarı sağlar.
Pratik Karar Matrisi: Doğru Açlık Karşıtı Mekanizmayı Seçme
| Belirti | Kaynak Türü | Önerilen Araç | Yapılandırma Hedefi |
|---|---|---|---|
| Arka plan işleri hiç tamamlanmıyor | CPU | SCHED_IDLEnice +19 | Arka plan CPU rekabetini ortadan kaldır |
| Yük altında etkileşimli gecikme artışları | CPU | CFS ayarı + cgroups v2 CPU ağırlığı | Etkileşimli süreç payını garanti et |
| Veritabanı sorguları zaman aşımına uğruyor | CPU + Kilit | innodb_thread_concurrency | Kilit bekleme süresini sınırla |
| Disk yoğun işler web sunumunu engelliyor | I/O | BFQ zamanlayıcı + cgroups v2io.weight | Orantılı I/O tahsisi |
| Yük altında konteyner OOM sonlandırmaları | Bellek | cgroups v2memory.minvm.swappiness | Minimum yerleşik belleği garanti et |
| Ağ yoğun süreç diğerlerini açlığa uğratıyor | Ağ | tc | Sınıf başına bant genişliği garantisi |
| VM hipervizör tarafından açlığa uğratılıyor | vCPU | Hipervizör CPU rezervasyonları/payları | Minimum vCPU döngülerini rezerve et |
Temel Teknik Çıkarımlar
- Karma iş yüklü sunucular için varsayılan zamanlamaya asla güvenmeyin. Gecikme hassasiyetlerine ve iş önceliklerine göre,
chrtve cgroups v2 kullanarak süreçleri açıkça sınıflandırın.nice - PSI izlemeyi etkinleştirin () tüm üretim Linux sistemlerinde. Çekirdekteki en doğru gerçek zamanlı açlık göstergesidir ve neredeyse sıfır ek yük getirir.
/proc/pressure/* - Dönen diskler için BFQ kullanın ve çok kiracılı ortamlarda karma rastgele/sıralı iş yüklerine hizmet eden herhangi bir NVMe aygıtı için. Adalet garantileri, marjinal verim ek yüküne değer.
- Kubernetes kaynak isteklerini istisnasız ayarlayın. Ayarlanmamış bir“sınırsız” değildir — konteyner düzeyinde CPU açlığını mümkün kılan bir zamanlama yüküdür.
requests.cpu - Müdahale etmeden önce açlığı kilitlenmeden ayırt edin. Açlığa uğramış bir süreci öldürüp yeniden başlatmak, temel zamanlama dengesizliğini düzeltmez; yalnızca belirtiyi geçici olarak ortadan kaldırır.
- Gerçek zamanlı öncelik atamalarını denetleyin (/
SCHED_FIFO) kullanıldıkları herhangi bir sistemde. Yanlış yapılandırılmış tek bir gerçek zamanlı süreç, bir CPU çekirdeğindeki tüm normal öncelikli iş yüklerini süresiz olarak açlığa uğratabilir.SCHED_RR - Shared Web Hosting ortamları için, yalnızca uygulama katmanı hız sınırlamasına güvenmek yerine cgroup düzeyinde hesap başına CPU ve I/O kotaları uygulayın.
Sıkça Sorulan Sorular
Bir işletim sisteminde açlık ile kilitlenme arasındaki fark nedir?
Kilitlenme, iki veya daha fazla sürecin kalıcı olarak engellendiğinde ortaya çıkar; her biri diğerinin ihtiyaç duyduğu kaynağı tutar — hiçbir süreç ilerleme kaydetmez. Açlık, bir sürecin çalıştırılabilir olmasına rağmen zamanlayıcı tarafından sürekli olarak atlandığında ortaya çıkar; diğer süreçler normal şekilde yürütülmeye devam eder. Kilitlenme, döngüsel bir bağımlılığın kırılmasını gerektirir; açlık, zamanlama politikasının düzeltilmesini gerektirir; bu genellikle yaşlandırma veya adil kuyruklama uygulanarak yapılır.
Linux CFS zamanlayıcısı CPU açlığını nasıl önler?
CFS, her süreç için bir sanal çalışma süresi (vruntime) izler ve her zaman yürütme için en düşük vruntime’a sahip süreci seçer. Bu, daha az CPU süresi alan süreçlerin sistematik olarak önceliklendirilmesini sağlar ve
SCHED_OTHERSCHED_FIFOSCHED_RRsched_rt_runtime_usBir Linux sunucusunda bir sürecin açlığa uğrayıp uğramadığını nasıl tespit edebilirim?
Kümülatif çalışma kuyruğu bekleme süresini kontrol etmek için
/proc/<PID>/schedstat/proc/pressure/cpuperf sched latency --sort maxps auxDSüreç açlığı VPS ve bulut sunucu ortamlarını bare metal’den farklı şekilde etkiler mi?
Evet. Bir VPS’de açlık hem hipervizör katmanında (hipervizör zamanlayıcısının VM’nize vCPU süresi vermemesi) hem de misafir işletim sistemi içinde ortaya çıkabilir. Hipervizör düzeyindeki açlık, standart işletim sistemi izleme araçlarına görünmez ve hipervizöre özgü metrikler veya fark edilebilir çalma süresi gerektirir (
top%stYoğun bir sunucuda belirli bir sürecin diğerlerini açlığa uğratmasını önlemenin en hızlı yolu nedir?
chrt -i -p 0 <PID>SCHED_IDLEionice -c 3 -p <PID>