14 Nisan 2017 Cuma

Virtual Memory-Sanal Hafıza

virtual memory,sanal hafıza günümüz modern işletim sistemleri tarafından kullanılan hafıza yönetim tekniğidir.

peki ama neden ?

sisteminizdeki ram den kapasitece daha fazla olan bir programı çalıştırmak istediğinizi düşünelim bu durumda- yapılması gerekilen iş programı bölümlemek/sayfalamak ve ardından ihtiyaç duyulanları ram içerisine yerleştirmek o anlık ihtiyaç duyulmayanları ise virtual memory de bulundurmak ileride ihtiyaç duyulduğunda bunlarıda ram içerisine yerleştirmek diyebiliriz.

virtual memory ile prosesler birbirlerinden izole edilmiş şekildedir yani her process kendi sanal adres uzayına sahip ve bir proses başka bir prosesin alanına müdahalede bulunamaz.

virtual memory ile hard-diskin belirli bir kısmı memory olarak kullanılmaktadır ve bu alan işletim sistemi tarafından pagelere ayrılmaktadır.


eğer linux işletim sistemi kullanıyorsanız pagelerin boyutunu şu şekilde bulabilirsiniz

root@kali:~# getconf PAGESIZE
4096 ----------------------------->>>>> 4K

buradan da anlaşılacağı üzerine işletim sistemi sanal hafızayı bu sistem için 4096 bytelık pagelere bölümleyecek ve ayrıca fiziksel hafızayıda(RAM) 4K olarak bölümlere ayıracaktır.fiziksel hafızadaki bu pageler frame olarak da adlandırılabilinmektedir.

işletim sistemi için geriye kalan tek şey bunların birbirlerine iz düşürülmesi yani sanal hafızadaki adresin fiziksel hafızada neye karşılık geldiğini belirlemek.



bir tablo düşünün sanal hafızadaki adreslerin fiziksel hafızada nereye karşı düştüğünü belirtsin işte buna page tablosu denilmektedir.işte en sade hali ile bunun gösterimi şu şekilde olacaktır.





peki page table nerede tutulacak ?

sanal hafızanın hard-diskten bir parça olduğu biliyoruz ve hard-diske işlemci tarafından
erişim süresi rame erişim süresinden çok daha yavaştır.o halde bu page tablosunu tutmamız gereken yer RAM gibi duruyor.her ne kadar bu düşünce gerçekte yeterli gibi görünsede bu işi bilen insanlar için yeterli görünmemiş kısacası page tablosunu sadece ram üzerinde saklamanın yeterli olmadığı düşüncesinden dolayı bir takım optimizasyonlara(en iyilemeye) ihtiyaç duyulmuş.


MMU(Memory Management Unit),sanal adreslerin fiziksel adreslere izdüşürülmesinden sorumlu olan birimdir.CPUnun içerisinde bulunabileceği gibi(günümüzde daha çok bu şekilde) CPU dan ayrı da olabilir.

TLB(Translation lookaside buffer),güncel olarak kullanılan sanal adreslerin fiziksel adreslerini tutan bir cache veya MMU için lookup table vazifesi görmektedir.







TLB ve MMU biriminin Fiziksel Adres üretiminde kabaca yaptığı işi aşağıdaki şekil ile anlayabiliriz.






yukarıdaki resmi açıklayacak olursak,CPU sanal adresi MMU birimine gönderir ve TLB içerisinde bir arama gerçekleştirilir bulunması durumunda gerçek adres elde edilmiş olunur ve page tablosuna erişim yapılmasına ihtiyaç yoktur.aksi durumda sanal adres için RAM içerisinde bulunan Page tablosuna bakılır ve bulunması durumunda gerçek adres page tablosundaki ilgili kayıttan elde edilmiş olunur.Eğer bu virtual adrese sahip page ram içerisinde yoksa işletim sistemi uyarılır(yazılımsal kesme) ve işletim sistemi ilgili sanal adresi barındıran sayfayı RAME mapler(yerleştirir) daha sonra page tablosunun güncellemelerini yapar bu işlemler sonucu istenilen sanal adres için fiziksel/gerçek adres elde edilmiş olunur.


