Linux内核API find_vma_intersection

find_vma_intersection函数功能描述:find_vma_intersection( )函数的功能是查找获得给定的地址空间中所存在的某一进程的第一个虚拟区间,若没有该进程的虚拟区间,则返回NULL,否则,返回对该虚拟区间的结构体描述。

find_vma_intersection文件包含

#include<linux/mm.h>

find_vma_intersection函数定义

在内核源码中的位置:linux-3.19.3/include/linux/mm.h

函数定义格式:

static inline struct vm_area_struct * find_vma_intersection(struct mm_struct* mm, unsigned long start_addr, unsigned long end_addr)

find_vma_intersection输入参数说明

  • mm:是进程整个用户空间的抽象,也是总的控制结构,一个进程只有一个mm_struct结构,一个进程整个用户空间通常有若干离散的虚拟区间,这些虚拟区间由vm_area_struct结构描述(关于这两个结构体的详细说明参考find_vma( )函数的分析)。
  • star_addr:给定的地址空间的起始地址。
  • end_addr:给定的地址空间的结束地址。

find_vma_intersection返回参数说明

struct vm_area_struct是对进程虚拟区间抽象的数据结构,返回值为该结构类型的指针,它指向在地址空间start_addr和end_addr中进程mm的第一个虚拟区间。

find_vma_intersection实例解析

编写测试文件:find_vma_intersection.c

头文件及全局变量声明如下:

#include <linux/security.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
static int __init find_vma_intersection_init(void);
static void __exit find_vma_intersection_exit(void);

模块初始化函数:

int __init find_vma_intersection_init(void)
{
    struct mm_struct *mm ;
    unsigned long mm_start ;
    unsigned long start_addr ;
    unsigned long end_addr ;
    struct vm_area_struct * vma ;

    mm = current->mm;                      //mm指向当前进程的地址空间
    mm_start = mm->mmap->vm_start;       //mm_start为当前进程起始地址
    printk("mm_start = 0x%lx\n", mm_start);

    printk("In first situation:\n");
    start_addr = mm_start + 1;            //参数start_addr取起始地址+1
    end_addr = mm_start +10;              //参数end_addr取起始地址+10

    vma = find_vma_intersection(mm , start_addr , end_addr );

    if(vma ! = NULL)
        printk("vma->vm_start = 0x%lx\n", vma->vm_start); //输出所查找到的vma的起始地址
    else
        printk("There is no vma exists between start_addr and end_addr! \n");

    printk("In second situation:\n");
    start_addr = mm_start -10;           //参数start_addr取起始地址-10
    end_addr = mm_start -1;              //参数end_addr取起始地址-1

    vma = find_vma_intersection(mm, start_addr, end_addr);

    if(vma ! = NULL)
        printk("vma->vm_start = 0x%lx\n", vma->vm_start);
    else
        printk("There is no vma exists between start_addr and end_addr! \n");

    return 0;
}

模块退出函数:

void __exit find_vma_intersection_exit(void)
{
    printk("exit! \n");
}

模块初始化及退出函数调用:

module_init(find_vma_intersection_init);
module_exit(find_vma_intersection_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod find_vma_intersection.ko插入模块,然后执行命令dmesg -c,会出现如图所示的结果。

Linux内核API find_vma_intersection

结果分析:

“mm = current->mm; ”是获取当前进程用户空间。

“mm_ start = mm->mmap->vm_start; ”此时mm_start即为用户空间中的虚拟起始地址,由输出信息可知addr = 0x7fe2b8777000。接下来通过两种情况验证函数的功能:第一种情形是将当前进程的虚拟区间设定在地址空间start_addr和end_addr之内,则调用find_vma_intersection( )返回的vm_area_struct不为空,将会执行if中的语句“vma->vma_start =0x7fe2b8777000”;第二种情形是将当前进程的虚拟区间设定在地址空间start_addr和end_addr之外,则调用find_vma_intersection返回的vm_area_struct将为NULL,从而执行else中的语句“There is no vma exists between start_addr and end_addr! ”

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程