APUE_内存管理
2016-01-24 10:10
555 查看
1.进程 中的内存模型
虚拟内存管理技术unix/linux系统中的内存管理技术是采用虚拟内存管理技术进行管理的,即:每个进程都可一有0~4G的地址空间(虚拟的,并不是真是存在的),由操作系统负责把虚拟地址和真实的物理内存映射起来的(内存地址是以字节为基本单位,但是内存的映射是以内存页为基本单位的,目前主流的操作系统内存页大小是4kb(4096个字节),因此,不同进程的地址空间看起来是一样的,但所对应的真实物理内存并不是一样的。
对于每个进程中的虚拟地址空间来说,分为两部分:用户空间和内核空间
其中0~3G之间的虚拟内存叫做用户空间,而3~4G之间的虚拟地址叫做内核空间;
用户程序一般都运行在用户空间中,内核空间只有系统内核才可以访问,用户程序不能直接访问,但可以通过内核提供的API函数访问。
一般来说,堆区的内存地址从小到大分配,而栈区的内存地址从大到小分配,堆区和栈区之间的距离较远,本质上是因为堆区和栈区之间没有明显的分割线,避免区域重合。
2.内存管理的相关函数
1.sbrk函数#include <unistd.h> void *sbrk(intptr_t increment);
函数功能:
主要用于修改数据段的大小.
参数:当参数 >0时,则申请动态内存,当参数 = 0时,获取当前的内存块位置,当参数 <0时;则释放动态内存空间
返回值:成功返回之前的内存块地址;失败返回(void*)-1,sbrk(0)返回的是当前内存块的末尾地址
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main (viod){ void *p1=sbrk(4); void *p2=sbrk(4); void *p3=sbrk(4); void *p4=sbrk(4); printf("p1=%p,p2=%p,p3=%p,p4=%p\n",p1,p2,p3,p4); void *cur=sbrk(0); printf("cur = %p\n",cur); void *p5=sbrk(-4); printf("p5=%p\n",p5); cur = sbrk(0); printf("cur = %p\n",cur); return 0; }
运行结果:
sbrk 函数的工作方式(一般性原则)
当使用sbrk函数申请比较小的内存时,系统会一次性分配1个内存页大小的空间,如果申请的内存超过1个内存页的范围,则再次分配一个内存页(也就是按照1个内存页的整数倍
管理)
使用sbrk函数释放内存时,如果剩下的内存可以用1个内存页表示则一次性回收一个内存页的空间(也就是按照1个内存页的整数被管理)
当所有内存释放完毕后,系统不再保留内存空间。
注意:使用sbrk函数申请内存比释放内存更方便一些。
2. brk函数
#include <unistd.h> int brk(void *addr);
函数功能:
主要根据参数指定的目标地址调整内存地址,如果目标地址>起始地址,表示申请内存,如果目标地址=起始地址,表示内存空家不变;如果目标地址<起始地址,则表示释放内存;其中最开始的起始地址由操作系统指定。
注意:使用brk函数释放内存比较方便,因此一般情况下与sbrk函数搭配使用,sbrk负责申请内存,brk负责释放内存.
#include<stdio.h> #include<stdlib.h> #include<unistd.h> int main(void){ void *p=sbrk(0); printf("p=%p\n",p); int res=brk(p+4); if(-1 == res){ perror("brk"),exit(-1); } void *cur=sbrk(0); printf("cur=%p\n",cur); brk(p+8); cur=sbrk(0); printf("cur=%p\n",cur); return 0; }
3.getpagesize函数
int gfetpagesize(void)
函数功能:获取内存页的大小,一般为4KB
4.mmamp函数
include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
Para1:建立映射的起始地址,给null表示由内核指定。
Para2:映射的大小,基本单位是内存页
Para3:映射的访问权限(不要和文件的打开方式冲突),
PROT_EXEC :可执行 PROT_READ :可读 PROT_WRITE :可写 PROT_NONE :不可访问
表示映射的标志,是否对其他进程可见
MAP_SHARED:共享的
MAP_PRIVATE:私有的
MAP_ANONYMOUS:映射到物理内存(忽略参数fd和offset)
Para5:文件描述符,暂时给0即可。
Para6:文件中的偏移量,暂时给0即可。
返回值:成功返回映射的地址,失败返回MAP_FAILED(-1)
函数功能:主要建立/解除 文件/设备 到内存的映射
5.munmap函数
int munmap(void *addr, size_t length);
函数功能:主要用于根据参数指定的映射地址的大小进行映射解除。
#include <stdio.h> #include <sys/mman.h> #include <unistd.h> #include <stdlib.h> int main(void){ void *p=mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,0,0); if(p ==-1) { printf("mmap"),exit(-1); } int *pi=p; *pi=200; printf("*pi=%d\n",*pi); int res = munmap(p,4); if(res == -1) { printf("munmap"),exit(-1); } printf("解除映射成功"); return 0; }
相关文章推荐
- Leetcode 128. Longest Consecutive Sequence
- Influencer Finder
- the requested resource is not available
- Unique Path II
- Xib和购物车UI界面的完善
- NSKeyValueSlowMutableCollectionGetter
- 监听UITextField改变事件(三种方法)
- 禁止在Handler、Ui线程中使用第三方控件ImageLoader.loadImageSync函数,缓存问题,很痛苦
- ios 9.0 后用UIAlertController代替了UIAlertView弹框 和 UIActionSheet下弹框
- stl提供了三个最基本的容器:vector,list,deque
- Duilib 窗口流程
- The request sent by the client was syntactically incorrect.
- Duilib技巧:背景图片平铺
- UICollectionView
- 分享一个使用NSIS制作安装包的UI插件
- quickfix的使用
- 【leetcode】142. Linked List Cycle II My Submissions Question
- DUILIB异形窗口实现
- UITableViewCell高度自适应 autoLayout
- IOS开发怎么UINavigationController设置title标题的颜色?