buraya kadar anlatılanlar gerçekte tek seviyeli bir page tablosu kullanımına dayalı olarak anlatılmıştır fakat günümüz işletim sistemleri tek seviyeli page tablosu yerine çok seviyeli paging mekanizmasını kullanmaktadırlar.


Çok seviyeli tabloların neden kullanıldığı ile ilgili olarak bir açıklama yaparak konuya giriş yapmak yerinde olacaktır.

bildiğiniz gibi işletim sistemleri birden fazla prosesi,prosesi run kuyruğunda bulundurabilirler ve kısa süreli zamanla bunları çalıştırırlar ve kullanıcı sistem eşzamanlı olarak çalışıyormuş hissine kapılır,aslında bu çok çekirdekli ve çok işlemcili sistemler için bir anlığına his değil gerçek olsa da biz tek işlemci tek çekirdekli sistemler için arka planda çok sayıda proses çalıştırdığımızdan dolayı context switch yapıldığını biliyoruz.sanırım prosesler ile ilgili kısmı burada bırakmalıyız eğer prosesler konusunda bilgi sahibi değilseniz bu konular hakkında genel bilgi sahibi olmanız faydanıza olacaktır.



x86 mimaride işlemci 4GBlık bir adres alanını adresleyebilir.

x86 mimarinin kullandığı flat memory model ile bir proses belleği(ram) 4GBlık bir dizi veya düz bir alan gibi görebilir.

kısacası bir proses 0.....2^32-1 adres aralığını adresleyebilir.o halde  4GB lık alanı 4K parçalara ayırmaya çalıştığımızı düşünelim.

4GB/4KB=1 milyon adet sayfa

bu anlatılanları aklımızda tutalım ve bir prosesin sahip olduğu kaynaklardan birininde kendisine ait page tablosu olduğunu hatırlayalım.

peki bu durumda nasıl bir sorun karşımıza çıkar diye düşünücek olursak bunu demeden önce bir prosesin 4GBlık bir adres alanı için ne kadarlık bir page tablosuna sahip olması gerektiğini hesaplayalım.

yukarıdaki hesaplamada da görüldüğü gibi 4GBlık bir adres alanının 4Klık pagelere bölmek istediğimizde 1 milyon tane 4Klık page elde ederiz.

tablodaki her bir page için bir kayıt tutmalıyız ve minimum gereksinimler göz önünde bulundurulduğunda her bir kayıt için 4 bytelık bir alana ihtiyaç duyduğumuzu düşünelim.

bir kayıt için gereksinimlerden bazıları o an da page'in ram de bulunup bulunmadığı veya yazılabilir olup olmadığı gibi bilgiler olabilir.tüm bunlardan sonra page tablomuzdaki bir kayıtın uzunluğunu 4 byte olduğunu kabul ederek,bir page tablomuzun 4MBlık bir alana sahip olacağınıda kabul etmiş oluyoruz.

4MB = 1 MİLYON * 4 BYTE

görüldüğü gibi yalnızca bir prosesin page tablosu için 4MBlık bir alan ihtiyacı gerekmektedir.

eş zamanlı(kimi zaman eş,kimi zaman ayrık ama bize göre eş zamanlı) olarak 200 processin çalıştığını düşünücek olursak neredeyse 1 GB lık bir alan ihtiyacı ortaya çıkacaktır.Bu alanın RAM den karşılanması gerektiğini yazının yukarı kısımlarında belirtmiştik,sanırım buradaki sorun belirginleşti ve o sorun page tablosunun boyutu.

işte page tablosunun boyutundan sebep günümüz modern işletim sistemleri çok seviyeli paging mekanizmasını kullanmaktadırlar.

Umarım konu anlatılırken zihinsel olarak bir dağınıklık yaşamıyorsunuzdur,kimi zaman anlatılanların birbirinden kopuk olmamasına dikkat etsem bile yeni anlatılacak olan kavram içerisinde yeni bir kavramın belirmesi konuyu ister istemez dağıtıyor olabilir.

Paging işlemlerinin donanım tarafından nasıl desteklendiğini anlatmadan önce PAEden bahsetmemiz gerekiyor.

normal şartlarda x86 mimari ile uyumlu bir işletim sistemi kullanıyorsanız 4GB den daha fazla bir RAMiniz varsa maalesef işletim sistemi 4GBlık alandan daha fazlasını adresleyemeyecektir bu kısıt göz önünde bulundurularak X86 mimariye PAE desteği eklenilmiştir.

