内存管理
文章目录
1 虚拟内存抽象模型
在虚拟内存系统中以上所有的地址都是虚拟地址而不是物理地址。处理器基于由操作系 统维护的一组表中的信息,将虚拟地址转换成物理地址。 为了使这种变换容易一些,虚拟内存和物理内存都被分为合适大小的块叫做页 (page)。 这些页中每一个 都有一个唯一的号码:页帧号(Page Frame Number, PFN)。在这种分页模型中,一个虚拟地址由两部分组成:一个偏移和一个虚拟页帧号。每当处理器面临一个虚拟地址时,它必须析取出偏移和 虚拟页帧号。将虚拟页帧号转换成物理的页帧号,然后在该物理页中正确的偏移位置上进行访问。
1.1 交换
如果一个进程想将一个虚拟页装入物理内存,而又没有可使用的空闲物理页,操作系统 就必须淘汰物理内存中的其他页来为此页腾出空间。
1.2 共享虚拟内存
虚拟内存使得几个进程共享内存变得容易。所有的内存访问都是通过页表进行,并且每 个进程都有自己的独立的页表。
3 内存映射
当一个映像被执行时,该可执行映像的内容必须被放到进程的虚拟地址空间。可执行文件并非真正地被读到物理内存,而只是链接到进程的虚拟内存。这种将一个映像链接到一个进程的虚拟地址空间的技术也被称为内存映射 (memery mapping)。
#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flag, int fd, off_t off);
//成功返回映射区的起始地址,出错返回MAP_FAIL
int mprotect(void *addr, size_t len, int prot);
int msync(void *addr, size_t len, int flags);
int munmap(void *addr, size_t len);
//成功返回0,出错返回-1
3.1 mmap函数
将一个给定文件映射到一个存储区域中。
addr:用于指定映射存储区的起始位置。通常设置为0,表示由系统选择该映射区的起始位置。
fd:指定要被映射文件的描述符。在文件映射到地址空间之前,必须先打开该文件。
len:映射的字节数。
off:要映射字节在文件中的起始偏移量。通常设置为0。
prot:指定了映射存储区的保护要求,可指定为下表前三项的位或,或者最后一项。对指定映射存储区的保护要求不能超过文件open模式访问权限。
prot | 说明 |
---|---|
PROT_READ | 映射区可读 |
PROT_WRITE | 映射区可写 |
PROT_EXEC | 映射区可执行 |
PROT_NONE | 映射区不可访问 |
flag:影响存储区的多种属性,必须指定为MAP_SHARED或者MAP_PRIVATE。
flag | 说明 |
---|---|
MAP_FIXED | 返回值必须等于addr,不利于可移植性,不推荐使用 |
MAP_SHARED | 指定存储操作修改映射文件,即存储操作相当于对该文件的write |
MAP_PRIVATE | 对映射区的存储操作导致创建该映射文件的一个私有副本,所有后来对该映射区的引用都是引用该副本。 |
3.2 mprotect函数
可以更改一个现有映射的权限。
3.3 msync函数
若共享映射中的页已被修改,则可以调用msync将该页冲洗到被映射的文件中。
3.4 munmap函数
当进程终止时,会自动解除存储映射区的映射,或直接调用munmap函数解除映射区。关闭映射区使用的文件描述符不会解除映射区。
3.3 相关信号
SIGSEGV:用于指示进程试图访问对它不可用的存储区。
SIGBUS:用于指示进程试图访问映射区已不存在的某个部分。
4 存储空间动态分配
#include <stdlib.h>
void *malloc(size_t size);
void *calloc(size_t nobj, size_t size);
void *realloc(void *ptr, size_t newsize);
//成功返回非空指针,出错返回NULL
void free(void *ptr);
4.1 malloc
分配指定字节数的存储区,此存储区中的初始值不确定。
4.2 calloc
为指定数量指定长度的对象分配存储空间,该空间中的每一位都初始化为0。
4.3 realloc
的初始值不确定。
4.2 calloc
为指定数量指定长度的对象分配存储空间,该空间中的每一位都初始化为0。
4.3 realloc
增加或减少以前分配区的长度,新增区域内初始值不确定。newsize是存储区的新长度,不是新、旧存储区长度之差。