Stronger_Cracker
- 25 Tem 2022
- 6,410 Mesaj
Aktiflik
Seviye
Deneyim
Merhabalar,
Sistem programlamada, modern cpuların çalışma mekanizmalarını anlayabilmek için veya bilgi sahibi olabilmek için sayfalama mekanizması nedir, sanal bellek nedir konularına aşina olmak gerekmektedir.
Bellek yönetiminde fragmentation adında bir terim söz konusudur ve bu terim belleğin bölünmesi, yönetilmesi ile alakalı bir kavramdır. Herhangi bir bellek alanını düşünelim ve bu belleğin toplam kapasitesinin 100k boyutunda olduğunu varsayalım. Bu bir diskte olabilir bellekte olabilir.
Bellekte tahsisat işlemleri sırasında ya da program yükleme sırasında ardışıllık göz önüne alınarak tahsisat yapılırsa uzun dönemde fragmentation problemleri ile karşılaşmaktayız.
100k kapasiteli bir bellekte üzerinde bir programcının 30k’lık bir alan tahsis ettiğini düşünelim.
Farklı bir programcı, 20k, bir diğer programı 15klık bir alan tahsis etti. Toplamda 65k oldu.
Bir diğeri daha geldi ve 30k daha tahsis etti. Toplamda 95k’lık alan tahsis edilmiş oldu. 100k’lık bir alandan yalnızca 5klık bir bellek alanının kullanılabilir olduğunu (free) düşünelim.
Betimleme açısından aşağıdaki görsele göz atabiliriz.
Dikkat edersek bu bellek alanında ki tahsisat ardışık olarak gerçekleştirilmiştir. Bu tahsisatın ne için yapıldığının herhangi bir önemi yoktur. Örnek olması açısından bu tahsisatın bir programın ram belleğe yüklenmesi olarak göz önüne alabiliriz ya da gerçekten heap alanından yazılımcıların bellek alanından tahsis ettikleri (malloc ile) bellek alanları olarak varsayılabilir. Gösterilmek istenen nokta ardışık bir tahsisatın dezavantajlarıdır. Alınan bu bellek alanlarının işinin bittiğini, kullanımının dolduğunu ve herhangi bir şekilde free hale getirildiğini varsayalım. Ardından tekrar free hale getirilen 20k’lık alandan 12’lık ve 27k’lık bir bellek tahsisatının yapıldığını varsayalım. Free olan bellek alanlarından sonra aşağıdaki görüntü bellek alanının şuan ki durumunu temsil etsin.
Daha sonra, yukarıda var olan görseldeki 30K’lık alanında free hale getirildiğini (programcı tarafından ya da işletim sistemi tarafından) düşünelim. Sonrasında tekrar aynı alandan 27k’lık bir tahsisat daha gerçekleştirildi. 30K’lık alandan 3k yeni free alan kaldı.
Tüm bu yaptığımıza, konunun anlamlaştırılması için küçük bir simülasyon diyebiliriz. Bu çalışma sonucunda eğer bellekten alan tahsisatı ve free hale getirmeleri devam ettirerek, yani parçalanmış vaziyette tahsisatları gerçekleştirmeye devam ettirirsek, hiçbir işe yaramayan çok küçük ve ardışık olmayan bellek alanları ile karşılaşırız.
Toplamda bakıldığında 11K’lık bir free bellek alanı mevcut fakat 10k’lık bir bellek tahsisatı yapılamamaktadır çünkü ardışıklık mevcut değildir. Birbirinden kopuk yapıdalar. Fragmentation denilen olgu budur. Uzun süre boyunca, bellek alanlarının tahsis edilip geri verilmesi sonrasında ve bunun devamlı yapılması sonrasında birçok ardışık olmayan çok boyutta bellek alanları ortaya çıkıyor fakat bunlar hiçbir işe yaramıyor. Bu şekilde belleği verimli kullanmamış oluyoruz.
**Peki bu fragmentation nasıl engellenmekte? **
Öncelikle fgramentation’a sebep olan durumu tekrar hatırlayalım. Ardışık yüklenme zorunluluğu ve bir zamandan sonra küçük bölgelerin oluşması, bu küçük free alanların sayısal toplamının elle tutulabilir bir alan oluşturması fakat herhangi bir işe yaramaması.
Fragmentation’ı önlemek için birinci yöntemimimiz sıkıştırmadır. Bu tur yöntem biraz eski bir yöntem olmakla birlikte işletim sisteminin sistemi durdurup ya da ilgili bellek tahsisat algoritması sistemi durduruyor ve bu free alanları sıkıştırıyor.
Örneğin C# ve JAVA gargage collection mekanizması bu yöntemi kullanmaktadır. C# da CLR (common language runtime), JAVA için JVM (java virtual machine)’de tahsisatlar bu şekilde yapılıyor. Sanal makine olduğu için sistem sistem durdurulabiliyor ve sıkıştırmayı yapıyor. Bunu yaparken de tüm referanslarını tabi ki değişiyor. Örneğin java da “a = new Simple();” tarzı bir referans alın, gargage collection sonrası a nın adresinin değiştiğini görebilirsiniz. Fakat native işletim sistemlerine böyle bir durum yapılamamakta.
Bir diğer fragmentationın engellenme yöntemi de şudur; eğer fragmentation sorununu ortaya çıkartan sebep ardışıl yüklenme zorunluluğuysa, biz bu ardışıl yüklenme zorunluluğunu ortadan kaldırırız. Bu tür sistemlerde fragmentationı ortadan kaldırmak istiyorsanız eğer, memory’i bloklara ayırılıyorsunuz. Örneğin 4klık bloklar olsun ve bu şekilde tahsisatı ardışıl yapma zorunluluğunu ortadan kaldırıyorsunuz. Bu şekilde küçük olan bellek alanları da kullanılabiliyor.
Fakat burada şu tarz bir problem çıkıyor, bu tür ardışıl yüklenme zorunluluğunu ortadan kaldırma yöntemi C gibi bir programlama dilinde çalışır mı, yani malloc gibi bellek tahsisatı için kullanılan yerlerde çalışır mı? Hayır, çalışmaz ama disk gibi yerlerde çalışabilir. Dosya sistemleri bu şekilde çalışmakta. Bir dosyanın parçalarını ardışıl olmayan bir yerde tutuyorlar. Bu tür bir durumda bu blokların yerlerinin disk üzerinde bir alanda kayıtlı olması gerekiyor. Microsoft’un dosya sistemlerinde FAT kısmında bu kayıtlar tutulabilmekte.
Bu tür bir yöntem disk üzerinde uygulanabilir fakat RAM bellek üzerinde uygulanabilir mi?
Alanlara böldüğümüz ve 4k veya 1klık alanların olduğu bir yapıda, bellek üzerinde örneğin 8.5klık bir alan tahsisatı gerekliyse ve alanlarımız 1k’lıksa, 9k’lık bir alan tahsis etmemiz gerekir. Bu durumda boşa giden en fazla 1klık bir alanımız olmuş olacak. Bu Internal Fragmentation yöntemidir.
Bu tür durumlar disk üzerinde kullanılabilmektedir. Fakat farklı bir soru daha akla gelmektedir. Biz blokları küçülttük, fragmentation durumunu ortadan kaldırdık, bloklar artık ardışıl yüklenmiyorlar ve dağınık vaziyetteler. Bu dağınık vaziyetteki blokların yerleri, adresleri de bir yerde kayıt altında bulunmalı ki erişmek istediğimiz verinin hangi bloklarda dağınık vaziyetlerde tutulduğunu bilelim ve gerektiğinde onları çağırabilelim. Biz blokları küçülttük fakat bu blokların adreslerinin bir yerde tutuluyor olması zorunluluğu söz konusu olduğunda, adreslerin tutulacağı alanda blokların küçülmesinden dolayı büyüyecek. Örneğin 50klık bloğu dörder dörder bloklara ayırıp bunların yerlerini tutmak mı daha zordur yoksa 512 bytelık alanların yerlerini mi tutmak daha zordur. Tabi ki 512 bytelik blokların yerlerinin tutulması daha zor olacaktır. Bunun nihai boyutu ve noktası belirlenebilir.
Modern işlemcilerin neredeyse tamamında sayfalama mekanizması mevcuttur. Örneğin intelin 8086 mimarisinde bu mevcut değil.
Bildiğiniz üzere işlemci ram belleğe bağlı olarak çalışmakta. Bunlar devamlı aralarında bilgi alışverişi yapıp işler halde çalışmaktalar. Ram sayfalar dediğimiz bloklara ayrılmış durumda. Ram belleklerin geliştirme aşamasında, donanımsal olarak bu tür herhangi bir bloklara ayırma işlemi mevcut değil. Bu tamamen işlemcinin mantıksal bir mekanizması ve kabul görüşü diyebiliriz.
Bir sayfanın uzunluğu işlemciden işlemciye değişkenlik gösterebilmektedir ve hatta yeni nesil bilgisayarların neredeyse tamamında siz bu sayfa boyutlarını yapılandırabiliyor ve seçebiliyorsunuz. Kafamıza göre tabi ki bu boyutları belirleyememekteyiz. Önceden belirlenmiş olan sabit sayfa boyutlarından birini seçebilmekteyiz. Yazdığımız gibi, ram belleğin üretiminde herhangi bir sayfa yok yalnızca işlemci rami sayfalardan oluşuyormuş gibi görüyor. Bu işlemcinin bir organizasyonu.
Peki, bir sayfa büyüklüğü ne kadar?
Görüldüğü üzere yukarıda ki tabloda modern işlemciler sırasıyla belirtilmiş vaziyetteler. En küçük sayfa boyutları genel olarak 4K boyutunda fakat desteklediği boyutları değişkenlik gösterebilmekte.
İşlemciler, işlemcilerin sayfalama mekanizmalarını destekliyor olsalar da siz eğer işlemciyi resetlerseniz sayfalama mekanizması pasif hale gelmekte. Pasif hale getirirseniz CPU bu yapıyı kullanmamakta.
Sistem programlamada, modern cpuların çalışma mekanizmalarını anlayabilmek için veya bilgi sahibi olabilmek için sayfalama mekanizması nedir, sanal bellek nedir konularına aşina olmak gerekmektedir.
Bellek yönetiminde fragmentation adında bir terim söz konusudur ve bu terim belleğin bölünmesi, yönetilmesi ile alakalı bir kavramdır. Herhangi bir bellek alanını düşünelim ve bu belleğin toplam kapasitesinin 100k boyutunda olduğunu varsayalım. Bu bir diskte olabilir bellekte olabilir.
Bellekte tahsisat işlemleri sırasında ya da program yükleme sırasında ardışıllık göz önüne alınarak tahsisat yapılırsa uzun dönemde fragmentation problemleri ile karşılaşmaktayız.
100k kapasiteli bir bellekte üzerinde bir programcının 30k’lık bir alan tahsis ettiğini düşünelim.
Farklı bir programcı, 20k, bir diğer programı 15klık bir alan tahsis etti. Toplamda 65k oldu.
Bir diğeri daha geldi ve 30k daha tahsis etti. Toplamda 95k’lık alan tahsis edilmiş oldu. 100k’lık bir alandan yalnızca 5klık bir bellek alanının kullanılabilir olduğunu (free) düşünelim.
Betimleme açısından aşağıdaki görsele göz atabiliriz.
Dikkat edersek bu bellek alanında ki tahsisat ardışık olarak gerçekleştirilmiştir. Bu tahsisatın ne için yapıldığının herhangi bir önemi yoktur. Örnek olması açısından bu tahsisatın bir programın ram belleğe yüklenmesi olarak göz önüne alabiliriz ya da gerçekten heap alanından yazılımcıların bellek alanından tahsis ettikleri (malloc ile) bellek alanları olarak varsayılabilir. Gösterilmek istenen nokta ardışık bir tahsisatın dezavantajlarıdır. Alınan bu bellek alanlarının işinin bittiğini, kullanımının dolduğunu ve herhangi bir şekilde free hale getirildiğini varsayalım. Ardından tekrar free hale getirilen 20k’lık alandan 12’lık ve 27k’lık bir bellek tahsisatının yapıldığını varsayalım. Free olan bellek alanlarından sonra aşağıdaki görüntü bellek alanının şuan ki durumunu temsil etsin.
Daha sonra, yukarıda var olan görseldeki 30K’lık alanında free hale getirildiğini (programcı tarafından ya da işletim sistemi tarafından) düşünelim. Sonrasında tekrar aynı alandan 27k’lık bir tahsisat daha gerçekleştirildi. 30K’lık alandan 3k yeni free alan kaldı.
Tüm bu yaptığımıza, konunun anlamlaştırılması için küçük bir simülasyon diyebiliriz. Bu çalışma sonucunda eğer bellekten alan tahsisatı ve free hale getirmeleri devam ettirerek, yani parçalanmış vaziyette tahsisatları gerçekleştirmeye devam ettirirsek, hiçbir işe yaramayan çok küçük ve ardışık olmayan bellek alanları ile karşılaşırız.
Toplamda bakıldığında 11K’lık bir free bellek alanı mevcut fakat 10k’lık bir bellek tahsisatı yapılamamaktadır çünkü ardışıklık mevcut değildir. Birbirinden kopuk yapıdalar. Fragmentation denilen olgu budur. Uzun süre boyunca, bellek alanlarının tahsis edilip geri verilmesi sonrasında ve bunun devamlı yapılması sonrasında birçok ardışık olmayan çok boyutta bellek alanları ortaya çıkıyor fakat bunlar hiçbir işe yaramıyor. Bu şekilde belleği verimli kullanmamış oluyoruz.
**Peki bu fragmentation nasıl engellenmekte? **
Öncelikle fgramentation’a sebep olan durumu tekrar hatırlayalım. Ardışık yüklenme zorunluluğu ve bir zamandan sonra küçük bölgelerin oluşması, bu küçük free alanların sayısal toplamının elle tutulabilir bir alan oluşturması fakat herhangi bir işe yaramaması.
Fragmentation’ı önlemek için birinci yöntemimimiz sıkıştırmadır. Bu tur yöntem biraz eski bir yöntem olmakla birlikte işletim sisteminin sistemi durdurup ya da ilgili bellek tahsisat algoritması sistemi durduruyor ve bu free alanları sıkıştırıyor.
Örneğin C# ve JAVA gargage collection mekanizması bu yöntemi kullanmaktadır. C# da CLR (common language runtime), JAVA için JVM (java virtual machine)’de tahsisatlar bu şekilde yapılıyor. Sanal makine olduğu için sistem sistem durdurulabiliyor ve sıkıştırmayı yapıyor. Bunu yaparken de tüm referanslarını tabi ki değişiyor. Örneğin java da “a = new Simple();” tarzı bir referans alın, gargage collection sonrası a nın adresinin değiştiğini görebilirsiniz. Fakat native işletim sistemlerine böyle bir durum yapılamamakta.
Bir diğer fragmentationın engellenme yöntemi de şudur; eğer fragmentation sorununu ortaya çıkartan sebep ardışıl yüklenme zorunluluğuysa, biz bu ardışıl yüklenme zorunluluğunu ortadan kaldırırız. Bu tür sistemlerde fragmentationı ortadan kaldırmak istiyorsanız eğer, memory’i bloklara ayırılıyorsunuz. Örneğin 4klık bloklar olsun ve bu şekilde tahsisatı ardışıl yapma zorunluluğunu ortadan kaldırıyorsunuz. Bu şekilde küçük olan bellek alanları da kullanılabiliyor.
Fakat burada şu tarz bir problem çıkıyor, bu tür ardışıl yüklenme zorunluluğunu ortadan kaldırma yöntemi C gibi bir programlama dilinde çalışır mı, yani malloc gibi bellek tahsisatı için kullanılan yerlerde çalışır mı? Hayır, çalışmaz ama disk gibi yerlerde çalışabilir. Dosya sistemleri bu şekilde çalışmakta. Bir dosyanın parçalarını ardışıl olmayan bir yerde tutuyorlar. Bu tür bir durumda bu blokların yerlerinin disk üzerinde bir alanda kayıtlı olması gerekiyor. Microsoft’un dosya sistemlerinde FAT kısmında bu kayıtlar tutulabilmekte.
Bu tür bir yöntem disk üzerinde uygulanabilir fakat RAM bellek üzerinde uygulanabilir mi?
Alanlara böldüğümüz ve 4k veya 1klık alanların olduğu bir yapıda, bellek üzerinde örneğin 8.5klık bir alan tahsisatı gerekliyse ve alanlarımız 1k’lıksa, 9k’lık bir alan tahsis etmemiz gerekir. Bu durumda boşa giden en fazla 1klık bir alanımız olmuş olacak. Bu Internal Fragmentation yöntemidir.
Bu tür durumlar disk üzerinde kullanılabilmektedir. Fakat farklı bir soru daha akla gelmektedir. Biz blokları küçülttük, fragmentation durumunu ortadan kaldırdık, bloklar artık ardışıl yüklenmiyorlar ve dağınık vaziyetteler. Bu dağınık vaziyetteki blokların yerleri, adresleri de bir yerde kayıt altında bulunmalı ki erişmek istediğimiz verinin hangi bloklarda dağınık vaziyetlerde tutulduğunu bilelim ve gerektiğinde onları çağırabilelim. Biz blokları küçülttük fakat bu blokların adreslerinin bir yerde tutuluyor olması zorunluluğu söz konusu olduğunda, adreslerin tutulacağı alanda blokların küçülmesinden dolayı büyüyecek. Örneğin 50klık bloğu dörder dörder bloklara ayırıp bunların yerlerini tutmak mı daha zordur yoksa 512 bytelık alanların yerlerini mi tutmak daha zordur. Tabi ki 512 bytelik blokların yerlerinin tutulması daha zor olacaktır. Bunun nihai boyutu ve noktası belirlenebilir.
İşlemcilerin Sayfalama Mekanizması
İşlemcilerin sayfalama mekanizmasının amacı ardışıl yüklenme zorunluluğunu ortadan kaldırmak ve sanal bellek (virtual memory) teknolojisinin işler hale gelmesini sağlamak.Modern işlemcilerin neredeyse tamamında sayfalama mekanizması mevcuttur. Örneğin intelin 8086 mimarisinde bu mevcut değil.
Bildiğiniz üzere işlemci ram belleğe bağlı olarak çalışmakta. Bunlar devamlı aralarında bilgi alışverişi yapıp işler halde çalışmaktalar. Ram sayfalar dediğimiz bloklara ayrılmış durumda. Ram belleklerin geliştirme aşamasında, donanımsal olarak bu tür herhangi bir bloklara ayırma işlemi mevcut değil. Bu tamamen işlemcinin mantıksal bir mekanizması ve kabul görüşü diyebiliriz.
Bir sayfanın uzunluğu işlemciden işlemciye değişkenlik gösterebilmektedir ve hatta yeni nesil bilgisayarların neredeyse tamamında siz bu sayfa boyutlarını yapılandırabiliyor ve seçebiliyorsunuz. Kafamıza göre tabi ki bu boyutları belirleyememekteyiz. Önceden belirlenmiş olan sabit sayfa boyutlarından birini seçebilmekteyiz. Yazdığımız gibi, ram belleğin üretiminde herhangi bir sayfa yok yalnızca işlemci rami sayfalardan oluşuyormuş gibi görüyor. Bu işlemcinin bir organizasyonu.
Peki, bir sayfa büyüklüğü ne kadar?
Görüldüğü üzere yukarıda ki tabloda modern işlemciler sırasıyla belirtilmiş vaziyetteler. En küçük sayfa boyutları genel olarak 4K boyutunda fakat desteklediği boyutları değişkenlik gösterebilmekte.
İşlemciler, işlemcilerin sayfalama mekanizmalarını destekliyor olsalar da siz eğer işlemciyi resetlerseniz sayfalama mekanizması pasif hale gelmekte. Pasif hale getirirseniz CPU bu yapıyı kullanmamakta.