kısacası PAE desteğini göz önünde bulundurarak yazılmış 32-bit işletim sistemleri 4GB den daha fazla olan bir RAM ile çalışabilir/adresleyebilir.

PAE ile x86 mimaride 32-bit adres bacağı 36-bit olarak genişletmiştir.

Yazıda 3 tür pagingden bahsetilmiştir.

1.)NON-PAE PAGING
2.)PAE PAGING
3.)LONG MODE PAGING


Ayrıca anlatımlarda pagelerin boyutu 4K olarak ele alınmıştır.



normal(NON-PAE) paging mekanizması :

non-PAE paging x86 mimaride PAEnin aktif olmaması durumunda kullanılmaktadır.aşağıdaki şekilde 32-bit sanal adresin x86 non-PAE paging kullanılrıken nasıl yorumlandığını göstermektedir.





 İki tablonun entrylerinin/kayıtlarının formatları ise aşağıdaki şekildeki gibidir.



Page Directory kayıtındaki 31:12 bitleri Page Tablosunun Base adresini göstermektedir sizinde fark edebileceğiniz gibi burası yalnızca Page Tablosunun ilk en yüksek 20 bitini göstermektedir geriye kalan 12 bitin ise 0 olduğunu biliyoruz çünkü bir page tablosu 4K ve katlarından oluşmaktadır.

Her iki kayıt da geriye kalan diğer bitler(31:12 bitleri hariçinde olanlar) page-protection için kullanılmakta veya bazı denetimler için kontrol edilmektedir.

Örneğin P biti istenilen PAGE’in o an için ram de olup olmadığını belirtirken,U/S biti ise PAGE’in usera mı yoksa kernela mı ait olduğunu göstermektedir.

Bu tablolar aracılığı ile adres çevriminin nasıl gerçekleştiğini anlamamız bizim için yeterlidir.

şekil üzerinden de görebileceğiniz gibi CR3 registerı çok seviyeli paging için en üstteki page directory tablosunu işaret ediyor ve bu adresin fiziksel adres olduğunu unutmuyoruz.
(hiyerarşik olarak düşünürseniz en üst kısımda page directory tablosu vardır.)

daha sonra virtual adres 3 gruba ayrılıyor ve ilk 10-bit Page-Directory tablosu için offset olarak kullanıyorken ikinci 10 bit Page-Table için offset ve son 12-bit ise 4K Page için offset olarak kullanılıyor,peki buradaki yapı ile tek seviyeli paging mekanizması arasındaki fark nedir diye bir soru kafamıza takılabilir.

Çok seviyeli paging mekanizmasında her proses için bir page tablosu yerine her proses için bir page directory gerekmektedir ve page directoryinin işaret ettiği page tabloları mevctuttur.

dikkat ederseniz page tabloları dedik page tablosu değil,bu durumda bir proses birden fazla page tablosuna sahip olabilir.

Çok seviyeli paging ile tek seviyeli paging arasındaki ayrım page tablosunun parçalara ayrılması, artık birden fazla page tablomuzun olması ve ihtiyaç duyulanın ram içerisinde bulunmasının yeterli olduğudur. Bazı uygulamaları göz önünde bulundurduğumuzda gerçekten de uygulamanın 4GB lik bir alana ihtiyacı olmadığını görebiliriz.4GB adres alanının tamamına ihtiyaç duymayan bir proses neden tüm alanın haritasına sahip olsun.

(kernel space/user space gibi bir ayrımın yazı boyunca yapılmadığına dikkat ediniz.)


çok seviyeli pagingde bir prosesin sanal-fiziksel adres alanının dönüşümünü gerçekleştirmek için elimizde bulunması gereken kaynağın boyutunu hesaplayalım.


bir proses için bir page directory ihtiyacımız var ve page directory tablosu 2^10 ---> 1024 adet kayıt barındırır ve her biri 4 byte uzunluğundadır.

Bu durumda bir page directory 4K (1024 * 4 BYTE) boyutundadır.

yine page directoryinin işaret ettiği bir page tablosu ise 2^10 ---> 1024 adet kayıt barındırır ve her biri 4 byte uzunluğundadır.

