VMA使用

Vulkan系列教程—VMA教程(一)—快速上手VMA Vulkan的内存分配器VMA系列教程 阅读详情

VMA使用


用户地址空间

用户层进程的虚拟地址空间是linux的一个重要抽象:它向每个运行进程提供了同样的系统视图,这使得多个进程可以同时运行,而不会相互干扰。
本文讨论内核管理用户虚拟地址空间的方法,由于一下种种原因,这比内核地址空间的管理更复杂。

  • 每个应用程序都有自身的地址空间,与所有其它的应用程序分隔开。
  • 通常在巨大的线性地址空间中,只有很少的段可用于各个用户空间进程,这些段彼此有一定的距离。内核需要一些数据结构来有效管理这些段。
  • 地址空间只有极小的一部分与物理内存页直接关联。不经常使用的段,只有当需要时才会与物理页帧进行关联。
  • 内核信任自身,但无法信任用户进程。因此,各个操作用户地址空间的操作都伴随着各种检查,以确保程序的权限不会超出应有的限制。
  • fork-exec模型在UNIX操作系统中用于产生新进程。如果实现得较为粗劣,该模型的功能将大打折扣。因此内核借助与一些技巧,来尽可能高效的管理用户地址空间。
进程地址空间的布局

虚拟地址空间中包含了若干区域。其分布方式是特定于体系结构的,但所有方法都有下列共同部分。

  • 代码段,当前运行代码的二进制代码。
  • 动态库,程序使用的动态库代码。
  • 堆。
  • 栈。
  • 环境变量和命令行参数的段。
  • 将文件内容映射到虚拟地址空间中的内存映射。

既然出现了这么多的区域,所以内核就将各个区域称为VMA(virtual memoryAreas),每个区域使用一个名为struct vm_area_struct的数据结构进行管理。

VMA数据结构

vm_area_struct结构体描述了指定地址空间内连续区间上的一个独立内存范围。内核将每个内存范围作为一个单独的内存对象管理,每个内存对象都拥有一致的属性,比如访问权限等,另外,相应的操作也都一致。注意在同一个地址空间内的不同内存区域不能重叠。

<include/linux/mm_types.h>
struct vm_area_struct {
	/* The first cache line has the info for VMA tree walking. */

    /* 线性区内的第一个线性地址 */
	unsigned long vm_start;		/* Our start address within vm_mm. vm_mm内的起始地址 */
    /* 线性区之外的第一个线性地址 */
	unsigned long vm_end;		/* The first byte after our end address
					   within vm_mm. 在vm_mm内结束地址之后的第一个字节的地址 */

	/* linked list of VM areas per task, sorted by address 各进程的虚拟内存区域链表,按地址排序 */
    /* 整个链表会按地址大小递增排序 */
    /* vm_next: 线性区链表中的下一个线性区 */
    /* vm_prev: 线性区链表中的上一个线性区 */
	struct vm_area_struct *vm_next, *vm_prev;

    /* 用于组织当前内存描述符的线性区的红黑树的结点 */
	struct rb_node vm_rb;

	/*
	 * Largest free memory gap in bytes to the left of this VMA.
	 * Either between this VMA and vma->vm_prev, or between one of the
	 * VMAs below us in the VMA rbtree and its ->vm_prev. This helps
	 * get_unmapped_area find a free area of the right size.
	 */
	/* 此vma的子树中最大的空闲内存块大小(bytes) */
	unsigned long rb_subtree_gap;

	/* Second cache line starts here. */

    /* 指向所属的内存描述符 */
	struct mm_struct *vm_mm;	/* The address space we belong to. 所属地址空间 */
    /* 页表项标志的初值,当增加一个页时,内核根据这个字段的值设置相应页表项中的标志 */
    /* 页表中的User/Supervisor标志应当总被置1 */
	pgprot_t vm_page_prot;		/* Access permissions of this VMA. 该区域虚拟内存区域的访问权限 */
    /* 线性区标志
     * 读写可执行权限会复制到页表项中,由分页单元去检查这几个权限
     */
	unsigned long vm_flags;		/* Flags, see mm.h. 标志 */

