Çekirdek geliştiricisi değilim, ancak yıllarca bu meseleyi felsefe ederek geçirdim çünkü bu soooo'yu defalarca karşıladım. Aslında tüm durum için bir metafor buldum, o yüzden size söyleyeyim. Hikayemde "takas" gibi şeylerin var olmadığını varsayacağım. Bu günlerde 32 GB RAM'le takas yapmak pek mantıklı gelmiyor.
Suyun her binaya borularla bağlandığı ve kasabaların kapasiteyi yönetmesi gereken bir mahallenizi hayal edin. Saniyede yalnızca 100 birim su ürettiğinizi varsayalım (ve kullanılmayan tüm kapasite boşa gider çünkü rezervuar tankınız yoktur). Her ev (ev = küçük bir uygulama, bir terminal, saat gereci, vb.) Saniyede 1 birim su gerektirir. Bunların hepsi güzel ve güzel çünkü nüfusunuz 90 gibi, bu yüzden herkes yeterli miktarda su alıyor.
Şimdi belediye başkanı (= siz) büyük bir restoran açmak istediğinize karar verir (= tarayıcı). Bu restoran birden fazla aşçıya ev sahipliği yapacak (= tarayıcı sekmeleri). Her aşçı saniyede 1 birim suya ihtiyaç duyar. 10 aşçıyla başlıyorsunuz, bu nedenle tüm mahalle için toplam su tüketimi hala iyi olan 100 birim su.
Şimdi eğlenceli şeyler başlıyor: restoranınızdaki toplam su ihtiyacını (101) sahip olmayan bir aşçı daha işe alıyorsunuz. Bir şey yapmalısın.
Su yönetimi (= çekirdek) 3 seçeneğe sahiptir.
1. İlk seçenek, son zamanlarda suyu kullanmayan evlerin hizmetini kesmektir. Bu iyi, ancak bağlantısı kesilen ev suyu tekrar kullanmak istiyorsa, tekrar uzun kayıt işleminden geçmeleri gerekecek. Yönetim, daha fazla su kaynağını boşaltmak için birden fazla evin bağlantısını kesebilir. Aslında, son zamanlarda su kullanmayan tüm evlerin bağlantılarını kesecekler ve böylece bir miktar serbest su her zaman kullanılabilir durumda kalacaklar.
Şehriniz çalışmaya devam etse de, dezavantajı, ilerlemenin durma noktasına gelmesidir. Zamanınızın çoğu, hizmetinizi eski durumuna getirmek için su yönetimini beklemeye harcanır.
Bu, çekirdeğin dosya destekli sayfalarla yaptığı şeydir. Büyük bir yürütülebilir dosyayı çalıştırırsanız (krom gibi), dosyası belleğe kopyalanır. Belleği az olduğunda veya yakın zamanda erişilmemiş parçalar varsa, çekirdek bu parçaları düşürebilir, çünkü bunları yine de diskten yeniden yükleyebilir. Bu aşırı yapılırsa, masaüstünüzü durdurur, çünkü her şey sadece disk IO'yu bekleyecektir. Çok fazla GÇ yapmaya başladığınızda çekirdeğin en az kullanılmış sayfaların da düşeceğini unutmayın. Bu nedenle, DVD görüntüleri gibi birkaç büyük dosyayı kopyaladıktan sonra arka plan uygulamasına geçme zaman alır.
Bu benim için en sinir bozucu davranış, çünkü can sıkıntısından nefret ediyorum ve bunun üzerinde hiçbir kontrolünüz yok. Kapatmak güzel olurdu. Ben çizgileri boyunca bir şey düşünüyorum
sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c
ve sonra vm_swappiness işlevini, bunu devre dışı bırakmak için -1 olarak ayarlayabilirsiniz. Bu benim küçük testlerimde oldukça işe yaradı ama ne yazık ki ben çekirdek geliştiricisi değilim, bu yüzden kimseye göndermedim (ve açıkça yukarıdaki küçük değişiklik tamamlanmadı).
2.Yönetim yeni aşçıların su talebini reddedebilir. Bu başlangıçta iyi bir fikir gibi geliyor. Ancak iki dezavantajı var. İlk olarak, kullanmasalar bile çok fazla su aboneliği isteyen şirketler var. Bunu yapmanın olası bir nedeni, fazladan suya ihtiyaç duyduklarında su yönetimiyle konuşmanın genel giderinden kaçınmaktır. Günün zamanına bağlı olarak su kullanımları artar. Örneğin restoranın durumunda, öğle vakti öğle vakti şirkete kıyasla suya daha çok ihtiyaç duyuyor. Bu yüzden kullanabilecekleri tüm suyu talep ediyorlar ancak bu gece yarısı boyunca su tahsislerini boşa harcıyor. Buradaki sorun, tüm şirketlerin en üst düzeyde kullandıklarını doğru bir şekilde öngörememeleridir, bu yüzden daha fazla talep etmek için endişe etmeyecekleri umuduyla çok daha fazlasını talep ederler.
Java'nın sanal makinesinin yaptığı şey şudur: başlangıçta bir miktar bellek ayırır ve bundan sonra çalışır. Varsayılan olarak, çekirdek yalnızca Java uygulamanız gerçekten kullanmaya başladığında belleği ayırır. Ancak aşırı ödemeyi devre dışı bırakırsanız, çekirdek rezervasyonu ciddiye alır. Tahsisin ancak kaynaklara gerçekten sahip olması durumunda başarılı olmasına izin verecektir.
Ancak, bu yaklaşımla ilgili daha ciddi bir sorun daha var. Diyelim ki bir şirket her gün (10'ar adım yerine) tek bir birim su talep etmeye başladı. Sonunda 0 ücretsiz ünitenizin olduğu bir duruma ulaşacaksınız. Şimdi bu şirket daha fazlasını tahsis edemeyecek. Sorun değil, zaten büyük şirketleri önemseyen. Ancak sorun şu ki, küçük evler de daha fazla su talep edemeyecek! Ani turist akını ile başa çıkmak için küçük umumi banyolar yapamazsınız. Yakındaki ormandaki yangına acil su sağlayamazsınız.
Bilgisayar terimleriyle: Aşırı düşük hafıza koşullarında çok düşük bellek durumlarında, yeni bir xterm açamazsınız, makinenize ssh alamazsınız, aramak için yeni bir sekme açamazsınız düzeltmeleri. Başka bir deyişle, aşırı ödemeyi devre dışı bırakmak da masaüstünüzün hafızası azaldığında işe yaramaz hale getirir.
3. İşte bir şirket çok fazla su kullanmaya başladığında sorunu çözmenin ilginç bir yolu. Su yönetimi onu havaya uçurur! Kelimenin tam anlamıyla: restoranın sitesine gider, dinamitleri içine atar ve patlayana kadar bekler. Bu, kasabanın su ihtiyacını anında çok azaltacak, böylece yeni insanlar taşınabiliyor, ortak banyolar yaratabiliyorsunuz. Belediye başkanı olarak, restoranın bu sefer daha az su gerektireceği umuduyla yeniden inşa edebilirsiniz. Örneğin, içeride çok fazla kişi varsa, insanlara restoranlara girmemelerini söylersiniz (örneğin, daha az tarayıcı sekmesi açarsınız).
Bu aslında, çekirdeğin tüm seçenekleri tükendiğinde ve belleğe ihtiyacı olduğunda yaptığı şeydir: OOM katilini çağırır. Büyük bir uygulamayı seçer (birçok sezgiye dayanarak) ve onu öldürür, çok fazla bellek boşaltır, ancak duyarlı bir masaüstünü korur. Aslında Android çekirdeği bunu daha da agresif bir şekilde yapar: bellek az olduğunda en son kullanılan uygulamayı öldürür (yalnızca son çare olarak kullanan stok çekirdeğine kıyasla). Bu Android Viking Katili denir.
Bence bu, sorunun en basit çözümlerinden biri: bence bundan daha fazla seçeneğe sahip değilsin, neden daha sonra başaramazsın, değil mi? Sorun, çekirdeğin OOM katilini çağırmaktan kaçınmak için oldukça fazla iş yapmasıdır. Bu yüzden masaüstünüzün çok yavaş olduğunu ve çekirdeğin bu konuda hiçbir şey yapmadığını görüyorsunuz. Neyse ki OOM katilini kendiniz çağırmak için bir seçenek var! İlk önce, sihirli sysrq tuşunun etkinleştirildiğinden emin olun (örn. echo 1 | sudo tee
/proc/sys/kernel/sysrq
), Sonra çekirdeğin hafızanın azaldığını hissettiğinizde, sadece Alt + SysRQ, Alt + f tuşlarına basın.
Tamam, tüm bunlar güzel ama denemek ister misin? Düşük hafıza durumu yeniden üretilmesi çok kolaydır. Bunun için çok basit bir uygulama var. İki kez çalıştırman gerekecek. İlk çalıştırmada ne kadar boş RAM bulunduğunu, ikinci çalıştırmada ise düşük bellek durumu yaratacaktır. Bu yöntemin takas seçeneğinin devre dışı bırakıldığını varsaydığını unutmayın (örn sudo swapoff -a
. A ). Kod ve kullanım şu şekildedir:
// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv)
{
int limit = 123456789;
if (argc >= 2) {
limit = atoi(argv[1]);
}
setbuf(stdout, NULL);
for (int i = 1; i <= limit; i++) {
memset(malloc(1 << 20), 1, 1 << 20);
printf("\rAllocated %5d MiB.", i);
}
sleep(10000);
return 0;
}
Ve işte bunu nasıl kullanıyorsunuz:
$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed
İlk çağrı 31.118 MiB boş RAM'e sahip olduğumuzu tespit etti. Ben de başvuruya 31.110 MiB RAM tahsis etmesini söyledim, böylece çekirdek onu öldürmeyecek ama neredeyse bütün hafızamı yer. Sistemim dondu: fare imleci bile tomurcuklanmadı. Alt + SysRQ, Alt + f tuşlarına bastım ve eatmem sürecimi öldürdü ve sistem restore edildi.
Düşük bellek durumunda ne yaptığımızı seçeneklerimizi kapsamamıza rağmen, en iyi yaklaşım (diğer tehlikeli durumlar gibi) ilk etapta bunu önlemektir. Bunu yapmanın birçok yolu vardır. Gördüğüm yaygın yollardan biri, yaramazlık uygulamalarını (tarayıcılar gibi) sistemin geri kalanından farklı kaplara koymak. Bu durumda tarayıcı masaüstünüzü etkileyemez. Ancak önlemenin kendisi, sorunun kapsamı dışında olduğundan yazmam.
TL; DR: Şu anda, sayfalamayı tamamen önlemenin bir yolu olmamasına rağmen, aşırı ödemeyi devre dışı bırakarak tam sistem durmasını azaltabilirsiniz. Ancak sisteminiz düşük bellek durumu sırasında yine de kullanılamayacak, ancak farklı bir şekilde olacaktır. Yukarıdakilerden bağımsız olarak, düşük bellek durumunda çekirdek seçiminin büyük bir işlemini öldürmek için Alt + SysRQ, Alt + f tuşlarına basın. Sisteminiz yanıtını birkaç saniye sonra geri yüklemelidir. Bu, sihirli sysrq anahtarının etkin olduğunu varsayar (varsayılan olarak değildir).