虚拟内存可以使计算机操纵更大的地址空间,使系统中的每一给进程拥有独立的虚拟地址空间,所以运行一个程序的进程不会影响到其他进程。
另外,硬件的虚拟内存机制允许对内存区写保护,这可以防止代码和数据被错误的程序覆盖。内存映射可以将cpu的虚拟地址空间映射到物理内存。
虚拟内存机制虽然允许进程拥有独立的地址空间,但有时也需要进程之间共享内存。有些程序会被多个进程运行(bash),此时更好的方法是
再物理内存中只拥有一份bash的代码,所有运行bash的进程共享代码。动态链接库也是一个常见的多个进程共享执行代码的的常见例子。
linux虚存采用动态地址映射方式,也就是说进程的地址空间和存储空间的对应关系是在程序执行的过程中实现的。进程使用的是虚拟地址,因此
他对每个地址的访问都需要通过MMU转化为内存的物理地址。
动态地址映射可以使linux 实现进程在主存中的动态重定位、虚拟内存的动态扩展和移动,也为虚拟内存的实现提供了基础。当linux的进程映像执行
时,需要调入可执行映像的内容(相关代码)。但是不用把这些数据直接调入物理内存,只需要将这些数据与虚拟地址空间关联起来。只有当正真执行
需要先关数据时才真正调入内存。这种进程的映像和虚拟地址空间的连接称为内存映像。
当需要将进程的映像调入到进程的虚拟内存空间时,需要申请一段合适的虚拟内存空间,这时linux使用do_mmap() 函数完成可执行映像向虚存区域的
映射,建立有关虚存区域,/include/linux/mm.h文件中:
static inline unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
{
unsigned long ret = -EINVAL;
if ((offset + PAGE_ALIGN(len)) < offset)
goto out;
if (!(offset & ~PAGE_MASK))
ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
out:
return ret;
}
file 指向该文件结构体的指针;
addr 虚存区域在虚拟内存空间的起始地址;
len 虚存区域的长度;
prot 指定了虚存区域的访问特性;
flag 制定了虚存区域的属性;
offset 相对于文件起始位置的偏移量;
内存的映像详解:
首先,什么叫做内存映像呢? 进程的内存映像,指的是内核在内存中如何存放可执行程序文件。注意了,这里的可执行程序文件和内存映像是有区别的,,具体是:
1) 可执行程序是位于硬盘上的,而内存映像位于内存上;
2) 可执行程序没有堆栈,因为只有当程序被加载到内存上的时候才会分配相应的堆栈
3) 可执行程序是静态的,因为它还没运行,但是内存映像是动态的,数据是随着运行过程改变的;
尽管程序映像看起来占据了一个连续的内存块,但实际上,操作系统将程序映像映射到不一定连续的物理内存块中。通常的映射将程序映像划分成大小相同的片,这些片被称为页(PAGE)。操作系统将这些页加载到内存中,当处理器引用某页上的内存时,操作系统会从一个表中查找这一页的物理位置。这种映射方式允许栈和堆有很大的逻辑地址空间,除非需要,否则这些栈和堆实际上可以不占用物理内存。操作系统隐藏了这种底层映射的存在,这样,即使有些页实际上并没有驻存在内存中,程序员也可以认为程序映像在逻辑上是连续的。
本文深入探讨了虚拟内存机制,包括其如何使计算机操纵更大的地址空间、硬件的虚拟内存机制、内存映射以及如何实现进程间的内存共享。重点介绍了动态链接库和bash程序在多个进程中的应用,同时详细解释了Linux中内存映像的概念,以及内存映像如何在内存中存放可执行程序文件,并通过do_mmap()函数进行内存区域映射。
3871

被折叠的 条评论
为什么被折叠?