	/*
	 * For areas with an address space and backing store,
	 * linkage into the address_space->i_mmap interval tree.
	 * 对于有adress_space和后备存取器的区域来说,
	 * shared连接到address_space->i_mmap优先树
	 */
	struct {
		struct rb_node rb;
		unsigned long rb_subtree_last;
	} shared;

	/*
	 * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
	 * list, after a COW of one of the file pages.	A MAP_SHARED vma
	 * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
	 * or brk vma (with NULL file) can only be in an anon_vma list.
	 */
	/* 
     * 指向匿名线性区链表头的指针,这个链表会将此mm_struct中的所有匿名线性区链接起来
     * 匿名的MAP_PRIVATE、堆和栈的vma都会存在于这个anon_vma_chain链表中
     * 如果mm_struct的anon_vma为空,那么其anon_vma_chain也一定为空
     */
	struct list_head anon_vma_chain; /* Serialized by mmap_sem &
					  * page_table_lock */
    /* 指向anon_vma数据结构的指针,对于匿名线性区,此为重要结构 */
	struct anon_vma *anon_vma;	/* Serialized by page_table_lock */

	/* Function pointers to deal with this struct. */
    /* 指向线性区操作的方法,特殊的线性区会设置,默认会为空 */
	const struct vm_operations_struct *vm_ops;

	/* Information about our backing store: 后备存取器有关信息 */
    /* 如果此vma用于映射文件,那么保存的是在映射文件中的偏移量。
     * 如果是匿名线性区,它等于0或者vma开始地址对应的虚拟页框号(vm_start >> PAGE_SIZE),
     * 这个虚拟页框号用于vma向下增长时反向映射的计算(栈) 
     */
	unsigned long vm_pgoff;		/* Offset (within vm_file) in PAGE_SIZE
					   units */
    /* 指向映射文件的文件对象,也可能指向建立shmem共享内存中返回的struct file,
     * 如果是匿名线性区,此值为NULL或者一个匿名文件(这个匿名文件跟swap有关?待看) 
     */
	struct file * vm_file;		/* File we map to (can be NULL). */
	void * vm_private_data;		/* was vm_pte (shared mem) */

#ifndef CONFIG_MMU
	struct vm_region *vm_region;	/* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMA
	struct mempolicy *vm_policy;	/* NUMA policy for the VMA */
#endif
	struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
};

由于这些地址空间归属于各个用户进程,所以在用户进程的struct mm_struct数据结构中也有相应的成员,用于对这些VMA进程管理。

struct mm_struct {
    /* 指向线性区对象的链表头,链表是经过排序的,按线性地址升序排列,里面包括了匿名映射线性区和文件映射线性区 */
	struct vm_area_struct *mmap;		/* list of VMAs 虚拟内存区域列表 */
    /* 指向线性区对象的红黑树的根,一个内存描述符的线性区会用两种方法组织,链表和红黑树,红黑树适合内存描述符有非常多线性区的情况 */
    struct rb_root mm_rb;               /* 虚拟内存区域红黑树 */
    ...
};

每个VMA都要连接到mm_struct中的链表和红黑树中,以便查找。

  • mmap形成一个单链表,进程中所以的VMA都链接到这个链表中,链表头是mm_struct->mmap,节点元素是vm_area_struct->vm_next和vm_prev。
  • mm_rb是红黑树的根节点,子节点为vm_area_struct->rb,红黑树的键值为vm_area_struct->vm_end,每个进程有一颗VMA的红黑树。

VMA按照起始地址一递增的方式插入mm_struct->mmap链表中。当进程拥有大量的VMA时,扫描链表和查找特定的VMA是非常低效的操作,例如在云计算的机器中,所以内核中通常要靠红黑树来协助,以便提高查找速度。

操作VMA
1.查找VMA

通过虚拟地址addr来查找VMA是内存中常用的操作。

1.1 find_vma() 函数根据给定地址addr查找满足如下条件之一的VMA:

  • addr在VMA空间范围内,即vma->vm_start <= addr < vma->vm_end。
  • 距离addr最近并且VMA的结束地址大于addr的一个VMA。
struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
{
	struct rb_node *rb_node;
	struct vm_area_struct *vma;

    //1
	/* Check the cache first. */
	vma = vmacache_find(mm, addr);
	if (likely(vma))
		return vma;

    //2
	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;
	}

    //3
	if (vma)
		vmacache_update(addr, vma);
	return vma;
}

find_vma()实现流程:

  1. 查找缓存,若在缓存中找到,则直接返回。在task_struct结构中,有一个存放最近访问过的VMA的数组vmacache[VMACACHE_SIZE],可以存放几个最近使用的VMA,充分利用局部性原理。
  2. 根据红黑树进行查找。这是一个典型的红黑树查找方式,根据键值选择左节点或者右节点。
  3. 若找到满足要求的VMA,则更新缓存。注意更新缓存时数组下标的哈希计算。基于页码,为具有良好局部性和随机访问的工作负载提供良好的命中率。

1.2 find_vma_prev() 函数的逻辑与find_vma()一样,但是返回VMA的前继成员。

struct vm_area_struct *
find_vma_prev(struct mm_struct *mm, unsigned long addr,
			struct vm_area_struct **pprev)
{
	struct vm_area_struct *vma;

	vma = find_vma(mm, addr);
	if (vma) {
		*pprev = vma->vm_prev;
	} else {
		struct rb_node *rb_node = mm->mm_rb.rb_node;
		*pprev = NULL;
		/* 遍历找到最大的节点 */
		while (rb_node) {
			*pprev = rb_entry(rb_node, struct vm_area_struct, vm_rb);
			rb_node = rb_node->rb_right;
		}
	}
	return vma;
}

pprev参数存放小于addr的VMA指针。

1.3 find_vma_intersection() 函数用于查找start_addr、end_addr和现存的VMA有重叠的一个VMA,它基于find_vma()实现。

static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr)
{
	struct vm_area_struct * vma = find_vma(mm,start_addr);

	if (vma && end_addr <= vma->vm_start)
		vma = NULL;
	return vma;
}
2.插入VMA

insert_vm_struct()是内核提供的插入VMA的核心API函数。

int insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vma)
{
	struct vm_area_struct *prev;
	struct rb_node **rb_link, *rb_parent;

    //1.
	if (find_vma_links(mm, vma->vm_start, vma->vm_end,
			   &prev, &rb_link, &rb_parent))
		return -ENOMEM;
    //2.
	if ((vma->vm_flags & VM_ACCOUNT) &&
	     security_vm_enough_memory_mm(mm, vma_pages(vma)))
		return -ENOMEM;

	/*
	 * The vm_pgoff of a purely anonymous vma should be irrelevant
	 * until its first write fault, when page's anon_vma and index
	 * are set.  But now set the vm_pgoff it will almost certainly
	 * end up with (unless mremap moves it elsewhere before that
	 * first wfault), so /proc/pid/maps tells a consistent story.
	 *
	 * By setting it to reflect the virtual start address of the
	 * vma, merges and splits can happen in a seamless way, just
	 * using the existing file pgoff checks and manipulations.
	 * Similarly in do_mmap_pgoff and in do_brk.
	 */
	//3.
	if (vma_is_anonymous(vma)) {
		BUG_ON(vma->anon_vma);
		vma->vm_pgoff = vma->vm_start >> PAGE_SHIFT;
	}

    //4.
	vma_link(mm, vma, prev, rb_link, rb_parent);
	return 0;
}

insert_vm_struct()实现流程

  1. 寻找插入位置,寻找的过程很有意思,运用了二级指针和三级指针作为形参。
  2. 若该区域是一个记账VMA区域(没懂),这个机制还没遇到过。
  3. 如果VMA是匿名映射区,则设置vma->vm_pgoff等于区域起始页码。
  4. 插入到链表和红黑树中,若是文件映射,加入到文件的基数树中。
3.合并VMA

在新的VMA被加入到进程的地址空间时,内核会检查它是否可以与现存的VMA进行合并。vma_merge()函数实现将一个新的VMA和附近的VMA合并的功能。

