4 Nisan 2012 Çarşamba

Virtual Memory nedir? - I


Virtual memory hem C programlamada hem de sistem yöneticiliğinde muhattap olduğumuz bir konu. Virtual memory'nin çalışma prensiplerini bilmek bazı durumlarda yazılan uygulamanın ya da genel olarak sistemin verimli çalışması için çok önemli olabiliyor.

Temelde virtual memorynin yaptığı iki iş var:
  1. Processlere kendilerine ait sürekli bir hafıza alanını kullanıyorlarmış gibi hissettirmek
  2. Pagefile/swap kullanarak aktif olmayan uygulamaların fiziksel RAM'i gereksiz yere işgal etmesini engellemek
Virtual memory'den bahsetmeden önce bazı kavramları bir kaç cümle ile açıklamakta fayda var.



Fiziksel memory (RAM) ve swapdisk/pagefile: RAM, CPU'nun (ve bazı çevre birimlerinin) doğrudan eriştiği hızlı depolama alanıdır. Fakat belli sınırları olduğundan dolayı pahalı bir kaynaktır, mümkün olduğunca verimli kullanılması gerekir. Bu yüzden çoğu işletim sisteminde CPU (uygulamalar da denebilir) tarafından sık sık erişilmeyen memory alanları geçici olarak diske yazılır, bu alanlar RAM'e daha acil ihtiyacı olan  uygulamalara verilir. Linux'ta swap partitionları, Windows'ta ise pagefile disk üzerinde bu iş için özel olarak ayrılmış yerlerdir. (pagefile ve swap partition konfigürasyonu ile ilgili ayrı bir yazım var, bir ara ekleyeceğim.)

Page: Virtual memorynin en küçük parçasına page denir. Günlük hayatta kullandığımız sistemlerde 4Kb boyutundadır. Belleğe ihtiyacı olan bir uygulama bellek istediğinde 4Kb'tan daha az verilemez. Eğer bir uygulamanın kullanmadığı bellek geri alınacaksa ya da fiziksel RAMden çıkartılıp diske yazılacaksa 4Kb'lık parçalar halinde yapılmak zorundadır. Memory kullanımını verimli hale getirmek için yazılmış bazı özel kütüphaneler uygulamaya ait pagelerin içindeki daha küçük boyutlardaki memory alanlarını düzenlemek için kullanılabilirler.

Paging: Pagelerin fiziksel memoryden kopartılıp diskte ayrılmış alanlara yazılması (ya da tersi) işlemidir. Bazen swapping de denir. Eğer bir sistem sık sık paging yapıyorsa ciddi performans sorunlarıyla karşılaşır. Bu konunun detaylarını 4. yazıda bulabilirsiniz.

x86 ve x86_64/amd64 mimarilerinde memory management işletim sistemi ve CPU içindeki MMU işbirliği ile gerçekleştirilir. Tüm processler belleği kullanırken sanki tüm bellek kendisilerininmiş gibi görür. Arkaplanda ise tüm sanallaştırmalarda olduğu gibi memory manager gerçek bellek alanları ile processlerin okuyup yazdıklarını sandıkları adres alanları arasında bir mapping yapar. Bu mapping uygulamaya transparan olduğundan uygulamanın kendisi gerçekte belleğin neresine yazdığını, yazdığı yerin sağında solunda kimin verisi olduğunu bilemez.


Virtual memory bir güvenlik katmanı olarak da aşağıdaki işlere yarar:
  1. Uygulamaların başka bir uygulamanın bilgilerine erişmesini ya da yanlışlıkla silmesini engeller.
  2. Sayfalara ayrı ayrı erişim hakları verilebilir. Process'e ait sayfaların içinde data bölümündeki kodların çalıştırılmasını engelleyerek stack overflow tarzı saldırıları zorlaştırır. (PAE kullanabilen ya da 64bit CPUlar için NX/ND biti ile, PAE'siz 32bit CPUlarda yazılım kullanarak (örneğin PaX))
Bir karşılaştırma yapmak için zamanında oldukça popüler olan Amiga'dan bahsedebiliriz. Amiga'da virtual memory gibi bir konsept yok. Memory kullanmak isteyen processler exec kütüphanesi vasıtası ile işletim sisteminden bellek istiyorlar. Eğer aldıkları alanın dışına taşarlarsa başka processlerin verilerini kirletebiliyorlar. İyi yanı processler arası iletişim  için ortak bir alan belirlemek yerine doğrudan birbirlerinin alanlarına yazabiliyorlar, driverlarla muhattap olmadan ve CPU'yu yormadan doğrudan donanımın kullandığı bellek alanlarına yazarak donanımı kullanabiliyorlar.

x86'da 32 bit adresler ile en fazla 4 GB memory adreslenebiliyordu, bunun üzerinde adresleme yapacaksanız PAE destekleyen bir CPU ve kernel kullanmanız gerekiyordu. Bunun dışında kernel memorynin altında mı üstünde mi duracak, ne kadarı kernel memory olacak ne kadarı userspace'e kalacak gibi dertler vardı. Bunlara bu yazıda değinmiyorum.

Geri kalanını virtual memory manager'ın müdahalesini gerektiren page fault türlerini incelediğim üç bölümde anlatacağım.

Segmentation Fault:  Memory manager tarafında henüz uygulamaya tahsis edilmemiş, uygulama sayfalarından hiçbirinde karşılığı bulunmayan bir adrese erişmeye çalıştıldığında ortaya çıkan hata.Linux işletim sisteminde konsola segmentation fault yazdırdığı için bu şekilde yazdım. Aslında bir tür page hatası değil, hatta segment denen yapılar da artık kullanılmıyor.

Bu bölümde sayfaların processlere atanması ve geri alınmasından bahsedeceğim.

Soft Page Fault: Erişilmek istenen sayfanın bulunamadığı ama fiziksel memory içinde bazı işlemlerle hızlı bir şekilde tekrar verildiği durumlar.

Bu bölümde Linux'taki demand page faultlardan ve Windows'ta standby pages denilen hem disk hem memory'de bulunan, bir nevi araftaki sayfalardan bahsedeceğim.

Hard Page Fault: Erişilmek istenen sayfanın fiziksel memoryde değil diskte olduğu, I/O yaparak tekrar fiziksel memoryye taşındığı durumlar.

Bu bölümde sistemi durma noktasına getirebilen sürekli paging/swapping durumundan ve Linux ve Windows işletim sistemlerinde bu durumun nasıl monitor edilebileceğinden bahsedeceğim.

Hiç yorum yok:

Yorum Gönder