内存

基本概念

内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。

良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。

使用场景

针对用户态开发,OpenHarmony内存提供了一套内存系统调用接口,支持内存的申请释放、重映射、内存属性的设置等,还有C库的标准内存操作函数。

功能

表 1 标准C库相关接口

头文件 接口 功能
strings.h int bcmp(const void s1, const void s2, size_t n) 比较字节序列。
strings.h void bcopy(const void src, void dest, size_t n) 拷贝字节序列。
strings.h void bzero(void s, size_t n) 写入零值字节。
string.h void memccpy(void dest, const void src, int c, size_t n) 拷贝src 所指的内存内容前n 个字节到dest 所指的地址上。复制时检查参数c 是否出现,若是则返回dest 中值为c 的下一个字节地址。
string.h void memchr(const void s, int c, size_t n) 在s所指内存的前n个字节中查找c。
string.h int memcmp(const void s1, const void s2, size_t n) 内存比较。
string.h void memcpy(void dest, const void src, size_t n) 内存拷贝。
string.h void memmem(const void haystack, size_t haystacklen, const void needle, size_t needlelen) 找到一个子串。
string.h void memmove(void dest, const void src, size_t n) 内存移动。
string.h void mempcpy(void dest, const void src, size_t n) 拷贝内存区域。
string.h void memset(void s, int c, size_t n) 内存初始化。
stdlib.h void malloc(size_t size) 申请内存。
stdlib.h void calloc(size_t nmemb, size_t size) 申请内存并清零。
stdlib.h void realloc(void ptr, size_t size) 重分配内存。
stdlib.h/malloc. void valloc(size_t size) 分配以页对齐的内存。
stdlib.h void free(void ptr) 释放内存。
malloc.h size_t malloc_usable_size(void ptr) 获取从堆分配的内存块的大小。
unistd.h int getpagesize(void) 获取页面大小。
unistd.h void sbrk(intptr_t increment) 更改数据段大小。

差异接口详细说明:

  • mmap

函数原型:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

函数功能:申请虚拟内存。

参数说明:

参数 描述
addr 用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),否则会降低程序的可移植性,因为不同系统的可用地址范围不一样。
length 内存段的大小。
prot 用于设置内存段的访问权限,有如下权限: - PROT_READ:允许读该内存段。 - PROT_WRITE:允许写该内存段。 - PROT_EXEC:允许执行该内存段。 - PROT_NONE:不能访问。
flags 控制程序对内存段的改变所造成的影响,有如下属性: - MAP_PRIVATE:内存段私有,对它的修改值仅对本进程有效。 - MAP_SHARED:把对该内存段的修改保存到磁盘文件中。
fd 打开的文件描述符。
offset 用以改变经共享内存段访问的文件中数据的起始偏移值。

内存 - 图1 说明: mmap与Linux实现差异详见与Linux标准库的差异章节。

返回值:

  • 成功返回:虚拟内存地址,这地址是页对齐。
  • 失败返回:(void *)-1。

  • munmap接口

函数原型:

int munmap(void *addr, size_t length);

函数功能:释放虚拟内存。

参数说明:

参数 描述
addr 虚拟内存起始位置。
length 内存段的大小。

返回值:

  • 成功返回0。
  • 失败返回-1。

  • mprotect接口

函数原型:

int mprotect(void *addr, size_t length, int prot);

函数功能:修改内存段的访问权限。

参数说明:

参数 描述
addr 内存段起始地址,必须页对齐;访问权限异常,内核将直接抛异常,kill该进程,而不会产生SIGSEGV信号给当前进程。
length 内存段的大小。
prot 内存段的访问权限,有如下定义: - PROT_READ:允许读该内存段。 - PROT_WRITE:允许写该内存段。 - PROT_EXEC:允许执行该内存段。 - PROT_NONE:不能访问。

返回值:

  • 成功返回0。
  • 失败返回-1。

  • mremap接口

函数原型:

void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, void new_address);

函数功能:重新映射虚拟内存地址。

参数说明:

参数 描述
old_address 需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。
old_size 内存段的原始大小。
new_size 新内存段的大小。
flags 如果没有足够的空间在当前位置展开映射,则返回失败 - MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。 - MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,还必须指定MREMAP_MAYMOVE。

返回值:

  • 成功返回:重新映射后的虚拟内存地址。
  • 失败返回:((void *)-1)。