struct vm_area_struct *vma_merge(struct mm_struct *mm,
			struct vm_area_struct *prev, unsigned long addr,
			unsigned long end, unsigned long vm_flags,
			struct anon_vma *anon_vma, struct file *file,
			pgoff_t pgoff, struct mempolicy *policy,
			struct vm_userfaultfd_ctx vm_userfaultfd_ctx)
{
    /* 计算出区域大小,单位是页 */
	pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
	struct vm_area_struct *area, *next;
	int err;

	/*
	 * We later require that vma->vm_flags == vm_flags,
	 * so this tests vma->vm_flags & VM_SPECIAL, too.
	 */
	/* VM_SPECIAL指的是non-mergable, non-mlock的VMAs */
	if (vm_flags & VM_SPECIAL)
		return NULL;

	if (prev)
		next = prev->vm_next;
	else
		next = mm->mmap;
	area = next;
	if (area && area->vm_end == end)		/* cases 6, 7, 8 */
		next = next->vm_next;

	/* verify some invariant that must be enforced by the caller */
	VM_WARN_ON(prev && addr <= prev->vm_start);
	VM_WARN_ON(area && end > area->vm_end);
	VM_WARN_ON(addr >= end);

	/*
	 * Can it merge with the predecessor?
	 */
	/* 判断能否与前继区域合并 
     * 合并条件:1.插入区域的起始地址与前一区域的结束地址相等
     *           2.在NUMA架构中,判断两个区域的vm_policy是否相等
     *           3.判断prev是否满足合并(vm_flag、vm_file、...)
     * 真正的合并工作在__vma_adjust()函数中进行,太长了,看不下去
     */
	if (prev && prev->vm_end == addr &&
			mpol_equal(vma_policy(prev), policy) &&
			can_vma_merge_after(prev, vm_flags,
					    anon_vma, file, pgoff,
					    vm_userfaultfd_ctx)) {
		/*
		 * OK, it can.  Can we now merge in the successor as well?
		 */
		/* 理想情况是新插区域的结束地址等于next节点的起始地址,那么前后节点prev和next可以合并在一起
		 * 这里判断条件多了一个prev与next的判断
		 */
		if (next && end == next->vm_start &&
				mpol_equal(policy, vma_policy(next)) &&
				can_vma_merge_before(next, vm_flags,
						     anon_vma, file,
						     pgoff+pglen,
						     vm_userfaultfd_ctx) &&
				is_mergeable_anon_vma(prev->anon_vma,
						      next->anon_vma, NULL)) {
							/* cases 1, 6 */
			err = __vma_adjust(prev, prev->vm_start,
					 next->vm_end, prev->vm_pgoff, NULL,
					 prev);
		} else					/* cases 2, 5, 7 */
			err = __vma_adjust(prev, prev->vm_start,
					 end, prev->vm_pgoff, NULL, prev);
		if (err)
			return NULL;
		khugepaged_enter_vma_merge(prev, vm_flags);
		return prev;
	}

	/*
	 * Can this new request be merged in front of next?
	 */
	/* 判断能否与后继区域合并 */
	if (next && end == next->vm_start &&
			mpol_equal(policy, vma_policy(next)) &&
			can_vma_merge_before(next, vm_flags,
					     anon_vma, file, pgoff+pglen,
					     vm_userfaultfd_ctx)) {
		if (prev && addr < prev->vm_end)	/* case 4 */
			err = __vma_adjust(prev, prev->vm_start,
					 addr, prev->vm_pgoff, NULL, next);
		else {					/* cases 3, 8 */
			err = __vma_adjust(area, addr, next->vm_end,
					 next->vm_pgoff - pglen, NULL, next);
			/*
			 * In case 3 area is already equal to next and
			 * this is a noop, but in case 8 "area" has
			 * been removed and next was expanded over it.
			 */
			area = next;
		}
		if (err)
			return NULL;
		khugepaged_enter_vma_merge(area, vm_flags);
		return area;
	}

