Neden kafanın karıştığını görebiliyorum. Diyagram biraz kafa karıştırıcı ve aslında yanlış olabilir.
Öncelikle, bir çekirdeğin neden sayfa seviyesinin altında bir bellek ayırıcıya ihtiyacı olduğunu düşünelim. Bu muhtemelen zaten bildiğiniz şeylerdir, ancak bütünlük için geçeceğim.
Sayfalar, bellek işlemlerinin tipik "birimidir". Bir kullanıcı alanı uygulaması bellek ayırdığında veya bir dosyayı veya bunun gibi bir şeyi bellekle eşlediğinde, genellikle makine sayfa boyutunun katını alır. Bazı istisnalar vardır; Windows, CPU'nun sayfa boyutu ne olursa olsun sanal bellek ayırma birimi olarak 64k kullanır. Yine de, bunu bu şekilde düşünelim.
Modern bir CPU'da, kullanıcı-alanı kodu söz konusu olduğunda, düz bir adres alanına sahiptir. Bu aslında sanal bellek sistemi tarafından sağlanan bir yanılsamadır. İşletim sistemi, RAM'deki herhangi bir yerden (veya takas bellek veya bellek eşlemeli dosyalarda hiç RAM'de bulunmayan) sayfalar sağlar ve bunları bitişik bir sanal adres alanına eşler.
Tüm bunların amacı, işletim sisteminin kendisi için birkaç özel durum dışında (belki de DMA tamponları, belki önyükleme zamanında kurulan bazı özel veri yapıları, oh ve çekirdek görüntüsünün kendisi), işletim sistemi çekirdeğinin muhtemelen asla bir sayfadan daha büyük RAM bloklarını yönetebilir. Bu, işleri son derece basitleştirir, çünkü sayfalar ilerledikçe, her ayırma ve ayırma aynı boyuttadır. Ayrıca makro düzeyde dış parçalanmayı etkin bir şekilde ortadan kaldırır.
Bununla birlikte, çekirdeklerin kendi veri yapılarını da uygulamaları gerekir ve bunun için farklı türde bir bellek ayırıcıya ihtiyaçları vardır. Bu veri yapıları genellikle tek tek nesnelerin bir toplamı olarak düşünülebilir (örneğin, bir nesne bir "iş parçacığı" veya bir "muteks" olabilir). Bu nesnelerin boyutu genellikle bir sayfa boyutundan çok daha küçüktür.
Örneğin, bir işlemin güvenlik kimlik bilgilerini temsil eden bir nesne (POSIX'teki kullanıcı kimliğini ve grup kimliğini düşünün, örneğin) yalnızca 16 bayt olabilir, ancak bir "işlem" veya "iş parçacığı" 1kb boyutunda. Açıkçası, bu küçük kayıtlar için bir sayfanın tamamını kullanmak istemezsiniz, bu nedenle fikir, sayfaların üstüne bir ayırıcı uygulamaktır.
Alt düzey ayırma sistemi, sayfa düzeyi ayırıcıyla aynı sorunların çoğunu karşılamalıdır: makul derecede hızlı (çok çekirdekli sistemler dahil) olmalı, parçalanmayı en aza indirgemek istiyorsunuz vb. Ancak daha da önemlisi, ne tür veri yapısı depoladığınıza bağlı olarak ayarlanabilir ve yapılandırılabilir olmalıdır.
Bazı veri yapıları doğal olarak "önbellek benzeri" dir. Örneğin, birçok işletim sistemi uzun dizin araması zincirlerinden (Unix-konuşmada "name cache" olarak adlandırılır) kaçınmak için dosya sistemi nesnelerine yol adları önbelleğini korur. Bu nesneler sadece doğruluk için değil performans için gereklidir, bu nedenle (teoride) bellek sıkıysa ve bir sayfa çerçevesini hızlı bir şekilde boşaltmanız gerekiyorsa, girişlerle dolu bir sayfayı unutabilirsiniz.
Bellek sıkıysa ve yakında bunlara ihtiyacınız yoksa, diğer veri yapıları diske değiştirilebilir. Ama bunu takas veya sanal bellek sistemini kontrol eden veri yapıları ile yapmak istemezsiniz!
Bazı veri yapıları, herhangi bir ceza olmaksızın hafızada hareket ettirilebilir (örneğin, kimse bir işaretçi ile onlara atıfta bulunmazsa), gerektiğinde parçalanmayı önlemek için kendilerini "sıkıştırabilir".
Yani levha ayırıcı ana fikri bir sayfanın sadece aynı "tip" veri yapılarını depolaması gerektiğidir. Bu, tüm kutuları işaretler: sayfadaki her nesne aynı boyuttadır, bu nedenle harici parçalanma yoktur. Aynı "tür" nesneler aynı performans gereksinimlerine ve aynı semantiğe sahiptir.
Bu arada, tahsis ile benzer bir hikaye. Bazı nesne türleri için, o nesneyi tahsis etmek için hemen kullanılabilir bellek yoksa beklemekte fayda vardır. Açık bir dosyayı temsil eden bir nesne bir örnek olabilir; Bir dosyayı açmak en iyi ihtimalle pahalı bir işlemdir, bu yüzden biraz daha beklemek o kadar incinmez.
Diğer nesne türleri için (örneğin, belirli bir zamanda gerçekleşmesi gereken gerçek zamanlı bir olayı temsil eden bir nesne), gerçekten beklemek istemezsiniz. Bu nedenle, bazı nesne türlerinin aşırı tahsis etmesi (örneğin, yedekte birkaç boş sayfa olması) mantıklıdır, böylece istekler beklemeden karşılanabilir.
Temel olarak yaptığınız şey, her bir nesne türünün, o nesnenin ihtiyaçları için yapılandırılabilen kendi ayırıcısına sahip olmasına izin vermektir. Bu nesne başına ayırıcılara kafa karıştırıcı bir şekilde "önbellek" denir. Her nesne türü için bir önbellek ayırırsınız. (Evet, genellikle "önbellek önbelleği" de uygularsınız.) Her önbellek yalnızca aynı türdeki nesneleri depolar (örneğin yalnızca iş parçacığı yapıları veya yalnızca adres alanı yapıları).
Her önbellek sırayla "levhaları" yönetir. Döşeme, aynı türden nesneler içeren bir sayfa çerçevesidir. Döşemeler "dolu" (kullanılan tüm nesneler), "boş" (kullanılmakta olan nesne yok) veya "kısmi" (kullanılan bazı nesneler) olabilir.
Kısmi levhalar muhtemelen en ilginç olanıdır, çünkü levha ayırıcı her kısmi levha için ücretsiz bir liste tutar. (Dolu levhaların ve boş levhaların boş listeye ihtiyacı yoktur.) Gerekli olmayan sayfaların tahsis edilmesinden kaçınmak için nesneler önce kısmi levhalardan (ve muhtemelen önce "en dolu" kısmi levhalardan) ayrılır.
Döşeme tahsisi ile ilgili güzel bir şey, tüm bu tahsis politikası seçeneklerinin (ve ayrıca bellek semantiği) her bir nesne türü için ayarlanabilmesidir. Bazı önbellekler boş döşeme havuzunu tutabilirken bazıları da tutamayabilir. Bazıları ikincil depolamaya değişebilir ve bazıları olmayabilir.
Linux'un kompaktlık, önbellek dostu veya ham hıza ihtiyacınız olup olmadığına bağlı olarak üç farklı slab ayırıcısı vardır. Birkaç yıl önce bu iyi bir sunum açıkladı iyi bir sunum oldu .
Solaris levha ayırıcısı (ayrıntılar için makaleye bakın ) daha da fazla performans elde etmek için birkaç ayrıntıya sahiptir. Bir başlangıç için, Solaris'te her şey sayfa çerçevesi ayırma da dahil olmak üzere döşeme tahsisi ile yapılır. (Bu, Solaris'in çözümünün yarım sayfadan daha büyük nesneleri ayırmak için kullanılmasıdır.) Döşeme ayırıcılarını levha tahsisli alana yerleştirerek daha küçük nesneleri yönetir.
Solaris'teki bazı nesneler karmaşık ve pahalı yapı ve yıkım gerektirir (örn. Çekirdek kilidine sahip nesneler) ve bu nedenle "kısmen özgür" olabilirler (yani inşa edilmiş ancak tahsis edilmemiş). Solaris ayrıca CPU başına ücretsiz listeler koruyarak ücretsiz döşeme tahsisini optimize ederek bazı işlemlerin tamamen beklemesiz olmasını sağlar.
Genel amaçlı tahsisi desteklemek için (örneğin, derleme zamanında boyutu bilinmeyen diziler için), çoğu makro çekirdeği türü işletim sisteminde nesne türlerinden ziyade nesne boyutlarını temsil eden önbellekler bulunur . Örneğin FreeBSD, boyutları 2 bayt güç olan bilinmeyen nesneler için 4'ten 256'ya kadar önbellekleri korur.
Umarım görebileceğiniz şey, slab tahsisinin farklı veri türlerinin ihtiyaçları için ayarlanabilen çok esnek bir çerçevedir. Disk belleği ile rekabet etmez, ancak bunu tamamlar (Solaris'te sayfa çerçeveleri levhalarla ayrılır).
Umarım bu yardımcı olur. Herhangi bir şeyin açıklığa ihtiyacı varsa bana bildirin.