Saya telah mencari-cari di Google dan menemukan kebanyakan orang menganjurkan penggunaan kmalloc
, karena Anda dijamin mendapatkan blok memori fisik yang berdekatan. Namun, tampaknya juga kmalloc
dapat gagal jika blok fisik yang berdekatan yang Anda inginkan tidak dapat ditemukan.
Apa keuntungan memiliki blok memori yang berdekatan? Secara khusus, mengapa saya perlu memiliki blok fisik memori yang berdekatan dalam panggilan sistem ? Apakah ada alasan mengapa saya tidak bisa begitu saja menggunakan vmalloc
?
Akhirnya, jika saya mengalokasikan memori selama penanganan panggilan sistem, haruskah saya menentukan GFP_ATOMIC
? Apakah panggilan sistem dijalankan dalam konteks atom?
GFP_ATOMIC
Alokasi ini berprioritas tinggi dan tidak tidur. Ini adalah bendera untuk digunakan pada penangan interupsi, bagian bawah dan situasi lain di mana Anda tidak bisa tidur.
GFP_KERNEL
Ini adalah alokasi normal dan mungkin memblokir. Ini adalah bendera untuk digunakan dalam kode konteks proses saat aman untuk tidur.
sumber
vmalloc
lebih cepat dengan Kernel 5.2 (Q2 2019)Jawaban:
Anda hanya perlu khawatir tentang penggunaan memori yang berdekatan secara fisik jika buffer akan diakses oleh perangkat DMA pada bus yang dialamatkan secara fisik (seperti PCI). Masalahnya adalah banyak panggilan sistem tidak memiliki cara untuk mengetahui apakah buffer mereka pada akhirnya akan diteruskan ke perangkat DMA: setelah Anda meneruskan buffer ke subsistem kernel lain, Anda benar-benar tidak dapat mengetahui kemana perginya. Bahkan jika kernel tidak menggunakan buffer untuk DMA saat ini, pengembangan di masa mendatang mungkin akan melakukannya.
vmalloc sering kali lebih lambat dari kmalloc, karena mungkin harus memetakan ulang ruang buffer menjadi rentang yang hampir bersebelahan. kmalloc tidak pernah memetakan ulang, meskipun jika tidak dipanggil dengan GFP_ATOMIC kmalloc dapat memblokir.
kmalloc dibatasi dalam ukuran buffer yang dapat disediakannya: 128 KBytes *) . Jika Anda membutuhkan buffer yang sangat besar, Anda harus menggunakan vmalloc atau mekanisme lain seperti menyimpan memori tinggi saat boot.
Untuk panggilan sistem Anda tidak perlu meneruskan GFP_ATOMIC ke kmalloc (), Anda dapat menggunakan GFP_KERNEL. Anda bukan penangan interupsi: kode aplikasi memasuki konteks kernel melalui sebuah perangkap, ini bukan sebuah interupsi.
sumber
Jawaban singkatnya: unduh Linux Device Drivers dan baca bab tentang manajemen memori.
Serius, ada banyak masalah halus terkait dengan manajemen memori kernel yang perlu Anda pahami - Saya menghabiskan banyak waktu untuk men-debug masalah dengannya.
vmalloc () sangat jarang digunakan, karena kernel jarang menggunakan memori virtual. kmalloc () adalah yang biasanya digunakan, tetapi Anda harus tahu apa konsekuensi dari flag yang berbeda dan Anda membutuhkan strategi untuk menangani apa yang terjadi jika gagal - terutama jika Anda berada dalam penangan interupsi, seperti yang Anda sarankan.
sumber
Pengembangan Kernel Linux oleh Robert Love (Bab 12, halaman 244 dalam edisi ke-3) menjawab ini dengan sangat jelas.
Ya, memori yang berdekatan secara fisik tidak diperlukan dalam banyak kasus. Alasan utama kmalloc digunakan lebih dari vmalloc di kernel adalah kinerja. Buku tersebut menjelaskan, ketika potongan memori besar dialokasikan menggunakan vmalloc, kernel harus memetakan potongan (halaman) yang tidak bersebelahan secara fisik ke dalam satu wilayah memori virtual yang berdekatan. Karena memori secara virtual berdekatan dan secara fisik tidak bersebelahan, beberapa pemetaan alamat virtual-ke-fisik harus ditambahkan ke tabel halaman. Dan dalam kasus terburuk, akan ada (ukuran buffer / ukuran halaman) jumlah pemetaan yang ditambahkan ke tabel halaman.
Ini juga menambah tekanan pada TLB (entri cache yang menyimpan pemetaan alamat virtual ke fisik terbaru) saat mengakses buffer ini. Ini bisa menyebabkan meronta - ronta .
sumber
The
kmalloc()
&vmalloc()
functions adalah antarmuka sederhana untuk mendapatkan memori kernel dalam potongan berukuran byte.The
kmalloc()
Fungsi menjamin bahwa halaman fisik berdekatan (dan hampir berdekatan).The
vmalloc()
fungsi bekerja dengan cara yang sama untukkmalloc()
, kecuali mengalokasikan memori yang hanya hampir berdekatan dan belum tentu berdekatan secara fisik.sumber
Apa keuntungan memiliki blok memori yang berdekatan? Secara khusus, mengapa saya perlu memiliki blok fisik memori yang berdekatan dalam panggilan sistem? Apakah ada alasan mengapa saya tidak bisa menggunakan vmalloc begitu saja?
Dari "Saya Lagi Beruntung" dari Google di
vmalloc
:kmalloc adalah cara yang disukai, selama Anda tidak membutuhkan area yang terlalu luas. Masalahnya adalah, jika Anda ingin melakukan DMA dari / ke beberapa perangkat keras, Anda harus menggunakan kmalloc, dan Anda mungkin membutuhkan potongan yang lebih besar. Solusinya adalah mengalokasikan memori sesegera mungkin, sebelum memori terfragmentasi.
sumber
Pada sistem 32-bit, kmalloc () mengembalikan alamat logis kernel (meskipun ini adalah alamat virtual) yang memiliki pemetaan langsung (sebenarnya dengan offset konstan) ke alamat fisik. Pemetaan langsung ini memastikan bahwa kami mendapatkan potongan fisik RAM yang berdekatan. Cocok untuk DMA di mana kami hanya memberikan penunjuk awal dan mengharapkan pemetaan fisik yang berdekatan setelahnya untuk operasi kami.
vmalloc () mengembalikan alamat virtual kernel yang pada gilirannya mungkin tidak memiliki pemetaan yang berdekatan pada RAM fisik. Berguna untuk alokasi memori yang besar dan dalam kasus di mana kami tidak peduli bahwa memori yang dialokasikan untuk proses kami juga berkelanjutan di RAM Fisik.
sumber
Salah satu perbedaan lainnya adalah kmalloc akan mengembalikan alamat logis (jika tidak, Anda menentukan GPF_HIGHMEM). Alamat logis ditempatkan di "memori rendah" (dalam gigabyte pertama memori fisik) dan langsung dipetakan ke alamat fisik (gunakan makro __pa untuk mengubahnya). Properti ini menyiratkan memori kmalloced adalah memori berkelanjutan.
Di sisi lain, Vmalloc mampu mengembalikan alamat virtual dari "memori tinggi". Alamat ini tidak dapat diubah dalam alamat fisik secara langsung (Anda harus menggunakan fungsi virt_to_page).
sumber