	return NULL;
}
4.创建VMA
unsigned long
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
		unsigned long pgoff, unsigned long flags)
{
	unsigned long (*get_area)(struct file *, unsigned long,
				  unsigned long, unsigned long, unsigned long);

	unsigned long error = arch_mmap_check(addr, len, flags);
	if (error)
		return error;

	/* Careful about overflows.. */
	if (len > TASK_SIZE)
		return -ENOMEM;

	get_area = current->mm->get_unmapped_area;
	if (file) {
		if (file->f_op->get_unmapped_area)
			get_area = file->f_op->get_unmapped_area;
	} else if (flags & MAP_SHARED) {
		/*
		 * mmap_region() will call shmem_zero_setup() to create a file,
		 * so use shmem's get_unmapped_area in case it can be huge.
		 * do_mmap_pgoff() will clear pgoff, so match alignment.
		 */
		pgoff = 0;
		get_area = shmem_get_unmapped_area;
	}

	addr = get_area(file, addr, len, pgoff, flags);
	if (IS_ERR_VALUE(addr))
		return addr;

	if (addr > TASK_SIZE - len)
		return -ENOMEM;
	if (offset_in_page(addr))
		return -EINVAL;

	error = security_mmap_addr(addr);
	return error ? error : addr;
}
linux内核那些事之VMA常用操作 内核对vm_area_struct 数据结构相关操作进行了一系列封装,方面进行后续操作,vma的操作实现大部分位于mm\mmap.c文件中 find_vma() find_vma()是内核中经常需要查找某个给定的虚拟地址是否已经分配,源代码如下: /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ struct vm_area_struct *find_vma(struct mm_struct 阅读详情

相关推荐

linux内核那些事之 VMA Gap

rb_subtree_gap kernel为了提高对VMA 查找、插入速度,采用了很多技术,例如VMA采用RB tree和 双向链表两种组织形式,另外对VMA结构对cache line对齐从而提高cache命中率等。由于内存在实际使用过程中,不断的申请释放,使得原来成片的连续内存空间变成了一段段不连续空间,每个VMA都存在一定空闲空间即gap: 在查找GAP时,一般为了知道GAP大小,需要知道前一个VMA prev的end地址和当前VMA的start地址即GAP=vma->start-..

weixin_42730667的博客 1044

向量自回归VAR模型、结构向量自回归SVAR模型、VMA模型

weixin_45593242的博客 1万+

向量自回归模型建模步骤梳理(VAR、VMA、VARMA模型)

向量自回归模型建模步骤梳理(VAR、VMA、VARMA模型)

根据序列选择自回归模型(AR、ARMA、VAR、VMA、VECH)

weixin_45593242的博客 2630

EGO-Planner文章解读(一)——论文原理和算法实现

详细解读egoplanner论文和代码

fegxg的博客 3990

linux 内核vxlan收发包流程

1.vxlan口收包处理流程 前面几章详细介绍了vxlan接口的使用,而且已经知道vxlan是 MAC IN UDP中的封装,因此,在解封装之前,一切按照原有流程走,在此复习一下内核收发包流程(驱动层的数据处理这次不再解析,直接从__netif_receive_skb_core开始) #物理网卡处理中断,触发softirq i40e_intr └─napi_schedule_irqoff #i40e softirq把包放到per cpu backlog,触发softirq i40e_napi_p

魏言华的博客 3826

多元时间序列分析统计学基础:基本概念、VMA、VAR和VARMA

顾名思义,多元时间序列是与时间相关的多维数据。我们可以用以下数学公式定义多元时间序列数据:其中Zᵢ,ₜ是时间t下第i个分量变量,注意它对每个i和t都是一个随机变量。Zₜ具有(m, t)维度。当我们分析多元时间序列时,不能应用标准的统计理论。这意味着什么?请记住多元线性回归。当计算多元线性回归(1)的似然时,我们假设样本中的每个观测值(=xᵢ)独立于其他观测值。因此可以通过单个观测值的概率密度的乘积轻松计算似然。通常假设观测值遵循具有以下参数的正态分布。但是在多元时间序列中,Zₜ依赖于i和t。

deephub 5159

Rust Reqwest+Rustls 自签名证书校验

所以这里必须保证reqwest引用的rustls库和本地工程一致。以上就是实现不校验签名的逻辑,后续自己可以在对应回调进行逻辑判断。

bawomingtian123的专栏 1357

什么是MVVM模型

MVVM(Model-View-ViewModel)是一种用于构建 Web 前端应用程序的架构模式。它是从传统的 MVC(Model-View-Controller)模型演变而来,旨在解决界面逻辑与业务逻辑之间的耦合问题。

有我更精彩的博客 1185

从涡流求解器到瞬态场:Maxwell 3D里无线充电仿真,选对求解器能省一半计算时间

本文深入探讨了Maxwell 3D在无线充电仿真中涡流求解器与瞬态求解器的选择策略,帮助工程师优化计算效率与精度。通过对比分析两种求解器的适用场景、性能差异及实战技巧,揭示如何根据频率特性、材料非线性和动态过程需求做出精准选择,可节省高达50%的计算时间。特别针对3D线圈模型的无线充电系统设计提供了专业建议。

weixin_26861329的博客 232

CocosCreator3.8.2实战:5分钟搞定多分辨率适配与横竖屏自动翻转(附完整Demo)

本文针对CocosCreator3.8.2开发者,提供了一套5分钟快速集成、开箱即用的多分辨率屏幕适配与横竖屏自动翻转解决方案。通过封装好的ScreenAdapter组件,开发者无需处理复杂计算,即可实现等比缩放或拉伸全屏两种主流适配模式,并自动响应设备旋转,有效解决移动端UI在不同屏幕比例和方向下的显示问题。文末附完整Demo。

z4a5b6的博客 723

Python实现向量自回归移动平均与外生变量模型(VARMAX算法)项目实战

Python实现向量自回归移动平均与外生变量模型(VARMAX算法)项目实战

张陈亚的博客 2510

Spring AI 实战:第七章、Spring AI Advisor机制之记忆大师

从金鱼到最强大脑通过 Spring AI 的记忆功能,我们成功让 AI:记住了用户身份实现了多用户隔离做到了持久化存储最终效果用户:“和上次一样” → AI 秒懂用户:“你知道我的名字吗?” → AI:“当然,张三!AI的进化路线🐟金鱼脑 →🧠最强大脑 →🏛️记忆宫殿管理员。

liaokailin的专栏 1516

linux VMA创建场景详解

本文总结了Linux内核中VMA(虚拟内存区域)的主要创建场景,包括常见系统调用和特殊场景。关键创建方式包括:1)mmap()进行匿名/文件/共享内存映射;2)malloc()大内存分配(>128KB)触发mmap;3)程序加载时自动创建各段VMA;4)mprotect()修改权限导致VMA分割;5)线程创建时生成栈VMA;6)设备文件映射创建设备VMA。其他操作如fork()复制VMA、mremap()调整VMA等也会影响VMA布局。这些机制共同构成了Linux灵活的内存管理基础。

