char *buf;
buf = vmalloc(16*PAGE_SIZE); /*獲得16頁*/
if (!buf)
/* 錯誤!不能分配內存*/
在使用完分配的內存之後,一定要釋放它:
vfree(buf);
****************************************************************************************************************************************
下面的內容參考LDD3,十五章內存映射
在內核空間中,kmalloc分配的空間往往被稱為內核邏輯地址(必須與物理地址的映射是線性的和一一對應的),vmalloc分配的空間被稱為內核虛擬地址(不必和物理地址線性對應)。
所有的內核邏輯地址都是內核虛擬地址,但是許多內核虛擬地址不是邏輯地址。
內核邏輯地址通常保存在unsigned long或者void*類型的變量中;內核虛擬地址通常保存在指針變量中。
物理內存中,低端內存存在於內核邏輯地址上,且與內核邏輯地址線性對應;而高端內存是不存在內核邏輯地址上的,只處於內核虛擬地址之上的。所有的物理內存都是通過page結構來描述的。
page結構中有個void *virtual域,表示如果頁面被映射,則指向頁的內核虛擬地址,如果未被映射則為NULL。低端內存頁面總是被映射,而高端內存通常不被映射。
page結構和內核地址的轉換
struct page *virt_to_page(void *kaddr); /* 內核邏輯地址->page結構指針 */
struct page *pfn_to_page(int pfn); /* 頁幀號->page結構指針,應在傳遞前用pfn_valid檢查頁幀號的合法性 */
void *page_address(struct page *page); /* page結構指針-> 內核虛擬地址,大多數情況用kmap替代 */
#include <linux/highmem.h>
void *kmap(struct page *page); /* page結構指針-> 內核虛擬地址 ,不同於page_address若是高端內存,則會創建映射,不要持有映射過長時間。會休眠*/
void kunmap(struct page *page); /* 釋放kmap創建的映射 */
#include <linux/highmem.h>
#include <asm/kmap_types.h>
void *kmap_atomic(struct page *page, enum km_type type); /* kmap的原子版本,type指定使用的槽 */
void kunmap_atomic(void *addr, enum km_type type);
The only slots that make sense for drivers are KM_USER0 and KM_USER1 (for code running directly from a call from user space), and KM_IRQ0 and KM_IRQ1 (for interrupt handlers).
前面提到了每個進程都各自維護一個頁表,來實現內存映射關系。2.6內核中刪除了對頁表直接操作的需求。
虛擬內存區(VMA)用於管理進程地址空間中不同區域的內核數據結構。查看/proc/<pid>/maps文件就能了解進程的內存區域。 /proc/self是一個特殊的文件,它始終指向當前進程。
# cat /proc/1/maps look at init
start-end pern offset major:minor inode image
08048000-0804e000 r-xp 00000000 03:01 64652 /sbin/init text
0804e000-0804f000 rw-p 00006000 03:01 64652 /sbin/init data
0804f000-08053000 rwxp 00000000 00:00 0 zero-mapped BSS
40000000-40015000 r-xp 00000000 03:01 96278 /lib/ld-2.3.2.so text
40015000-40016000 rw-p 00014000 03:01 96278 /lib/ld-2.3.2.so data
40016000-40017000 rw-p 00000000 00:00 0 BSS for ld.so
42000000-4212e000 r-xp 00000000 03:01 80290 /lib/tls/libc-2.3.2.so text
4212e000-42131000 rw-p 0012e000 03:01 80290 /lib/tls/libc-2.3.2.so data
42131000-42133000 rw-p 00000000 00:00 0 BSS for libc
bffff000-c0000000 rwxp 00000000 00:00 0 Stack segment
ffffe000-fffff000 ---p 00000000 00:00 0 vsyscall page
perm 內存區域的讀寫和執行權限的位掩碼,p表示私有,s表示共享
上面這些字段和vm_area_struct結構<linux/mm.h>中的重要成員對應。
vm_operations_struct結構包含了處理進程的內存需求的操作。
mm_struct結構,包含了虛擬內存區域鏈表、頁表以及其它大量內存管理信息等待。
mmap設備操作
在現代Unix操作系統中,內存映射是最吸引人的特征。對於驅動程序來說,內存映射可以提供給用戶程序直接訪問設備內存的能力。例如:X-windows服務的有關顯卡的/dev/mem映射。
映射一個設備意味著將用戶空間的一段內存與設備內存關聯。
不是所有設備都能進行mmap抽象。如串口和其它面向流的設備就不能做這樣的抽象。
mmap必須以PAGE_SIZE為單位進行映射,即只能在頁表一級上對虛擬地址進行管理。
mmap方法是file_operations結構的一部分,
int (*mmap) (struct file *filp, struct vm_area_struct *vma);
為了執行mmap,驅動程序只需要為該地址范圍建立合適的頁表,並將vma->vm_ops替換為一系列的新操作即可。