一篇关于Linux内存管理的深度解析

转载:https://blog.csdn.net/weixin_42462202/article/details/102157454

这是一篇转载贴,原作者是上面这位,下文中用到的图片均是取自原作,我做了裁剪和整理,如果想要更细致的了解,请移步原文观看。

Linux内存管理

linux内存管理主要涉及到这样几件事,一个是虚拟内存管理,一个是物理内存管理,还有就是虚拟内存与物理内存之间、虚拟内存与文件系统之间的映射。

Linux进程空间的管理

在进程描述符task_struct内有一个用于管理虚拟内存的结构体mm_struct.

struct mm_struct **mm;

该结构体描述的是整个进程的虚拟内存状态信息。比如:用户空间的大小

unsigned long task_size;

32位操作系统下,用户空间为3G,内核空间是1G。

在这里插入图片描述


相应的数据结构为

struct mm_struct{
unsigned long mmap_base;	/* base of mmap area,内存映射区起始地址 */
unsigned long total_vm;		/* Total pages mapped,总共映射页的数目 */
unsigned long locked_vm;	/* Pages that have PG_mlocked set,被锁定不能换出的页数目 */
unsigned long pinned_vm;	/* Refcount permanently increased,不能换出也不能移动的页数目 */
unsigned long data_vm;		/* VM_WRITE & ~VM_SHARED & ~VM_STACK,存放数据的页数目 */
unsigned long exec_vm;		/* VM_EXEC & ~VM_WRITE & ~VM_STACK,存放可运行程序的页数目 */
unsigned long stack_vm;		/* VM_STACK,栈所占的页数目 */
unsigned long start_code, end_code, start_data, end_data; //代码段和数据段的位置
unsigned long start_brk, brk, start_stack; //堆的位置,栈底位置,栈顶存放在栈指针寄存器中
unsigned long arg_start, arg_end, env_start, env_end; //参数列表和环境变量的位置
}

从上面的数据结构中可以看出,没有相应的分区描述信息。那么如何描述不同的分区呢?

有另外一个数据结构vm_area_strcut,用于描述和管理不同的分区。

struct vm_area_struct **mmap;  //不同分区的描述信息
struct rb_root mm_rb;
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. vma起始地址*/
	unsigned long vm_end;		/* The first byte after our end address within vm_mm. vma结束地址 */
	/* linked list of VM areas per task, sorted by address 通过地址串接该进程所有vma的链表*/
	struct vm_area_struct *vm_next, *vm_prev;
	struct rb_node vm_rb; // vm_rb是红黑树节点,用于描述该vma在红黑树中的信息
	struct mm_struct *vm_mm;	/* The address space we belong to. 所属地址空间 */
	struct list_head anon_vma_chain; /* Serialized by mmap_sem &
					  * page_table_lock */
	struct anon_vma *anon_vma;	/* Serialized by page_table_lock */
	/* Function pointers to deal with this struct. 针对该vma的相应操作*/
	const struct vm_operations_struct *vm_ops;
	struct file * vm_file;		/* File we map to (can be NULL). 映射到的文件,可以为NULL*/
	void * vm_private_data;		/* was vm_pte (shared mem) 是否共享*/
} __randomize_layout;

在这里插入图片描述

那么这些信息是如何被初始化的呢?或者说如何初始化一个进程的进程空间?这涉及到一个函数load_elf_binary(加载内核是它,启动第一个用户态进程init是它,fork完调用exec执行一个程序也是它).它一般会进行以下的一些操作。

  • 调用set_new_exec设置内存映射区mmap_base
  • 调用set_arg_pages设置栈的vm_area_struct,这里设置mm->area_start指向栈底
  • elf_map会将elf文件中代码段映射到内存中
  • set_brk设置堆的vm_area_struct,这里设置mm->start_brk=mm->brk,即堆为空
  • load_elf_interp将依赖的so文件映射到内存中来

通过以上的相关操作不仅初始化了mm_struct的信息也初始化了vm_area_struct的信息。

那么最终会形成下面的虚拟内存布局形式,注意此时还未与物理内存进行映射。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值