文章目录
- 一、mmap 创建内存映射 与 malloc 申请内存对比
- 1、malloc 函数原型
- 2、malloc 申请动态内存过程
- 3、malloc 使用的系统调用判定 ( brk | mmap )
- 4、mmap 创建内存映射
- 二、mmap 创建内存映射 与 普通文件操作 对比
一、mmap 创建内存映射 与 malloc 申请内存对比
1、malloc 函数原型
C 标准库 stdlib.h
中的 malloc
函数原型如下 :
#include <stdlib.h>
void *malloc(unsigned int size);
2、malloc 申请动态内存过程
使用 malloc
函数申请内存原理 : " 堆内存 " 动态分配 的 系统调用 过程 ;
① 用户应用程序调用 : 开发者 在 " 用户空间 “ 的 应用程序 中调用 malloc
等函数 , 申请 动态分配 ” 堆内存 " ,
glibc
库 的 " 内存分配器 " ptmalloc
, 负责调用 系统接口层 的 brk
sbrk
mmap
munmap
等系统调用 申请内存 ;
② 系统调用 : 用户空间 的 内存管理函数 调用 " 内核与用户层接口 “ 中的 brk
sbrk
mmap
munmap
等函数 , 这些函数就是 ” 系统调用 " 函数 ; 系统调用接口 是 用户层的 malloc
函数 与 内核层的 vmalloc
函数之间的 桥梁 ;
③ 内核层调用 : 内核与用户层接口 的 内存管理函数 调用 " Linux 内核 " 中的 kmalloc
vmalloc
函数 ;
参考 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 ) 博客 ;
3、malloc 使用的系统调用判定 ( brk | mmap )
内核层 使用 kmalloc
vmalloc
函数 申请 虚拟内存 , 之后将该 虚拟内存页 划分成 内存块 , 分配给 应用进程 , 默认的 内存块 划分阈值 是
KB ;
使用 brk
系统调用 : 如果 应用程序 申请的内存大小 小于 划分阈值 , glibc
库 的 ptmalloc
" 内存分配器 " 会使用 brk
系统调用 , 向 Linux 内核申请内存 ;
使用 mmap
系统调用 : 如果 应用程序 申请的内存大小 大于等于 划分阈值 , glibc
库 的 ptmalloc
" 内存分配器 " 会使用 mmap
系统调用 , 向 Linux 内核申请内存 ;
4、mmap 创建内存映射
mmap
可以直接向 Linux 内核申请 " 虚拟内存 " , 不需要经过 " 用户态 “ 与 ” 内核态 " 之间的转换 ;
二、mmap 创建内存映射 与 普通文件操作 对比
使用 mmap
系统调用 与 传统文件 操作 对比 :
传统的文件操作 , 首先调用 fopen
函数打开文件 , 然后调用 fread
fwrite
等函数操作文件 , 这些操作 在 用户模式 下调用 , 然后需要 切换到 内核模式 下调用 Linux 内核中相应的文件操作 , 这里 涉及到 用户模式 和 内核模式 之间的 切换 ;
使用 mmap
系统调用 , 避免了 用户模式 与 内核模式 切换的开销 , 提高了文件操作的性能 ;
此外 , 多个进程之间 , 可以使用 mmap
系统调用 创建 共享的 " 文件映射 “ 类型的 ” 内存映射 “ , 进而实现了 ” 共享内存操作 " ;