今天:-malloc() free() sbrk() brk() mmap() munmap()
文件读写函数(UC版)
malloc() 和 free()
malloc()分配的是堆区的内存 一次申请小块内存时,系统会映射33个内存页,如果申请大块内存(31个内存页以上),系统会映射比申请稍多一点的内存页数。
malloc申请内存时,除了数据占用的空间外,还需要额外占用一些空间,用于存储附加数据。malloc申请内存时,会包括三部分:数据本身的空间,附加数据的空间,空的空间(预留空间)。附加数据存于 底层维护的双向链表中。预留空间的大小不确定,可大可小。
int* pi = malloc(4);
free(pi);//free()释放到哪里结束呢? 附加数据中有。
理论上因为malloc()会映射多个内存页,导致未分配的内存只要在33页之内都能使用;但是为了便于内存的管理(反复使用和控制),内存还是要 先分配再使用。
free()一定会释放被占用的虚拟内存地址,但是不一定会解除内存映射,对于malloc()来说,free()不会释放最后的33个内存页映射。最后33个内存页的映射在进程结束时才会释放。free()在大多数情况下会清空内存,但是不保证清()
free对于申请大块内存时会 全部解除映射。
经验:malloc()虽然地址不连续,但是不影响内存的使用;malloc()申请的内存在使用时不要过界,否则会影响下一次的内存分配和回收。
sbrk()和brk()
sbrk()和brk()是Unix的系统函数,机制和malloc是完全不同的。借助系统维护的一个位置进行内存的分配和回收。
void* sbrk(int increment) 功能就是分配//回收内存,大多数情况下用于分配内存。
参数increment是分配/回收的增量,为正数分配,为负数时,回收,为0时候取当前值。
返回值返回移动之前的位置,如果出错返回(void*) -1.
sbrk()在分配内存时非常方便,但回收内存时需要计算字节数,因此比较麻烦,不便于管理。brk()则相反。
一般情况下都是使用sbrk()分配内存,使用brk()释放内存(虽然这两个函数都可以分配和回收)。
sbrk()和brk()都是以一个内存页作为映射的基本单位的,一旦释放就会同时解除内存映射。
int brk(void* position) 功能就是分配/回收内存,一般用于回收内存
参数position就是新位置,无论原来的位置在哪里。返回:成功返回0,失败返回 -1。
brk() 和sbrk() 不会清除回收内存的数据,数据会在下次使用时被覆盖。
memset()可以设置内存的内容,一般用于清内存;
memcpy()可以复制内存的内容,一般用内存复制。
mmap() 和munmap()
用户层能使用的功能最强大的函数,可以设置一些内存相关的数据。mmap()实现内存映射,包括:映射物理内存和硬盘文件
各种权限和多个选项用位或 | 连接。
RWX
R-- 100
-W- 010
--X 001
读+写
100 | 010
void* mmap(void* addr,size_t length, int prot, int flats, int fd, off_t offset)
功能是内存映射,比sbrk()功能强大的多,失败返回-1
参数:addr指定映射的首地址,为0就是交给内核选择。
size 就是映射内存的大小
prot 就是内存的权限 一般是PROT——READ|PROT——WRITE
flats 就是映射的标识 主要包括:
MAP_SHARD MAP_PRIVATE 2选1,
MAP_SHARED 代表这块内存其他进程可以共享,但只对映射文件有效
MAP_PRIVATE就是其他进程不能共享,只能本进程使用。
MAP——ANONYMOUS代表映射 物理内存,不写就映射硬盘文件(默认映射)。
fd 是文件描述符,映射文件时有效,映射物理内存为0.
offset 是文件偏移量,选择映射文件的位置,映射物理内存 为0;
返回:成功返回映射的首地址,失败返回MAP——FAILED
用户空间的程序不能进入内核空间,但很多功能需要内核实现,因此内核空间 提供了一系列的函数, 允许用户空间调用,从而进入内核空间。这一系列的函数通称为 系统调用(system call)。比如:标C的malloc() 不能进入Unix内核,但内存分配必须依赖内核,内核提供了系统调用sbrk()和mmap(),帮助malloc()进入内核完成内存的分配。
系统调用的使用方式和标C函数没有任何区别,因此无需过多关注。
eg:
int* pi =mmap(NULL,//首地址内核选择
6 4,//分配4字节,映射还是按一页算
7 PROT_READ | PROT_WRITE,//权限
8 MAP_PRIVATE | MAP_ANONYMOUS,//映射物理内存用 PRIVATE,ANNONYMOU S代表映射物理内存
9 0,0);//文件描述符映射物理内存给()
10 if(pi == MAP_FAILED)
11 {
12 perror("MMAP");
13 return -1;
14 }
15 *pi = 100;
16 printf("%d\n",*pi);
17 munmap(pi,4);
网友评论