進程地址空間 find_vma()

##進程地址空間 find_vma()

find_vma()功能是查找給定地址的最鄰近區,是尋找合適的線性地址空間至關重要的函數。find_vma()函數有兩個參數:進程內存描述符的地址mm和線性地址addr。查找線性區的vm_end字段大於addr的第一個線性區的位置,並返回這個線性區描述符的地址;如果沒有這樣的線性區存在,就返回-個NULL指針。
補充:
內核用兩個數據結構表示進程地址空間: struct mm_struct(內存描述符) 和 struct vm_area_struct(線性區描述符) 表示。
struct mm_struct 記錄進程地址空間有關的全部信息,進程描述符struct task_struct中mm字段指向屬於自己的mm_struct(內存描述符)。
struct vm_area_struct 記錄進程使用每個線性區以及線性區的屬性。內核中用兩種數據結構組織每個進程所使用的線性區----鏈表和紅黑樹,這樣做的好處是加快查找的速度。struct mm_struct中mmap 和 mm_rb字段分別存放其鏈表頭和紅黑樹根結點。

/* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
{
	struct rb_node *rb_node;
	struct vm_area_struct *vma;

	/* Check the cache first. */
	vma = vmacache_find(mm, addr);
	if (likely(vma))
		return vma;
	
    /* 查找第一個vm_end字段大於addr的線性區 */
	rb_node = mm->mm_rb.rb_node;

	while (rb_node) {
		struct vm_area_struct *tmp;

		tmp = rb_entry(rb_node, struct vm_area_struct, vm_rb);

		if (tmp->vm_end > addr) {
			vma = tmp;
			if (tmp->vm_start <= addr)
				break;
			rb_node = rb_node->rb_left;
		} else
			rb_node = rb_node->rb_right;
	}

/* 
 * vmacache_update : 將新得到的vma緩衝到struct task_struct中vmacache數組中,
 *                  提高下次查找的命中率.
 * 原因 : 程序中引用地址的局部性使下面這種情況出現的可能性很大,如果檢查的最後一個
 *        線性地址屬於某一給定的線性區,那麼下一個要前差的線性地址也屬於這個線性區。
 */
	if (vma)
		vmacache_update(addr, vma);
	return vma;
}

EXPORT_SYMBOL(find_vma)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章