虚拟内存管理

一、虚拟内存管理

我们都知道,每个用户进程可以拥有4GB的可寻址的虚拟地址空间,也可以称为进程地址空间。在32位系统中,进程可以合法访问用户空间的虚拟地址。若要访问内核虚拟地址,就要通过系统调用才行。

内核中是如何来管理这些进程地址空间的呢?根据内核风格,抽象出一个结构体来描述这个进程地址空间,这个结构体就是struct vm_area_struct,看名称可以知道,这就是一虚拟地址的结构体,简称VMA。

一个进程包含下列内存区域:代码段、数据段、用户进程栈、MMAP区域、堆区域。

I、内存描述符mm_struct

linux内核需要管理每个进程所有的内存区域和它们对应的页映射,所以必须抽象出一个数据结构,就是mm_struct数据结构,进程控制块PCB数据结构task_struct中有一个指针mm指向这个mm_struct数据结构。在include\linux\mm_types.h有定义。下面是它的主要成员。

mmap:进程所有的VMA形成一个单链表,这是该链表的链表头

mm_rb:VMA红黑树的根结点

get_unmapped_area:用来判断虚拟内存是否有足够的空间

mmap_base:指向mmap区域的起始地址

pgd:指向进程的页表PGD目录(以及页表)

mm_users:记录正在使用该进程地址空间的线程数目

mm_count:mm_struct的主引用计数

mmap_sem:保护进程地址空间VMA的一个读写信号量

start_code,end_code:代码段的起始地址和终止地址

start_data,end_data:数据段的起始地址和终止地址

brk:表示当前堆中VMA的结束地址

struct mm_struct {
	struct vm_area_struct *mmap;		/* list of VMAs */
	struct rb_root mm_rb;
	u32 vmacache_seqnum;                   /* per-thread vmacache */
    unsigned long (*get_unmapped_area) (struct file *filp,
				unsigned long addr, unsigned long len,
				unsigned long pgoff, unsigned long flags);
	unsigned long mmap_base;		/* base of mmap area */
	
	pgd_t * pgd;
	atomic_t mm_users;			/* How many users with user space? */
	atomic_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
	atomic_long_t nr_ptes;			/* PTE page table pages */
	atomic_long_t nr_pmds;			/* PMD page table pages */
	int map_count;				/* number of VMAs */

	spinlock_t page_table_lock;		/* Protects page tables and some counters */
	struct rw_semaphore mmap_sem;

	struct list_head mmlist;		/* List of maybe swapped mm's.	These are globally strung
						 * together off init_mm.mmlist, and are protected
						 * by mmlist_lock
						 */


	unsigned long hiwater_rss;	/* High-watermark of RSS usage */
	unsigned long hiwater_vm;	/* High-water virtual memory usage */

	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 shared_vm;	/* Shared pages (files) */
	unsigned long exec_vm;		/* VM_EXEC & ~VM_WRITE */
	unsigned long stack_vm;		/* VM_GROWSUP/DOWN */
	unsigned long def_flags;
	unsigned long start_code, end_code, start_data, end_data;
	unsigned long start_brk, brk, start_stack;
    ...
}

 II、malloc实现

malloc是C语言中最常见用的内存分配函数。

先思考以下几个问题:

1、malloc返回的内存是否马上就分配物理内存?如果不是,什么时候才分配?

2、malloc申请100个字节,内核就分配100个字节给进程吗?

3、两个进程malloc之后返回的虚拟地址是一样的,是否代表两者的物理内存也一样呢?

malloc函数其实是为用户空间分配进程地址空间的,用内核术语来说就是分配一块VMA,相当于一块空的纸箱。当使用这段内存时,CPU去查询页表,发现页表并没有映射到物理地址上,即为空。那么CPU会发出缺页异常,然后在缺页异常里一页一页的分配内存。

我们都知道处理器的mmu硬件最小处理单元是页,所以内核分配内存、建立虚拟地址和物理地址映射关系都是以页为单位的。

每个进程都有自己的一份页表,mm_struct有一个pgd成员指向这个页表的基地址,每个进程都有一个mm_struct数据结构,进程的VMA会挂入自己的红黑树和链表,即使两个进程分配到的虚拟地址是一样的,但是他们也有不同的VMA,分别被两套页表来管理。

以下为malloc实现流程:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值