Pada arsitektur 32-bit, rentang ruang alamat untuk pengalamatan RAM adalah:
0x00000000 - 0xffffffff
atau 4'294'967'295
(4 GB).
Kernel linux membaginya menjadi 3/1 (bisa juga 2/2, atau 1/3 ) masing-masing menjadi ruang pengguna (memori tinggi) dan ruang kernel (memori rendah).
Rentang ruang pengguna:
0x00000000 - 0xbfffffff
Setiap proses pengguna yang baru muncul mendapatkan alamat (rentang) di dalam area ini. Proses pengguna umumnya tidak dipercaya dan karena itu dilarang untuk mengakses ruang kernel. Selanjutnya, mereka dianggap tidak mendesak, sebagai aturan umum, kernel mencoba menunda alokasi memori untuk proses tersebut.
Kisaran ruang kernel:
0xc0000000 - 0xffffffff
Proses kernel mendapatkan alamatnya (rentang) di sini. Kernel dapat langsung mengakses alamat 1 GB ini (yah, bukan 1 GB penuh, ada 128 MB yang dicadangkan untuk akses memori tinggi).
Proses yang muncul di ruang kernel dipercaya, mendesak, dan dianggap bebas kesalahan, permintaan memori diproses secara instan.
Setiap proses kernel juga dapat mengakses rentang ruang pengguna jika diinginkan. Dan untuk mencapai ini, kernel memetakan alamat dari ruang pengguna (memori tinggi) ke ruang kernelnya (memori rendah), 128 MB yang disebutkan di atas secara khusus dicadangkan untuk ini.
Apakah pembagiannya 3/1, 2/2, atau 1/3 dikontrol oleh CONFIG_VMSPLIT_...
pilihan; Anda mungkin dapat memeriksa di bawah /boot/config*
untuk melihat opsi mana yang dipilih untuk kernel Anda.
Referensi pertama yang harus dituju adalah Linux Device Drivers (tersedia online dan dalam bentuk buku), khususnya bab 15 yang memiliki bagian tentang topik tersebut.
Di dunia yang ideal, setiap komponen sistem dapat memetakan semua memori yang diperlukan untuk diakses. Dan ini adalah kasus untuk proses di Linux dan sebagian besar sistem operasi:proses 32-bit hanya dapat mengakses memori virtual kurang dari 2^32 byte (sebenarnya sekitar 3GB pada arsitektur khas Linux 32-bit). Menjadi sulit bagi kernel, yang harus dapat memetakan memori penuh dari proses yang panggilan sistemnya dijalankan, ditambah seluruh memori fisik, ditambah perangkat keras lain yang dipetakan memori.
Jadi ketika kernel 32-bit perlu memetakan lebih dari 4GB memori, itu harus dikompilasi dengan dukungan memori yang tinggi. Memori tinggi adalah memori yang tidak dipetakan secara permanen di ruang alamat kernel. (Memori rendah adalah kebalikannya:selalu dipetakan, sehingga Anda dapat mengaksesnya di kernel hanya dengan mendereferensi pointer.)
Saat Anda mengakses memori tinggi dari kode kernel, Anda perlu memanggil kmap
pertama, untuk mendapatkan pointer dari struktur data halaman (struct page
). Memanggil kmap
bekerja apakah halaman dalam memori tinggi atau rendah. Ada juga kmap_atomic
yang memiliki kendala tambahan tetapi lebih efisien pada mesin multiprosesor karena menggunakan penguncian berbutir halus. Pointer diperoleh melalui kmap
adalah sumber daya:menggunakan ruang alamat. Setelah selesai, Anda harus memanggil kunmap
(atau kunmap_atomic
) untuk membebaskan sumber daya itu; maka pointer tidak valid lagi, dan konten halaman tidak dapat diakses hingga Anda memanggil kmap
lagi.
Ini relevan dengan kernel Linux; Saya tidak yakin bagaimana kernel Unix menangani ini.
Memori Tinggi adalah segmen memori yang dapat ditangani oleh program ruang pengguna. Itu tidak dapat menyentuh Memori Rendah.
Memori Rendah adalah segmen memori yang dapat ditangani langsung oleh kernel Linux. Jika kernel harus mengakses Memori Tinggi, kernel harus memetakannya terlebih dahulu ke ruang alamatnya sendiri.
Ada tambalan yang diperkenalkan baru-baru ini yang memungkinkan Anda mengontrol di mana segmen itu berada. Imbalannya adalah Anda dapat mengambil memori yang dapat dialamatkan dari ruang pengguna sehingga kernel dapat memiliki lebih banyak memori yang tidak harus dipetakan sebelum digunakan.
Sumber daya tambahan:
- http://tldp.org/HOWTO/KernelAnalysis-HOWTO-7.html
- http://linux-mm.org/HighMemory