linux vma,内存管理 – Linux内核API find_vma
find_vma函数功能描述:find_vma( )函数根据一个属于某个进程的虚拟地址,找到其所属的进程虚拟区间,并返回相应的vma_area_struct结构体指针。
find_vma文件包含
#include
find_vma函数定义
在内核源码中的位置:linux-3.19.3/mm/mmap.c
函数定义格式:
struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
find_vma输入参数说明
mm:是进程整个用户空间的抽象,也是总的控制结构,一个进程只有一个mm_struct结构,一个进程整个用户空间通常有若干离散的虚拟区间,这些虚拟区间由vm_area_struct结构描述。
addr:是进程用户空间中一虚拟地址,它属于某一虚拟区间。
find_vma返回参数说明
struct vm_area_struct是对进程虚拟区间抽象的数据结构,find_vma( )函数返回一个该结构类型指针,该指针指向描述进程中虚拟地址addr所在虚拟区间的结构体。
其中,struct mm_struct和struct vm_area_struct在文件linux-3.19.3/include/linux/mm_types.h中定义,它们的具体结构如下,这里对部分字段的含义进行了说明:
struct mm_struct {
struct vm_area_struct * mmap; /* 指向线性区对象的链表头 */
struct rb_root mm_rb;
u32 vmacache_seqnum; /*每一个线程的vmacache序列号*/
#if def CONFIG_MMU
/* 在进程地址空间忠搜索有效线性地址区间的方法 */
unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags);
#endif
/* 标识第一个分配的匿名线性区或文件内存映射的线性地址 */
unsigned long mmap_base;
unsigned long mmap_legacy_base;
unsigned long task_size;
unsigned long highest_vm_end;
/* 内核从这个地址开始搜索进程地址空间中线性地址的空闲区间 */
pgd_t * pgd; /*指向页全局目录 */
atomic_t mm_users; /* 次使用计数器 */
atomic_t mm_count; /* 主使用计数器*/
atomic_long_t nr_ptes; /*页表所在的页*/
int map_count; /* 线性区vma的个数 */
spinlock_t page_table_lock; /* 线性区的自旋锁和页表的自旋锁 */
struct rw_semaphore mmap_sem; /* 线性区的读/写信号量 */
struct list_head mmlist; /* 指向内存描述符链表中的相邻元素*/
unsigned long hiwater_rss;
unsigned long hiwater_vm;
/**total_vm指进程地址空间的大小(页数), locked_vm指“锁住”而不能换出的页的个数,
**shared_vm指共享文件内存映射中的页数,exec_vm指可执行内存映射中的页数*/
unsigned long total_vm, locked_vm, pinned_vm, shared_vm, exec_vm;
/*stack_vm指用户堆栈中的页数*/
unsigned long stack_vm, def_flags;
/*start_code指可执行的起始地址,end_code指可执行代码的最后地址,start_data
**指已初始化数据的起始地址,end_data指已初始化数据的最后地址*/
unsigned long start_code, end_code, start_data, end_data;
/*start_ brk指堆的起始地址,brk指堆的当前最后地址,start_ stack指用户态堆栈的起始地址*/
unsigned long start_brk, brk, start_stack;
/* arg_start指命令行参数起始地址,arg_end指命令行参数的最后地址,
**env_start指环境变量的起始地址,env_end指环境变量的最后地址*/
unsigned long arg_start, arg_end, env_start, env_end;
……
……
};
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; /* 用于红黑树的数据*/
unsigned long rb_subtree_gap;
struct mm_struct * vm_mm; /*指向线性区所在的内存描述符 */
pgprot_t vm_page_prot; /* 线性区中页框的访问许可权 */
unsigned long vm_flags; /* 线性区的标志*/
……
……
struct list_head anon_vma_node; /* 指向匿名线性区链表的指针 */
struct anon_vma * anon_vma; /* 指向anon_vma数据结构的指针 */
const struct vm_operations_struct * vm_ops; /* 指向线性区的方法 */
unsigned long vm_pgoff; /*在映射文件中的偏移量,对于匿名页,它等于0或vm_start/PAGE_SIZE*/
struct file * vm_file; /* 指向映射文件的文件对象 */
void * vm_private_data; /* 指向内存区的私有数据 */
……
……
};
find_vma实例解析
编写测试文件:find_vma.c
头文件及全局变量声明如下:
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
static int __init find_vma_init(void);
static void __exit find_vma_exit(void);
模块初始化函数:
int __init find_vma_init(void)
{
struct mm_struct *mm ;
unsigned long addr ;
struct vm_area_struct * vma ;
mm = current->mm; //mm指向当前进程
addr = mm->mmap->vm_next->vm_start + 1;
printk("addr = 0x%lx\n", addr);
vma = find_vma(mm, addr);
if(vma ! = NULL )
{
/*输出所查找的虚拟区间的起始地址*/
printk("vma->vm_start = 0x%lx\n", vma->vm_start);
/*输出所查找虚拟区间的结束地址*/
printk("vma->vm_end = 0x%lx\n", vma->vm_end);
}
else
printk("UNLUCK! You have failed! \n");
return 0;
}
模块退出函数:
void __exit find_vma_exit(void)
{
printk("exit! \n");
}
模块初始化及退出函数调用:
module_init(find_vma_init);
module_exit(find_vma_exit);
实例运行结果及分析:
首先编译模块,执行命令insmod find_vma.ko插入模块,然后执行命令dmesg -c,会出现如图所示的结果。
结果分析:
““mm = current->mm; ”`获取当前进程用户空间。
令“ addr = mm->mmap->vm_next->vm_start + 1; ”此时addr即为用户空间中的某一虚拟地址,这里为当前进程第二个虚拟区间的起始地址加1,由输出结果可知addr = 0x7fb896ce6001。然后调用find_vma( )函数查询addr所在的虚拟区间,将描述该虚拟区间的结构体指针赋值给vma,最后通过输出vma的vm_start和vm_end值验证了查找成功。
linux vma,内存管理 – Linux内核API find_vma相关推荐
- linux drm 内存管理,linux DRM GEM 笔记
在GPU上的各种操做中涉及到多种.多个buffer的使用. 一般咱们GPU是经过图像API来调用的,例如OPENGL.vulkan等,因此GPU上buffer的使用,实际上就是在这些图像API中被使用 ...
- linux drm 内存管理,Linux RK3399 DRM 框架及代码流程 · Younix’s Studio
8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? RK3399 OS: Android 6.0 Kernel: 4.4 Version: v2017.04 DRM 简介 ...
- 全网独一无二值得收藏的,Linux的内存管理
Linux的内存管理 Linux的内存管理是一个非常复杂的过程,主要分成两个大的部分:内核的内存管理和进程虚拟内存.内核的内存管理是Linux内存管理的核心,所以我们先对内核的内存管理进行简介. 一. ...
- linux虚拟地址空间管理,Linux内存管理4---虚拟地址空间管理
1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本 ...
- Linux kernel内存管理之OOM相关参数
一.OOM概念 OOM是Out Of Memory(内存溢出)的缩写,虽然linux kernel的内存管理有很多机制(从cache中回收.swap out等)可以满足用户空间的各种虚拟内存需求,但是 ...
- Linux系统内存管理实验报告,Linux 内存管理 综合实验报告.pdf
Linux 内存管理 综合实验报告 计算机与通信学院 Linux 内存管理 综合实验报告 指导老师:孙建华 组员 :夏槟 20040810720 段翼真 20040810503 米晓亮 2004081 ...
- linux kernel内存管理之/proc/meminfo下参数介绍
一.前言 /proc/meminfo是了解Linux系统内存状态的主要接口,里面统计了当前系统各类内存的使用状况,需要注意的是:这是从内核的角度来统计.我们常用的free,vmstat等指令都是通过/ ...
- 转:浅谈Linux的内存管理机制
一 物理内存和虚拟内存 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概 ...
- 浅谈Linux的内存管理机制
一 物理内存和虚拟内存 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概 ...
最新文章
- VC INI文件读写 和 GetProfileString,WriteProfileString函数的使用
- SAP UI5 Require Busy dialog
- [转载]dynamic的小坑--RuntimeBinderException:“object”未包含“xxx”的定义
- LeetCode 881. 救生艇(贪心,双指针)
- 技术动态 | ACL 2019 知识图谱的全方位总结
- 不起眼的小动作可能葬送安全措施
- Win10中的IIS10安装php manager和IIS URL Rewrite
- 20 岁 Google vs 18 岁百度,分道扬镳?| 畅言
- 修改spring Boot启动时的默认图案Banner
- mysql自动跑sql发邮件_SQL server 表数据改变触发发送邮件的方法
- 计算机职称考试试题 操作题,2018职称计算机考试Excel备考试题及答案9-excel操作练习题...
- USBkey结合win7实现登陆验证
- 面试官:请实现单行文本居中,多行文本左对齐?
- Bluefish 1.1.3
- mysql show slave status 无记录_从show slave status 中判断mysql同步状态
- VMware宿主机与虚拟机之间的文件夹相互共享(看图操作)
- 分享一种Android端IM即时通讯智能心跳算法
- inode 耗尽故障处理办法
- 微信考勤签到 php,【投稿】微信签到打卡领积分源码,每日积分签到
- 云计算 第4章 云计算与移动互联网/物联网
热门文章
- 【转】WEB前端调优
- linux环境配置与使用合集
- ASP.NET生成WORD文档服务器部署注意事项
- TCP/UDP相关知识
- Android 设置定时刷新页面数据,最小自动刷新时间
- android studio 错误: 找不到符号 符号: 方法 xxx() 位置: 类 xxx
- Spring使用注解@Transactional事物手动回滚
- mysql实现decode_Oracle中的DECODE()函数,MySQL中怎么实现DECODE()函数
- Java中重载和复写的区别
- 微信小程序初始化 operateWXData:fail invalid scope