【Linux 内核 内存管理】munmap 系统调用源码分析 ② ( do_munmap 函数执行流程 | do_munmap 函数源码 )
munmap
系统调用函数 调用了 vm_munmap
函数 , 在 vm_munmap
函数 中 , 又调用了 do_munmap
函数 , do_munmap
函数 是 删除 内存映射 的 核心函数 ;
一、do_munmap 函数执行流程
do_munmap 函数执行流程 :
根据 unsigned long start
参数的起始地址 , 找到要删除的 第一个 虚拟内存区域 vm_area_struct 结构体实例 ,
int do_munmap(struct mm_struct *mm, unsigned long start, size_t len,
struct list_head *uf)
...
struct vm_area_struct *vma, *prev, *last;
...
/* Find the first overlapping VMA */
vma = find_vma(mm, start);
if (!vma)
return 0;
...
}
如果不是删除整个 vam 内存区域 , 而只是删除部分内存 , 那么需要分裂 vm_area_struct *vma
指向的内存区域 ;
error = __split_vma(mm, vma, start, 0);
根据 end
结束地址 , 找到 需要删除的 虚拟内存区域 的 最后一个 vm_area_struct *last
实例 ;
/* Does it split the last one? */
last = find_vma(mm, end);
如果不是删除整个 vam 内存区域 , 而只是删除部分内存 , 那么需要分裂 vm_area_struct *last
指向的内存区域 ;
if (last && end > last->vm_start) {
int error = __split_vma(mm, last, end, 1);
if (error)
return error;
}
如果 被删除的 内存区域 被锁定在 内存中 , 即 不允许换出到交换区 , 则调用 munlock_vma_pages_all
函数 解除 内存锁定 ;
/*
* unlock any mlock()ed ranges before detaching vmas
*/
if (mm->locked_vm) {
struct vm_area_struct *tmp = vma;
while (tmp && tmp->vm_start < end) {
if (tmp->vm_flags & VM_LOCKED) {
mm->locked_vm -= vma_pages(tmp);
munlock_vma_pages_all(tmp);
}
tmp = tmp->vm_next;
}
}
调用 detach_vmas_to_be_unmapped
函数 , 将要删除的 " 虚拟内存区域 " 从 进程的 虚拟内存区域 链表 和 红黑树 数据结构中删除 ,
这些内存区域 单独放在一个临时链表中 ;
/*
* Remove the vma's, and unmap the actual pages
*/
detach_vmas_to_be_unmapped(mm, vma, prev, end);
调用 unmap_region
函数 , 将 进程 的 页表中 的 " 被删除内存区域 对应的 映射 " 删除 , 从 处理器 页表缓存 中 也 删除对应 映射 ;
unmap_region(mm, vma, prev, start, end);
调用 arch_unmap
函数 , 执行 该处理器架构 对应的 删除内存映射 的 处理操作 ;
arch_unmap(mm, vma, start, end);
调用 remove_vma_list
函数 , 删除所有的虚拟内存区域 ;
/* Fix up all other VM information */
remove_vma_list(mm, vma);
二、do_munmap 函数源码
do_munmap
函数 , 定义在 Linux 内核源码 linux-4.12\mm\mmap.c#2620 位置 ;
do_munmap
函数源码如下 :
/* Munmap is split into 2 main parts -- this part which finds
* what needs doing, and the areas themselves, which do the
* work. This now handles partial unmappings.
* Jeremy Fitzhardinge <jeremy@goop.org>
*/
int do_munmap(struct mm_struct *mm, unsigned long start, size_t len,
struct list_head *uf)
{
unsigned long end;
struct vm_area_struct *vma, *prev, *last;
if ((offset_in_page(start)) || start > TASK_SIZE || len > TASK_SIZE-start)
return -EINVAL;
len = PAGE_ALIGN(len);
if (len == 0)
return -EINVAL;
/* Find the first overlapping VMA */
vma = find_vma(mm, start);
if (!vma)
return 0;
prev = vma->vm_prev;
/* we have start < vma->vm_end */
/* if it doesn't overlap, we have nothing.. */
end = start + len;
if (vma->vm_start >= end)
return 0;
if (uf) {
int error = userfaultfd_unmap_prep(vma, start, end, uf);
if (error)
return error;
}
源码路径 : linux-4.12\mm\mmap.c#2620
相关文章
- 图说Linux Deepin编年史
- 利用Volatility对Linux内存取证分析-常用命令翻译
- webmin下重启linux系统
- 【Linux基础】查看硬件信息-内存
- linux 普通用户切换成root免密码
- Linux cat查看文件,查找关键字(grep),统计(wc -l)
- Linux mmap原理
- Linux 磁盘分区工具fdisk和挂载
- Linux 0.11-透过 fork 来看进程的内存规划-28
- SpringBoot的端口配置server.port没办法设置成Linux的环境变量
- Atitit linux获取项目运行环境版本
- 手把手带你基于嵌入式Linux移植samba服务
- 【Linux 内核 内存管理】物理分配页 ② ( __alloc_pages_nodemask 函数参数分析 | __alloc_pages_nodemask 函数分配物理页流程 )
- 【Linux 内核 内存管理】物理内存组织结构 ⑥ ( 物理页 page 简介 | 物理页 page 与 MMU 内存管理单元 | 内存节点 pglist_data 与 物理页 page 联系 )
- 【Linux 内核 内存管理】munmap 系统调用源码分析 ① ( munmap 系统调用函数执行流程 | munmap 函数源码 | vm_munmap 函数源码 )
- 【Linux 内核 内存管理】内存映射相关数据结构 ③ ( vm_area_struct 结构体成员分析 | shared 成员 | anon_vma_chain 成员 | anon_vma 成员 )
- 【Linux 内核 内存管理】内存映射相关数据结构 ② ( vm_area_struct 结构体成员分析 | vm_mm 成员 | vm_page_prot 成员 | vm_flags 成员 )
- 【Linux 内核 内存管理】Linux 内核内存布局 ② ( x86_64 架构体系内存分布 | 查看 /proc/meminfo 文件 | /proc/meminfo 重要字段解析 )
- 【Linux 内核】Linux 内核体系架构 ( 进程调度 | 内存管理 | 中断管理 | 设备管理 | 文件系统 )
- 如何查看linux服务器内存使用情况
- Linux系统shell脚本之while循环实践1
- sar 找出系统瓶颈的利器 目前Linux上最为全面的系统性能分析工具之一 直接 sar -dur 1 30 即可看内存 CPU和IO占用
- linux 查看CPU、内存、磁盘信息命令
- 遇到问题之-linux系统安装后的一些内核调优
- MySQL手动安装Linux教程
- Linux 搞懂物理内存和虚拟内存
- Android/Linux之procrank查内存工具(九十九)