图形/计算GPU的驱动与虚拟化技术分享园地 2231

【晶振专题】晶振学习笔记——ST AN2867应用手册 2

通过学习AN2867设计指南,我们知道皮尔斯晶振的基本知识。也了解了晶振的负载电容计算方法、安全因子测试方法和反馈电阻的作用。

一点硬件 1364

RK3568 HDMI输出调试:分辨率切换与EDID解析

厂商信息(Vendor ID)显示器型号(Product ID)支持的分辨率列表色彩特性音频支持情况检查项方法HPD 信号EDID 读取当前模式TMDS 时钟PHY 状态。

小灰灰的博客 1489

2.7 VMA操作

目录 1、查找VMA。find_vma()/find_vma_prev() 1.1 在current->vmacache的cache中查找匹配的vma。 1.2 遍历进程的rb_node tree找匹配的vma。 find_vma_pre()与1,2类似,只不过找prev的vma。 2、插入VMA。insert_vm_struct() 2.1 找到vma要插入位置相关的:父结点(rb_parent),要插入位置的地址(rb_link),前一个vma(prev)。 2.2 将vma加入到对

New_Worms的专栏 774

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

VMA与page fault

一、 红黑树与VMA 红黑树的应用: 广泛用于 C++ 的 STL 中,set 和 map 是用红黑树实现的; Linux 的的进程调度,用红黑树管理进程控制块,进程的虚拟内存空间都存储在一颗红黑树上,每个虚拟内存空间都对应红黑树的一个节点,左指针指向相邻的虚拟内存空间,右指针指向相邻的高地址虚拟内存空间; IO 多路复用的 epoll 采用红黑树组织管理 sockfd,以支持快速的增删改查; Nginx 中用红黑树管理定时器,因为红黑树是有序的,可以很快的得到距离当前最小的定时器; Java 的 Tre

