歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> linux內存管理概述(二)

linux內存管理概述(二)

日期:2017/2/25 10:38:11   编辑:Linux教程
 vmalloc()函數用起來比較簡單:

  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替換為一系列的新操作即可。

Copyright © Linux教程網 All Rights Reserved