每个进程都有自己独立的4G内存。进程访问数据时,使用的是虚拟内存地址,由操作系统将虚拟地址映射到物理地址。
操作系统为每个进程建立一个从虚拟地址到物理地址的一个映射表。操作系统以“页”为单位进行内存的映射,所以映射表也称为页表。
一页的大小可以通过getpagesize()获得。头文件<unistd.h>
一般来说,两个进程即使使用同一个虚拟内存的地址,实际访问的也是不同的地方。所以指针或地址一但跨越进程将变得毫无意义。
进程内存分段:
代码段:函数和一些常量
数据段:初始化的全局变量和静态局部变量
BSS段:未初始化的全局变量和静态局部变量
堆:动态分配内存
栈:普通局部变量
高地址的1G是分配给内核和动态库的
size用于显示一个程序的大小,test是代码段,data是数据段,不显示堆和栈,因为它们是不定的。
在/proc/目录中以进程id为名的文件夹保存有进程的详细信息。maps和smaps是关于内存映射的。
低级内存分配:
使用malloc\realloc\calloc分配内存,连续两次调用申请的内存地址不是连续的,因为在每块内存的开头或结尾需要保留一点空间来 存储控制信息。
sbrk/brk重新指定数据段的结束位置:
int brk(void *addr) 返回0成功,-1失败
void *sbrk(intptr_t increment) 入参为增量可正可负,返回值为之前的数据段结束位置,失败返回-1 sbrk(0)可获得当前结束位置。
没有使用的虚拟内存地址操作系统就没有映射到物理内存,试图访问该内存地址就会出现断错误。指定新的结束位置如果有整个内存页被空闲出来,这一页立即被解除映射。
mmap/munmap 内存映射和解除映射 头文件<sys/mman.h>
void *mmap(void *addr, //指定映射到那个地址,一般为NULL
size_t length, //长度字节
int prot, //PROT_READ、PROT_WRITE、PROT_EXEC组合
int flags, //MAP_SHARED和MAP_PRIVITE二选一之后再和其他标准的组合:MAP_ANONYMOUS表示不适用文件(内存自动用0初始化)
int fd,
off_t off_set);
void *munmap(viod *addr, size_t length); //取消内存映射