Linux内核API get_unmapped_area

get_unmapped_area函数功能描述:get_unmapped_area( )函数的功能是在当前进程的用户空间中获得一个未映射区间的起始地址,即是搜查进程的地址空间以找到一个可以使用的线性地址空间。

get_unmapped_area文件包含

#include <linux/mm.h>

get_unmapped_area函数定义

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

函数定义格式:

unsigned long get_unmapped_area(struct f ile *f ile, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long f lags)

get_unmapped_area输入参数说明

  • file:表示要映射的文件,如果新的线性区间把一个文件映射到内存的话,则f ile为该文件的描述符指针。
  • addr:虚拟空间中的一个地址,表示从这个地址开始查找一个空闲的虚拟区。
  • len:要查找的线性区的长度。
  • pgoff:文件内的偏移量,因为并不是一下子全部映射一个文件,可能只是映射文件的一部分,pgoff就表示那部分的起始位置。
  • flags:这个参数指定虚拟区的其他标志,其常见取值及含义为:
    • MAP_SHARED和MAP_PRIVATE:前一个标志指定虚拟区中的页可以被许多进程共享,后一个标志作用相反。这两个标志都涉及vm_area_struct中的VM_SHARED标志。
    • MAP_ANONYMOUS:表示这个虚拟区是匿名的,与任何文件无关。
    • MAP_FIXED:这个区间的起始地址必须是由参数addr所指定的。
    • MAP_NORESERVE:函数不必预先检查空闲页面的数目。
    • MAP_GROWSDOWN:虚拟区可以向低地址扩展。
    • MAP_LOCKED:将映射区域锁定住,这表示该区域不会被置换(swap)。
    • MAP_DENYWRITE:虚拟区映射一个不能打开用于写的文件。
    • MAP_EXECUTABLE:虚拟区映射一个可执行文件。
    • MAP_POPULATE:函数应该为线性区建立的映射提前分配需要的页框。该标志仅对映射文件的线性区和IPC共享的线性区有意义。
    • MAP_NONBLOCK:只有在MAP_POPULATE标志置位时才有意义,提前分配页框时,函数肯定不阻塞。

get_unmapped_area返回参数说明

返回值是一个地址,如果查找所要求的区间成功,则返回该新区间的起始地址,否则返回错误码-ENOMEM,它表示内存不足。

get_unmapped_area实例解析

编写测试文件:get_unmapped_area.c

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

#include <linux/security.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int __init get_unmapped_area_init(void);
static void __exit get_unmapped_area_exit(void);

模块初始化函数:

int __init get_unmapped_area_init(void)
{
    unsigned long len ;
    unsigned long address ;         //定义一个长整型变量以接收所返回的地址值

    len = 1025;                     //假设所要查找的空闲空间的长度为1025个字节
    address = get_unmapped_area(NULL, 100, len, 0, MAP_ANONYMOUS);
                                    //为各参数赋值,调用该函数
    printk("find address = 0x%lx\n", address);
    return 0;
}

模块退出函数:

void __exit get_unmapped_area_exit(void)
{
    printk("exit ok! \n");      //退出
}

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

module_init(get_unmapped_area_init);
module_exit(get_unmapped_area_exit);

实例运行结果及分析:

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

Linux内核API get_unmapped_area

结果分析:

在该测试程序中,假设所映射的文件为空,即为匿名映射,则参数f ile为NULL,同样设置虚拟区的标志为MAP_ANONYMOUS。设置addr = 100和len = 1025字节,即从用户空间的地址100处开始查找长度为1025字节的空闲区,其中文件内偏移为0。调用get_unmapped_area( )函数后,由输出信息addr = 0x1000可知,所查找到空闲线性地址区间的起始地址为0x1000,也说明了查找成功。

注:如果查找成功,get_unmapped_area( )函数返回的地址应该总是页对齐的(地址0x1000即是页对齐),该函数的实现中会先检查所给的起始查找地址是不是有效的用户空间地址,并且是不是页边界对齐。

赞(1)
未经允许不得转载:极客笔记 » Linux内核API get_unmapped_area
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址