| 方法 | 原理 | 優點 | 缺點/難點 | 推薦場景 |
|---|---|---|---|---|
reserve_bootmem(addr, size, flags) | 在 bootmem 分配器中標記物理頁面保留 | 精確控制物理地址範圍 | 實測難以成功,需極早調用 (arch 代碼),文檔稀缺 | 極早期、特定物理地址保留 (如 firmware reserved) |
alloc_bootmem(size) | 從 bootmem 分配內存,返回線性地址 | 簡單,在 start_kernel 中調用即可 | 返回線性地址,後續如何映射到內核/用戶空間無現成 API,需手動建頁表 | 內核內部臨時大緩衝區,不需用戶映射 |
內核啟動參數 mem=XXX | 告知內核僅使用 XXX 內存,其餘物理內存不納入內核管理 | 最簡單,無需修改代碼;驅動中用 ioremap 映射內核空間,mmap 映射用戶空間 | 需知曉物理內存總量並精確計算;內核可用內存減少 | 設備驅動保留 DMA 緩衝區、共享內存、安全隔離區 |
bootargs 或 GRUB kernel 行):
mem=192M /* 內核只見 192MB,高 64MB (0x0C000000 - 0x0FFFFFFF) 保留 */
// 內核空間映射
void *kern_vaddr = ioremap(0x0C000000, 64*1024*1024);
// 用戶空間映射 (mmap file operations)
int my_mmap(struct file *filp, struct vm_area_struct *vma) {
unsigned long pfn = 0x0C000000 >> PAGE_SHIFT;
return remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot);
}
保留起始 = 總內存 - 保留大小 (需對齊頁邊界)。若堅持用 alloc_bootmem,獲得線性地址 ptr 後,需在進程上下文中為目標 task_struct 手動建立頁表映射 (參考 ioremap 實現或 vm_insert_page),複雜度極高,不推薦常規驅動開發使用。
mem= 參數 + ioremap/mmap。memblock_reserve (現代內核替代 bootmem) 或設備樹 reserved-memory 節點。start_kernel 後期嘗試保留大塊內存,頁面分配器已初始化,碎片化風險大。