内存
基本概念
内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。
良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。
使用场景
针对用户态开发,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.h
|
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
|
内存段的大小。
|
返回值:
-
mprotect接口
函数原型:
int mprotect(void *addr, size_t length, int prot);
**函数功能:**修改内存段的访问权限。
参数说明:
参数
|
描述
|
addr
|
内存段起始地址,必须页对齐;访问权限异常,内核将直接抛异常并且kill该进程,而不会产生SIGSEGV信号给当前进程。
|
length
|
内存段的大小。
|
prot
|
内存段的访问权限,有如下定义:
- PROT_READ:允许读该内存段。
- PROT_WRITE:允许写该内存段。
- PROT_EXEC:允许执行该内存段。
- PROT_NONE:不能访问。
|
返回值:
-
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)。