Saya bisa melihat mengapa Anda bingung. Diagram agak membingungkan, dan mungkin sebenarnya tidak benar.
Pertama, mari kita pikirkan mengapa kernel membutuhkan pengalokasi memori di bawah tingkat halaman. Ini mungkin sudah hal-hal yang sebagian besar sudah Anda ketahui, tapi saya akan melengkapinya untuk kelengkapan.
Halaman adalah "unit" khas dari operasi memori. Ketika aplikasi ruang pengguna mengalokasikan memori, atau memetakan memori file, atau sesuatu seperti itu, biasanya mendapatkan kelipatan dari ukuran halaman mesin. Ada beberapa pengecualian; Windows menggunakan 64k sebagai unit alokasi memori virtual, apa pun ukuran halaman CPUnya. Meskipun demikian, mari kita pikirkan cara ini.
Pada CPU modern, sejauh menyangkut kode ruang pengguna, ia memiliki ruang alamat datar. Ini sebenarnya ilusi yang disediakan oleh sistem memori virtual. OS menyediakan halaman dari mana saja dalam RAM (atau mungkin juga tidak dalam RAM sama sekali, dalam kasus memori yang ditukar atau file yang dipetakan memori) dan memetakannya ke dalam ruang alamat virtual yang berdekatan.
Inti dari semua ini adalah bahwa terlepas dari beberapa kasus khusus untuk sistem operasi itu sendiri (mungkin buffer DMA, mungkin beberapa struktur data khusus yang diatur pada saat boot, oh dan gambar kernel itu sendiri), kernel sistem operasi mungkin tidak pernah harus mengelola blok RAM yang lebih besar dari satu halaman. Ini menyederhanakan banyak hal, karena itu berarti sejauh halaman berjalan, setiap alokasi dan alokasi adalah ukuran yang sama. Ini juga secara efektif menghilangkan fragmentasi eksternal di tingkat makro.
Namun, kernel juga perlu mengimplementasikan beberapa struktur data mereka sendiri, dan untuk itu, mereka membutuhkan jenis pengalokasi memori yang berbeda. Struktur data ini biasanya dapat dianggap sebagai kumpulan objek individu (mis. Objek dapat berupa "utas" atau "mutex"). Ukuran objek-objek ini biasanya jauh lebih kecil dari ukuran halaman.
Jadi, misalnya, sebuah objek yang mewakili kredensial keamanan suatu proses (pikirkan id pengguna dan id grup dalam POSIX, katakanlah) mungkin hanya 16 byte atau lebih, sedangkan "proses" atau "utas" mungkin hingga Berukuran 1 kb. Jelas Anda tidak ingin menggunakan seluruh halaman untuk catatan kecil ini, jadi idenya adalah menerapkan pengalokasi di atas halaman.
Sistem alokasi tingkat bawah harus memenuhi banyak masalah yang sama seperti pengalokasi tingkat halaman: harus cukup cepat (termasuk pada sistem multicore), Anda ingin meminimalkan fragmentasi, dan sebagainya. Tetapi yang lebih penting, itu harus dapat diatur dan dikonfigurasi tergantung pada jenis struktur data yang Anda simpan.
Beberapa struktur data secara inheren "seperti cache". Sebagai contoh, banyak sistem operasi menyimpan cache dari path path ke objek filesystem untuk menghindari rantai panjang pencarian direktori (disebut "cache nama" atau "cache namei" di Unix-speak). Objek-objek ini hanya diperlukan untuk kinerja, bukan kebenaran, sehingga Anda bisa (secara teori) hanya melupakan seluruh halaman yang penuh dengan entri jika memori ketat dan Anda perlu membebaskan bingkai halaman dengan cepat.
Struktur data lain dapat ditukar ke disk jika memori ketat dan Anda tidak membutuhkannya segera. Tetapi Anda tidak ingin melakukannya dengan struktur data yang mengontrol swapping atau sistem memori virtual!
Beberapa struktur data dapat dipindahkan di memori tanpa penalti (mis. Jika tidak ada yang merujuknya dengan pointer), jadi bisa "memadatkan" diri mereka sendiri untuk menghindari fragmentasi jika diperlukan.
Jadi ide utama dari pengalokasi slab adalah bahwa halaman seharusnya hanya menyimpan struktur data dari "tipe" yang sama. Ini mencentang semua kotak: setiap objek di halaman berukuran sama, jadi tidak ada fragmentasi eksternal. Objek dengan "tipe" yang sama memiliki persyaratan kinerja dan semantik yang sama.
Kebetulan, ini adalah cerita yang mirip dengan alokasi. Untuk beberapa jenis objek, boleh saja menunggu jika tidak ada memori yang tersedia untuk mengalokasikan objek tersebut. Objek yang mewakili file terbuka mungkin menjadi salah satu contoh; membuka file adalah operasi yang mahal pada saat terbaik, jadi menunggu sedikit lebih lama tidak akan banyak merugikan.
Untuk jenis objek lain (mis. Objek yang mewakili peristiwa waktu nyata yang harus terjadi pada waktu tertentu dari sekarang), Anda benar-benar tidak ingin menunggu. Jadi masuk akal untuk beberapa jenis objek untuk mengalokasikan berlebihan (katakanlah, miliki beberapa halaman gratis sebagai cadangan) sehingga permintaan dapat dipenuhi tanpa menunggu.
Apa yang Anda lakukan pada dasarnya adalah memungkinkan setiap jenis objek memiliki pengalokasi sendiri, yang dapat dikonfigurasi untuk kebutuhan objek tersebut. Alokasi per objek ini membingungkan disebut "cache". Anda mengalokasikan satu cache per jenis objek. (Ya, Anda biasanya juga akan mengimplementasikan "cache cache"). Setiap cache hanya menyimpan objek dari jenis yang sama (mis. Hanya struktur utas, atau hanya struktur ruang alamat).
Setiap cache, pada gilirannya, mengelola "lempengan". Slab adalah bingkai halaman yang berisi larik objek dengan tipe yang sama. Lembaran mungkin "penuh" (semua objek sedang digunakan), "kosong" (tidak ada objek yang digunakan), atau "sebagian" (beberapa objek sedang digunakan).
Slab parsial mungkin yang paling menarik, karena pengalokasi slab menyimpan daftar gratis untuk setiap slab parsial. (Slab penuh dan slab kosong tidak perlu daftar gratis.) Objek dialokasikan dari slab parsial terlebih dahulu (dan mungkin dari slab parsial "paling penuh" terlebih dahulu) untuk mencoba menghindari mengalokasikan halaman yang tidak diperlukan.
Yang menyenangkan tentang alokasi slab adalah bahwa semua opsi kebijakan alokasi ini (serta semantik memori) dapat disesuaikan untuk setiap jenis objek. Beberapa cache mungkin menyimpan kumpulan slab kosong dan beberapa mungkin tidak. Beberapa mungkin dapat ditukar dengan penyimpanan sekunder dan beberapa mungkin tidak.
Linux memiliki tiga jenis pengalokasi slab, tergantung pada apakah Anda memerlukan kekompakan, keramahan cache, atau kecepatan mentah. Ada presentasi yang baik tentang ini beberapa tahun yang lalu yang menjelaskan pengorbanan dengan baik.
Pengalokasi slab Solaris (lihat kertas untuk detailnya ) memiliki beberapa detail lagi untuk memeras kinerja yang lebih banyak lagi. Sebagai permulaan, di Solaris, semuanya dilakukan dengan alokasi slab, termasuk alokasi bingkai halaman. (Ini adalah solusi Solaris untuk mengalokasikan objek yang ukurannya lebih besar dari setengah halaman.) Ia mengelola objek yang lebih kecil dengan menumpuk pengalokasi slab di ruang yang dialokasikan slab.
Beberapa objek di Solaris memerlukan konstruksi dan penghancuran yang kompleks dan mahal (mis. Objek yang memiliki kunci kernel), dan sehingga bisa "sebagian bebas" (yaitu dibangun tetapi tidak dialokasikan). Solaris juga mengoptimalkan alokasi slab gratis dengan mempertahankan daftar gratis berdasarkan CPU, memastikan beberapa operasi sepenuhnya bebas-tunggu.
Untuk mendukung alokasi tujuan umum (misalnya untuk array yang ukurannya tidak diketahui pada waktu kompilasi), sebagian besar sistem operasi tipe macrokernel juga memiliki cache yang mewakili ukuran objek daripada tipe objek . FreeBSD, misalnya, memelihara cache untuk objek yang tidak diketahui yang ukurannya adalah kekuatan 2 byte, dari 4 hingga 256.
Apa yang saya harap Anda bisa lihat adalah bahwa alokasi slab adalah kerangka kerja yang sangat fleksibel yang dapat disesuaikan untuk kebutuhan berbagai jenis data. Itu tidak bersaing dengan paging, tetapi melengkapinya (meskipun di Solaris, frame halaman dialokasikan dengan slab).
Saya harap ini membantu. Beri tahu saya jika ada yang butuh klarifikasi.