o halde bir page tablosuda 4K boyutundadır.

Bu iki sonucu birleştirirsek,bir prosesin sanal-fiziksel adres alanının dönüşümü için o an ihtiyaç duyulan kaynağın boyutu = 4K+4K=8K olarak hesaplanır.

hatırlarsanız tek seviyeli paging mekanizmasında bir prosesin sanal-fiziksel adres alanının dönüşümü için o an ram de bulunan 4MB lık bir page tablosuna ihtiyacımız vardı.

peki ikinci seviyede bulunan page tablolarından her biri ile ne kadarlık bir adres alanını adresleyebiliriz.

Her bir page tablosu ile 4MB lık bir adres alanını adresleyebiliz,ve bunlardan 1024 tane olması ile 4096 MB yani 4GB lık bir adres alanını adresleyebiliriz.

bir proses 4GB adres alanının tamamını 1024 adet page tablosunun tamamını kullanarak adresleyebilir ama bir prosesin aynı anda 4GB lık bir adres alanını adreslemesi gerçekten uzaktır ve ayrık page tablo kullanma fikri buradan çıkmıştır.

paging hardware seviyesinde desteklendiğinden sistem programlamacının yapması gereken tek iş proses için page directory adresini crc3 registerına yüklemesidir.


PAE Aktif iken Paging :

PAE aktifken paging mekanizması değişiklik gösteriyor yazının yukarıki kısımlarında bahsettiğimiz gibi PAE aktif iken x86 mimaride 4GB den daha fazla bir adres alanını adresleyebiliriz.bu bilgiden sonra x86 mimaride PAE aktif iken paging mekanizması nasıl çalışıyor buna göz atalım.

PAE aktifleştirmek için CR4 registerında PAE bitine karşı düşen bit 1 değerine setlenir.




Buradaki 52* mimari limitidir.Biz x86 mimari ve PAE biti etkinleştirildiğini göz önünde bulundurduğumuzdan fiziksel adresimizin 36 bit olduğunu biliyoruz.Resim AMD64 Manualinden alıntı olduğundan dolayı bir an için kafanızı karıştırabilir bu yüzden 36 bit adres bacağına sahip olduğumuzu unutmuyoruz.




Page-Directory ve Page-Table dışında yeni bir tablonun daha geldiğini görmekteyiz Page-Directory-Pointer Table ve yine tablodaki kayıt sayımızdaki değişiklik olduğunu fark ettik ve her bir kayıtın uzunluğu 32-bit den 64-bite çıktı.

PAE bitinin etkinleştirilmesiyle adres bacaklarımız 32-bit den 36-bite yükseldi.peki bu tablolar üzerinden bir hesaplama yapsak gerçekten bir proses 2^36 yani 64 GB tamamını adresleyebilirmi paging mekanizması üzerinden ?

sistemdeki her proses 4 kayıtı olan Page-Directory-Pointer tablosuna
ve 512 adet kayıt içeren maximum 4 taneye sahip olabileceği Page-Directory-Tablosuna ve bunlarla da işaret edebileceği 512 adet page tablosuna sahip olabilir.

Bu durumda bir prosesin adresleyebileceği toplam alan = 4*512*512*4K kısacası 4GB lık bir alandır.

Burada yine non-PAE deki gibi bir prosesin bir kerede yalnızca 4GB lık bir adres alanını adresleyebileceğidir.

Peki o zaman non-PAE ve PAE arasındaki fark nedir ve nasıl 64 GB lık bir alanı PAE adresleyebilir diyorsanız,PAE paging kullanılırken her tablodaki kayıt genişletilmiştir. Non-PAE de kullanılan 31:12 bitleri yerine artık 35:12 bitleri base adres olarak kullanılmaktadır. 35:12 bitleri ile bir tablonun base adresinin en yüksek ilk 24 bitini gösterirken(geriye kalan 12-bit 0 değerine setlenmiştir) virtual adresin son 12-biti de bu base adrese ilave edilerek 36-bitlik bir fiziksel adres elde edilmiş olunur.


PAE aktif iken sistemdeki tüm prosesler için işletim sisteminin elinde bulunan maximum alan 2^36 dan 64 GB lık bir alandır.

