Düşük bellek koşulları altında OOM sonlandırıcı devreye girer ve zaman içinde gelişen bir dizi heuristic yöntem kullanarak bir işlem (process) seçer ve sonlandırır. Bu başka bir işlemin seçilip sonlandırılmasını istemiş kullanıcılar için oldukça can sıkıcı olabilir. Ayrıca sonlandırılan bu işlem, sistem açısında da önemli bir işlem de olabilir. Yanlış işlemlerin zamansız sonlandırılmasının önüne geçmek adına, pek çok geliştirici OOM işlem sonlandırma faaliyetleri üzerinde daha fazla kontrolleri olması gerektiği kanısındadır.
Neden OOM sonlandırıcı?
Ana dağıtımların çekirdekleri (kernels) /proc/sys/vm/overcommit_memory varsayılan değerini 0 olarak belirler, bu şu anlama geliyor, çalışan işlemler sistemde o anda kullanıma hazır bulunan boş bellekten fazlasını talep edebilirler. Bunun yapılması tahsis edilen belleğin hemen kullanılmıyor olmasına ve işlemlerin ayırdıkları belleğin tamamını yaşamları boyunca kullanmıyor olmalarına dayanmaktadır. "Overcommit" olmadan sistem bir kısmını israf ederek de olsa hafızasını tam olarak kullanamazdı. OOM riskleri pahasına "Overcommit" yöntemi ile sistem belleğini daha verimli bir şekilde kullanır. Belek savurganı programlar sistemin tüm belleğini tüketerek durmasına neden olabilir. Kullanıcı işlemleri için tek bir bellek sayfasının ayrılamadığı belleğin bu kadar düşük olduğu durumlar, OOM sonlandırıcının devreye girmesine ve sistemin geri kalanının yararı için kurbanlık kuzuyu belirlemesine yol açar.
Kullanıcılar ve sistem yöneticileri genellikle OOM işlem sonlandırıcının davranışını kontrol etmenin yollarını istemişlerdir. Sistemdeki önemli işlemlerin sonlandırılmasını engellemek ve sonlandırılacak işlemlerin sırasının belirlenmesi kontrolünü kolaylaştırmak için /proc/<pid>/oom_adj ucu sunulmuştur. oom_adj geçerli değerleri -17 ile +15 arasındadır. Değer ne kadar büyükse OOM sonlandırıcının seçiminde o kadar öncelikli olur. Değer -17 ise OOM sonlandırıcı sürecinde ele alınmaz.
Kimler Elverişsiz?
Bellek tükenmesi durumlarında bir işlemin sonlandırılacak işlem olarak seçilmesi elverişsizlik skoruna (oom_score) bağlıdır. Elverişsizlik skoru kabaca işlemin tükettiği bellek miktarı çalıştığı canlı kaldığı süre ve oom_adj değerine bağlı olarak ne kadar çok bellek tüketti isen o kadar çok ne kadar süredir çalışıyorsan o denli az elverişsiz olacak şekilde sistem tarafından belirlenerek /proc/<pid>/oom_score a yansıtır.
Sistemin swapoff() çağrısında (bu çağrı ile bir takas dosyası sistemden kaldırılır) yer alan herhangi bir şanssız işlem sonlandırılmak üzere seçilecek ilk işlem olur. Geriye kalan işlemlerin ilk bellek boyutları orijinal elverişsizlik skoru haline gelir. Eğer aynı belleği paylaşmıyorlarsa kendilerine bağlı alt işlemlerin (child process) kullandıkları bellek miktarının yarısı ana işlemin (parent process) elverişsizlik skoruna toplanır. Böylece salkımlı (forking) işlemler sonlandırılmaya birincil aday olurlar. Fazla bellek tüketen bir alt işlemi bulunan ana işlem sonlandırıcı tarafından alt işlem parçasına göre daha az tercih edilir olacaktır. Son olarak önemli işlemlerin korunması adına aşağıdaki kurallar uygulanır :
- - işlemin "nice" değeri 0 dan büyükse skoru 2 ile çarpılır.
- - superuser veya donanıma doğrudan erişen ( CAP_ SYS_ADMIN ,CAP_SYS_RESOURCE veya CAP_SYS_RAWIO ) bir görev ise skoru 4 e bölünür. Donanıma doğrudan erişen bir superuser görevin skoru 16 ya bölünerek bu kümülatif olarak yapılır.
- - Bir "cpuset" inde bir oom durumu oluşur ve işaretli görev o sete ait değilse skoru 8 e bölünür.
- - Son olarak ortaya çıkan skor değeri 2 üzeri oom_adj değeri ile çarpılır.
Böylece en yüksek elverişsizlik skoruna sahip görev (task) seçilerek bağlı alt (child) işlemleri sonlandırılır. Eğer görevin bağlı alt işlemleri yoksa oluşan bir oom durumunda kendisi de sonlandırılabilir.
OOM-Killer politikalarının kullanıcı alanına taşınması
oom_score zamanla değişen dinamik bir değer olduğundan sistem yönetimi için gereken farklı ve dinamik politikalar için yeterince esnek değildir. Bir oom durumunda hangi sürecin sonlandırılacağının belirlenmesi oldukça zordur. Sistem yönetimi yaratılan ve sonlanan her işlemin skorunu ayarlamak zorundadır,bu sürekli yeni işlemlerin başladığı ve sonlandığı bir sistemde oldukça zordur. Oom-killer politikalarının kolay uygulanabilmesi için Evgeniy Polyakov isme dayanan bir çözüm önermiştir. Onun yaması (patch) sonlandırılacak ilk işlem ismi /proc/sys/vm/oom_victim içinde bulunanlardan biri olacaktır. İsim tabanlı çözümün sınırlamaları :
- görev adı güvenilir bir işaretçi değildir.
- hiyerarşi olasılığına rağmen bu yaklaşım ile bir seferde sadece bir isim belirlenebilmektedir.
- isimleri aynı olmasına karşın farklı "binary" lerin olabilmesi.
- oom_victim de belirtilen sürecin bulunamaması durumunda bir sonrakine geçilmesi ile pek çok tarama gerektirmektedir.
Alan Cox bu çözümü beğenmiyor ve "container" ların bu sorunun çözümü için en uygun yol olduğunu öneriyordu. Bu öneriye karşılık olarak, Nikanth Karthikesan'ın katkısı olan "oom-killer controller" ı bellek yetersizliği durumlarında bir sıra işlemin sonlandırılabilmesi kontrolünü sağlıyordu. Bu yama (patch) ile oom.priority sahasına sahip bir oom kontrol grubu (cgroup) sunuldu ve sonlandırılacak işlem en yüksek oom.priority değerine sahip işlemlerin arasından seçildi.
Gömülü (Embedded) Sistemlerde Düşük BellekYönetimi
Oom-killer çok düşük bellek koşulları oluşana değin devreye girmiyor ve geç kalıyordu, Android geliştiricileri düşük bellek durumlarında daha büyük ölçüde kontrole ve boş bellek tükenmeden devreye girecek bir çözüme ihtiyaç duydular. Böylece birden fazla düşük bellek eşiği bulunan "lowmemory" sürücüsü (driver) ortaya çıktı. Bir düşük bellek durumunda ilk alt eşiğe ulaşıldığında arka plan (background) işlemler sorundan haberdar edildi. Bu işlemler sonlanmadılar bunun yerine durumlarını (state) kaydettiler. Bu durum görevler arasında geçişlerde bir miktar gecikmeye neden olur, çünkü uygulamanın aktive olduğunda durumunu (state) geri yüklemesi gerekir. Düşük bellek baskısı arttıkça "lowmemory" sonlandırıcı durumları kaydedilmiş arka plan uygulamalarını daha sonra ön plandaki uygulamaları sonlandırır.
Android telefonunuzu "root" ladıysanız bu düşük alt bellek eşik (minfree) değerlerini değiştirebilir bu sayede belirttiğiniz eşik değeri ile daha erken yada geç "lowmemory" sonlandırıcının devreye girmesini sağlayabilirsiniz. Android market de "root" lanan cihazlarda bu değerleri değiştirmenize imkan tanıyan çeşitli uygulamalar mevcut , benim kullanıp memnun kaldığım uygulama
Auto Memory Manager
market://search?q=pname:com.lim.android.automemman
Afiyet bal şeker olsun.
Kaynaklar
35ff3bd5-691c-4a85-8f1f-f294413c5d65|0|.0