日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux vma,内存管理 – Linux内核API find_vma

發布時間:2023/12/10 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux vma,内存管理 – Linux内核API find_vma 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

find_vma函數功能描述:find_vma( )函數根據一個屬于某個進程的虛擬地址,找到其所屬的進程虛擬區間,并返回相應的vma_area_struct結構體指針。

find_vma文件包含

#include

find_vma函數定義

在內核源碼中的位置:linux-3.19.3/mm/mmap.c

函數定義格式:

struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)

find_vma輸入參數說明

mm:是進程整個用戶空間的抽象,也是總的控制結構,一個進程只有一個mm_struct結構,一個進程整個用戶空間通常有若干離散的虛擬區間,這些虛擬區間由vm_area_struct結構描述。

addr:是進程用戶空間中一虛擬地址,它屬于某一虛擬區間。

find_vma返回參數說明

struct vm_area_struct是對進程虛擬區間抽象的數據結構,find_vma( )函數返回一個該結構類型指針,該指針指向描述進程中虛擬地址addr所在虛擬區間的結構體。

其中,struct mm_struct和struct vm_area_struct在文件linux-3.19.3/include/linux/mm_types.h中定義,它們的具體結構如下,這里對部分字段的含義進行了說明:

struct mm_struct {

struct vm_area_struct * mmap; /* 指向線性區對象的鏈表頭 */

struct rb_root mm_rb;

u32 vmacache_seqnum; /*每一個線程的vmacache序列號*/

#if def CONFIG_MMU

/* 在進程地址空間忠搜索有效線性地址區間的方法 */

unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr,

unsigned long len, unsigned long pgoff, unsigned long flags);

#endif

/* 標識第一個分配的匿名線性區或文件內存映射的線性地址 */

unsigned long mmap_base;

unsigned long mmap_legacy_base;

unsigned long task_size;

unsigned long highest_vm_end;

/* 內核從這個地址開始搜索進程地址空間中線性地址的空閑區間 */

pgd_t * pgd; /*指向頁全局目錄 */

atomic_t mm_users; /* 次使用計數器 */

atomic_t mm_count; /* 主使用計數器*/

atomic_long_t nr_ptes; /*頁表所在的頁*/

int map_count; /* 線性區vma的個數 */

spinlock_t page_table_lock; /* 線性區的自旋鎖和頁表的自旋鎖 */

struct rw_semaphore mmap_sem; /* 線性區的讀/寫信號量 */

struct list_head mmlist; /* 指向內存描述符鏈表中的相鄰元素*/

unsigned long hiwater_rss;

unsigned long hiwater_vm;

/**total_vm指進程地址空間的大小(頁數), locked_vm指“鎖住”而不能換出的頁的個數,

**shared_vm指共享文件內存映射中的頁數,exec_vm指可執行內存映射中的頁數*/

unsigned long total_vm, locked_vm, pinned_vm, shared_vm, exec_vm;

/*stack_vm指用戶堆棧中的頁數*/

unsigned long stack_vm, def_flags;

/*start_code指可執行的起始地址,end_code指可執行代碼的最后地址,start_data

**指已初始化數據的起始地址,end_data指已初始化數據的最后地址*/

unsigned long start_code, end_code, start_data, end_data;

/*start_ brk指堆的起始地址,brk指堆的當前最后地址,start_ stack指用戶態堆棧的起始地址*/

unsigned long start_brk, brk, start_stack;

/* arg_start指命令行參數起始地址,arg_end指命令行參數的最后地址,

**env_start指環境變量的起始地址,env_end指環境變量的最后地址*/

unsigned long arg_start, arg_end, env_start, env_end;

……

……

};

struct vm_area_struct {

unsigned long vm_start; /* 線性區的第一個線性地址 */

unsigned long vm_end; /* 線性區之后的第一個線性地址 */

struct vm_area_struct *vm_next, *vm_prev; /* 進程鏈表中的下一個線性區及上一個線性區*/

struct rb_node vm_rb; /* 用于紅黑樹的數據*/

unsigned long rb_subtree_gap;

struct mm_struct * vm_mm; /*指向線性區所在的內存描述符 */

pgprot_t vm_page_prot; /* 線性區中頁框的訪問許可權 */

unsigned long vm_flags; /* 線性區的標志*/

……

……

struct list_head anon_vma_node; /* 指向匿名線性區鏈表的指針 */

struct anon_vma * anon_vma; /* 指向anon_vma數據結構的指針 */

const struct vm_operations_struct * vm_ops; /* 指向線性區的方法 */

unsigned long vm_pgoff; /*在映射文件中的偏移量,對于匿名頁,它等于0或vm_start/PAGE_SIZE*/

struct file * vm_file; /* 指向映射文件的文件對象 */

void * vm_private_data; /* 指向內存區的私有數據 */

……

……

};

find_vma實例解析

編寫測試文件:find_vma.c

頭文件及全局變量聲明如下:

#include

#include

#include

#include

#include

MODULE_LICENSE("GPL");

static int __init find_vma_init(void);

static void __exit find_vma_exit(void);

模塊初始化函數:

int __init find_vma_init(void)

{

struct mm_struct *mm ;

unsigned long addr ;

struct vm_area_struct * vma ;

mm = current->mm; //mm指向當前進程

addr = mm->mmap->vm_next->vm_start + 1;

printk("addr = 0x%lx\n", addr);

vma = find_vma(mm, addr);

if(vma ! = NULL )

{

/*輸出所查找的虛擬區間的起始地址*/

printk("vma->vm_start = 0x%lx\n", vma->vm_start);

/*輸出所查找虛擬區間的結束地址*/

printk("vma->vm_end = 0x%lx\n", vma->vm_end);

}

else

printk("UNLUCK! You have failed! \n");

return 0;

}

模塊退出函數:

void __exit find_vma_exit(void)

{

printk("exit! \n");

}

模塊初始化及退出函數調用:

module_init(find_vma_init);

module_exit(find_vma_exit);

實例運行結果及分析:

首先編譯模塊,執行命令insmod find_vma.ko插入模塊,然后執行命令dmesg -c,會出現如圖所示的結果。

結果分析:

““mm = current->mm; ”`獲取當前進程用戶空間。

令“ addr = mm->mmap->vm_next->vm_start + 1; ”此時addr即為用戶空間中的某一虛擬地址,這里為當前進程第二個虛擬區間的起始地址加1,由輸出結果可知addr = 0x7fb896ce6001。然后調用find_vma( )函數查詢addr所在的虛擬區間,將描述該虛擬區間的結構體指針賦值給vma,最后通過輸出vma的vm_start和vm_end值驗證了查找成功。

總結

以上是生活随笔為你收集整理的linux vma,内存管理 – Linux内核API find_vma的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。