内存
基本概念
内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。
良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。
使用场景
针对用户态开发,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 | 用以改变经共享内存段访问的文件中数据的起始偏移值。 |
说明: 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)。
说明:
mmap与Linux实现差异详见