Linux内存管理 brk(),mmap()系统调用源码分析1:基础部分
Linux内存管理 brk(),mmap(),munmap()系统调用源码分析 基础部分
荣涛 2021年4月30日
- 内核版本:linux-5.10.13
- 注释版代码:https://github.com/Rtoax/linux-5.10.13
1. 用户态libc封装
1.1. brk
#include <unistd.h>int brk(void *addr);
void *sbrk(intptr_t increment);
1.2. mmap和munmap
#include <sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
int munmap(void *addr, size_t length);
1.2.1. prot取值
- PROT_EXEC Pages may be executed.
- PROT_READ Pages may be read.
- PROT_WRITE Pages may be written.
- PROT_NONE Pages may not be accessed.
1.2.2. flags取值
- MAP_SHARED:进程间共享,共享内存的一种
- MAP_PRIVATE:进程私有,当malloc一大块内存时,即为该选项
- MAP_32BIT: 映射到用户地址空间的前2G中;
- MAP_ANON
- MAP_ANONYMOUS:初始化为0的匿名映射
- MAP_DENYWRITE:忽略
- MAP_EXECUTABLE:忽略
- MAP_FILE:忽略
- MAP_FIXED:准确解释地址,如果addr和len指定的内存区域与任何现有映射的页面重叠,则现有映射的重叠部分将被丢弃
- MAP_GROWSDOWN:用于栈
- MAP_HUGETLB:大页内存,闻名于DPDK
- MAP_LOCKED:不会被swap出去
- MAP_NONBLOCK:仅与MAP_POPULATE结合使用才有意义,不执行预读:仅为RAM中已经存在的页面创建页表条目。 从Linux 2.6.23开始,此标志使MAP_POPULATE不执行任何操作。
- MAP_NORESERVE:不要为此映射提供swap空间
- MAP_POPULATE:填充页表以进行映射。 对于文件映射,这将导致文件上的预读。 pagefault不会阻止以后对映射的访问。 仅从Linux 2.6.23开始,专用映射才支持MAP_POPULATE。
- MAP_STACK:用于栈
- MAP_UNINITIALIZED:用于提高嵌入式设备的性能
需要注意的是,以上的选项很多,不用每个选项都清楚其原理和使用,就我来说,目前我是用过的只有MAP_SHARED
,MAP_PRIVATE
,MAP_HUGETLB
和MAP_LOCKED
这些常用的,剩下的我也没做过研究。
2. 内核中的入口点
2.1. brk
//mm\mmap.c
SYSCALL_DEFINE1(brk, unsigned long, brk);
2.2. mmap
//mm\mmap.c
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, pgoff);//arch\x86\kernel\sys_x86_64.c
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,unsigned long, prot, unsigned long, flags,unsigned long, fd, unsigned long, off);
2.3. munmap
//mm\mmap.c
SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len);
3. 内核调用栈
3.1. brk
SYSCALL_DEFINE1(brk, unsigned long, brk)check_data_rlimit()if (brk <= mm->brk)__do_munmap(...) -> 见 munmapfind_vmado_brk_flagsget_unmapped_areamunmap_vma_rangemay_expand_vmsecurity_vm_enough_memory_mmvma_mergevm_area_allocvma_set_anonymousvma_linkperf_event_mmapuserfaultfd_unmap_completeif (populate)mm_populate__mm_populate
3.2. mmap
SYSCALL_DEFINE6(mmap_pgoff, ...)
SYSCALL_DEFINE6(mmap,...)ksys_mmap_pgoffif (!(flags & MAP_ANONYMOUS))audit_mmap_fdfgetif (is_file_hugepages(file))else if (flags & MAP_HUGETLB)hstate_sizeloghugetlb_file_setupvm_mmap_pgoffsecurity_mmap_fileif (!ret)do_mmapuserfaultfd_unmap_completeif (populate)mm_populate -> 同 brk
3.3. munmap
SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)untagged_addrprofile_munmap__vm_munmap__do_munmaparch_unmapfind_vmaunmap_regionremove_vma_listuserfaultfd_unmap_complete
4. 相关内核数据结构
以下简化的三个数据结构承载了用户空间地址管理的任务,具体这三个数据结构的架构图
图片链接http://static.duartes.org/img/blogPosts/memoryDescriptorAndMemoryAreas.png
4.1. task_struct
struct task_struct {...struct mm_struct *mm;struct mm_struct *active_mm;...
};
4.2. mm_struct
struct mm_struct {...struct vm_area_struct *mmap;struct rb_root mm_rb;unsigned long start_code, end_code, start_data, end_data; /* brk() */unsigned long start_brk, brk, start_stack;...
};
4.3. vm_area_struct
struct vm_area_struct {...unsigned long vm_start;unsigned long vm_end;struct vm_area_struct *vm_next, *vm_prev;struct rb_node vm_rb;struct file * vm_file;pgd_t * pgd; //全局页目录...
};
在理解了VMA管理后,进行正式的源码分析,但是有必要先说一下进程地址空间的结构,这里我们就以32bit系统为例,64bit系统大同小异。
图片来源https://imgs.developpaper.com/imgs/4192938510-82183e6d4e7dc101_articlex.png
5. 相关链接
- https://www.cs.unc.edu/~porter/courses/cse506/f12/slides/address-spaces.pdf
- https://stackoverflow.com/questions/14943990/overlapping-pages-with-mmap-map-fixed
Linux内存管理 brk(),mmap()系统调用源码分析1:基础部分相关推荐
- Linux内存管理 brk(),mmap()系统调用源码分析2:brk()的内存释放流程
Linux brk(),mmap()系统调用源码分析 brk()的内存释放流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...
- 【Linux 内核 内存管理】mmap 系统调用源码分析 ④ ( do_mmap 函数执行流程 | do_mmap 函数源码 )
文章目录 一.do_mmap 函数执行流程 二.do_mmap 函数源码 调用 mmap 系统调用 , 先检查 " 偏移 " 是否是 " 内存页大小 " 的 & ...
- Linux brk(),mmap()系统调用源码分析3:brk()的内存申请流程
Linux brk(),mmap()系统调用源码分析 brk()的内存申请流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...
- 【Linux 内核】进程管理 ( 进程相关系统调用源码分析 | fork() 源码 | vfork() 源码 | clone() 源码 | _do_fork() 源码 | do_fork() 源码 )
文章目录 一.fork 系统调用源码 二.vfork 系统调用源码 三.clone 系统调用源码 四._do_fork 函数源码 五.do_fork 函数源码 Linux 进程相关 " 系统 ...
- 【C++内存管理】loki::allocator 源码分析
loki 是书籍 <Modern C++ Design>配套发行的一个 C++ 代码库,里面对模板的使用发挥到了极致,对设计模式进行了代码实现.这里是 loki 库的源码. ps. 有空是 ...
- (转)Linux设备驱动之HID驱动 源码分析
//Linux设备驱动之HID驱动 源码分析 http://blog.chinaunix.net/uid-20543183-id-1930836.html HID是Human Interface De ...
- 分页池内存持续增长_鸿蒙内核源码分析(从进程/线程视角看内存)
这篇文章说说内存,内存的管理是极其复杂的模块,涉及到非常多概念,光地址就有逻辑,线性,物理地址三个,网上文章很多,参差不齐,没有很好基础或实战经验的同学基本得懵掉,本篇最后也有这些概念介绍.系列篇打算 ...
- 掌握鸿蒙轻内核静态内存的使用,从源码分析开始
摘要:静态内存实质上是一个静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更.静态内存池由一个控制块和若干相同大小的内存块构成.控制块位于内存池头部,用于内存块管理.内存块的申请和释 ...
- Linux线程同步(三)---互斥锁源码分析
先给自己打个广告,本人的微信公众号:嵌入式Linux江湖,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题. 一 源码分析 1.li ...
最新文章
- 2018python培训-Python学习之路—2018/7/2
- 【ASP.NET开发】ASP.NET(MVC)三层架构知识的学习总结
- 一道异常处理执行顺序面试题的简单分析
- setTimeout and jquery
- QML模块定义qmldir文件
- NumPy之:理解广播
- P3435-[POI2006]OKR-Periods of Words【KMP】
- 用友t3显示无法解析服务器名称,用友T3软件进入用友通提示不能解析端口,不能登录服务器...
- 力扣93. 复原 IP 地址(JavaScript)
- 2013 Multi-University Training Contest 4
- Perceptual:英特尔感知计算挑战赛 正式启动
- 【Mybatis】maven配置pom.xml时找不到依赖项(已解决)
- 【数据结构和算法笔记】:图的储存方式(邻接矩阵,邻接表)
- ffmpeg系列-解决ffmpeg获取aac音频文件duration不准
- xp的guest访问
- python黑帽子学习笔记(三)—— ssh隧道
- wsus微软补丁升级服务器不能下发,WSUS配置微软升级服务器操作.doc
- 模电课程设计_函数发生器
- 浅谈EV证书的作用及思考
- c语言求成绩标准差,C语言中求和、计算平均值、方差和标准差的实例
热门文章
- 关于Java List 的remove(index)方法
- Hanlp得到语义相似度的方法
- Python中数组,列表,元组的区别、定义、功能
- 【Codeforces Round #507 (Div. 2, based on Olympiad of Metropolises) B】Shashlik Cooking
- C++学习笔记(九)——引用
- Educational Codeforces Round 25 E. Minimal Labelshdu1258
- TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接
- 探求Floyd算法的动态规划本质
- 公益图书馆-学习笔记五-jquery来动态设置div高度
- 图片抓取_小小爬虫批量抓取微信推文里的图片