much efforts, much luck 914

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

8.1 查找VMA

通过虚拟地址addr来查找VMA是内核中常用的操作,内核提供一个API函数来实现这个查找操作。find_vma()函数根据给定地址addr查找满足如下条件之一的VMA,如下图: addr在VMA空间范围内,即vma->vm_start <= addr < vma->vm_end。[vma->vm_start, vma->vm_end) 距离addr最近并且VMA的结束地址大于addr的一个VMA。 find_vma函数的实现如下: mm...

Do one thing at a time, and do well. 1130

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

vma的基本操作

在Linux内核中,这样的区域被称之为虚拟内存区域(virtual memory areas),简称vma。一个vma就是一块连续的线性地址空间的抽象,它拥有自身的权限(可读,可写,可执行等等) ,每一个虚拟内存区域都由一个相关的struct vm_area_struct结构来描述 struct vm_area_struct { struct mm_struct * vm_mm; /* 所

farmwang的专栏 6189

sfence.vma

清除TLB缓存 所有现代的处理器都用地 址转换缓存(通常称为 TLB,全称为 Translation Lookaside Buffer)来减少这种开销。为了 降低这个缓存本身的开销,大多数处理器不会让它时刻与页表保持一致。这意味着如果操 作系统修改了页表,那么这个缓存会变得陈旧而不可用。S 模式添加了另一条指令来解决 这个问题。这条sfence.vma 会通知处理器,软件可能已经修改了页表,于是处理器可以 相应地刷新转换缓存。它需要两个可选的参数,这样可以缩小缓存刷新的范围。一个位于 rs1,它指...

yiyeguzhou100的专栏 5333

VMA与LMA

​​​​​​VMA:Virtual Memory Address 运行地址,程序真正运行的地址空间 LMA:Load Memory Address 加载地址,程序实际存储的地址空间 运行地址就是程序运行的地址,PC指针指向的地址,比如程序中print出的函数地址、数组地址等,都是指VMA。 要作为运行地址,首先PC指针要能在这个地址空间内跑动,所以这段地址空间必须是可随机寻址的,也就是说可以...

stopshooting的博客 1691

VMA实战操练

在上篇文章根据crash学习用户空间程序内存布局涉及到了VMA的相关操作,本节通过一个简单的实例来深刻的学习下VMA是什么,以及VMA是如何组织的。 先来看下VMA的结构体 struct vm_area_struct { /* The first cache line has the info for VMA tree walking. */ unsigned long vm_s...

半月旋空 1327

一个进程的VMA区域

一个进程基本可以分为以下几种VMA区域: 代码VMA,权限只读、可执行;有映像文件 数据VMA,权限可读写、可执行;有映像文件 堆VMA,权限可读写、可执行;无映像文件,匿名,可向上扩展 栈VMA,权限可读写、不可执行;无映像文件,匿名,可向下扩展

空山无人,水流花开 666

VMA-virtual memory areas

【代码】VMA-virtual memory areas。

Jun's blog 263

从find_vma和find_vma_prev看内核

首先看一个问题: Linux has both find_vma_prev and find_vma routines. find_vma_prev returns both the current and previous VMAs. Therefore, find_vma could be written as a simple layer routine over find_vma_pr

TCP/IP 7501
上一篇: 关于安装TortoiseSVN.msi 报错2203错误
下一篇: malloc实现
识荒者
博客等级 码龄10年 533粉丝 79原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值