non-PAE de ise işletim sistemi sistemdeki tüm prosesler için ancak paging üzerinden 4GB lık bir alan adreslemesi yapabilirdi.

non-PAE deki tablo boyutları ile PAE pagingdeki tablo boyutlarının aynı olduğuna dikkat ediniz.

Örneğin 1024 adet kayıt kullanan Page Directory Tablomuzda her bir kayıtımızın uzunluğu 32-bit yani 4 byte boyutundaydı ve page directory tablomuzun non-PAE deki toplam boyutunu 4K(1024*4 byte) olarak hesaplamıştık.

PAE paginde bir page directory tablosu 512 adet kayıt tutmakta ve her bir kayıt 64 bit uzunluğunda bu durumda yine page directory boyutu 4K (512*8 byte) olarak kalıcaktır..burada her ne kadar tablomuzdaki kayıtların uzunluğu artmış olsa da tablomuzun toplam boyutu non-PAE paging deki ile aynı tutulmuştur.


Long Mode Paging :

x86-64 veya AMD64 veya x64 (veya siz onu nasıl adlandırmak isterseniz isteyin) mimarinin default çalışma modu olan long mode(iki ayrı modun birleşimidir,64-bit mod ve compatibility mod) içerisinde paging nasıl yapıldığına göz atalım.



4-seviyeli paging  için kullanılan tablolara ait kayıtların formatları aşağıdaki gibidir.





Long mode içerisinde PAE mod içerisindeki paging mekanizması kullanılmaya devam ediliyor ama biraz farklı bu farklardan birisi 4-seviyeli olması ve hiyerarşinin en üstünde yeni gelen tablomuz page-map level-4 tablomuz bulunması ve yine fark edebileceğiniz gibi virtual adres olarak 48 bit kullanılması.

Virtual adres 5 parçaya ayrılmış durumda bunlardan ilk dört-9 bit tablolar için index olarak kullanılırken yine son 12 bit 4K lık page için offset olarak kullanılmaktadır.
bu 4 seviyeli tabloları göz önünde bulundurduğumuzda bir prosesin ne kadarlık bir alanı adresleyebileceğini bilmek istersek yine basit bir hesaplama yapmamız gerekecektir.

Toplam alan = 4 * 512 * 512 * 512 * 512 = 2^48 byte karşılık gelmektedir.

2^48 bayt , 281,474,976,710,656 bayta karşılık gelmektedir bu ifadeyi TB cinsinden ifade edecek olursak 256 TB karşılık gelmektedir.

Çok seviyeli paging mekanizmasında işletim sistemi prosesi çalıştırmadan önce CR3 registerına prosese ait hiyerarşik olarak en üstte bulunan tablonun adresini setler bundan sonrası yine hardware tarafından gerçekleştirilmektedir.tabi burada tablolar arası ilişki yine işletim sistemi tarafından önceden hazırlanmıştır.



Virtual memory kavramını elimizden geldiğince anlatmaya çalıştık umarım faydalı bir yazı olmuştur.

Fakat bazı konulara hiç değinmedik örneğin PAGE REPLACEMENT algoritmaları gibi fakat buradaki amacımız temel kavramlar üzerine olduğundan,virtual ve fiziksel adreslemelerin ne olduğu , proseslerin page tabloları aracılığıyla sanal adreslerinin nasıl fiziksel adreslere dönüştürüldüğü ve çok seviyeli paging mekanizmasına göz atmaktı.



ve son olarak konu ile direk olarak bir bağlantısı olmasada amdnin manualinde bahsettiği bir adres formu mevcut.

yukarıda hesaplarkende gördüğümüz gibi x64 mimaride virtual adres 64 bit olarak kullanılmıyor, şu an için 48 bit kullanımı adresleme için yeterli olarak görülmekte.bu yüzden kullanılmayan bitler için(48.bit ile 63.bit arasındaki tüm bitler ve kendileri) ise en yüksek bitin 47.bitin(0.bit den başladık saymaya) kendisini 63.bite kadar tekrarlamasına canonical adres formu denilmektedir.x64 mimari bu kurala uygun virtual adres görmediği takdirde exception meydana geleceğini söylüyor.


Referanslar :

AMD64 Architecture Programmer's Manual Volume 2 : System Programming



EOF

Hiç yorum yok:

Yorum Gönder