get-vm linux,内存管理 – Linux内核API __get_vm_area

__get_vm_area函数功能描述:__get_vm_area( )函数查找一块从start开始到end结束的线性地址,并从该地址块中创建size字节大小的内核虚拟区间。

__get_vm_area文件包含

#include

__get_vm_area函数定义

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

函数定义格式:

struct vm_struct *__get_vm_area(unsigned long size, unsigned long f lags, unsigned long start, unsigned long end)

__get_vm_area输入参数说明

size:是指要创建的内存虚拟区间的大小。

flags:是指非连续地址空间的映射方式。

start和end分别指要查找线性地址块的开始结束位置。

其中f lags可取值定义见文件linux-3.19.3/include/linux/vmalloc.h,如下:

#define VM_IOREMAP 0x00000001 //通过函数ioremap( )分配的页

#define VM_ALLOC 0x00000002 //通过vmalloc( )分配的页

#define VM_MAP 0x00000004 //通过vmap( )映射的已经分配的页

#define VM_USERMAP 0x00000008 //适用于remap_vmalloc_range( )分配的页

#define VM_VPAGES 0x00000010 //将被分配的缓冲区的页

#define VM_UNINITIALIZED 0x00000020 //vm_struct结构体变量没有被完全初始化

其中,vm_struct结构体是内核虚拟区间描述符,它在内核文件linux-3.19.3/include/linux/vmalloc.h中定义,这里对该结构体的部分字段进行说明:

struct vm_struct {

struct vm_struct *next; //下一个vm用来形成链表

void *addr; //虚拟地址

unsigned long size; //vm的大小

unsigned long flags; //vm的标志

struct page **pages; //vm所映射的page

unsigned int nr_pages; //page个数

phys_addr_t phys_addr; //对应的起始物理地址

const void *caller;

};

__get_vm_area返回参数说明

__get_vm_area( )函数返回一个指针,该指针指向所分配的内核虚拟区间的描述符,如果创建虚拟区间不成功,则返回NULL。

__get_vm_area实例解析

编写测试文件:__get_vm_area.c

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

#include

#include

#include

MODULE_LICENSE("GPL");

static int __init __get_vm_area_init(void);

static void __exit __get_vm_area_exit(void);

struct vm_struct *vm = NULL;

模块初始化函数:

int __init __get_vm_area_init(void)

{

vm = __get_vm_area(8192*4, VM_ALLOC, 0xC0000100, 0xdd000000);

if( ! vm )

{

return -ENOMEM;

}

else

{

printk("vm->size :%ld\n", vm->size); //输出内核线性区间大小

printk("vm->addr :0x%lx\n", (unsigned long)vm->addr); //输出起始地址

}

return 0;

}

模块退出函数:

void __exit __get_vm_area_exit(void)

{

if(vm)

{

free_vm_area(vm);

printk("free_vm_area ok! \n");

}

printk("exit ! \n");

}

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

module_init(__get_vm_area_init);

module_exit(__get_vm_area_exit);

实例运行结果及分析:

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

0b7d0bd2cd5ad558eb35a4aa0f6d680b.png

执行命令rmmod __get_vm_area.ko卸载模块,执行命令dmesg -c,会出现如图所示的结果。

a36900fca91b56bcf21c4f17e591f0b6.png

结果分析:

由传入__get_vm_area( )函数的实参可知,该实例创建一个8192*4大小的内核虚拟区间,该地址区间是按照VM_ALLOC映射方式在0xc0000100和0xdd000000之间的线性地址块中分配的。输出值36864是8192*4加上4096后得到的,在调用__get_vm_area( )分配内核虚拟地址时,内核都会在原本大小的基础上再加一个保护页给返回值vm_struct,所以会得到vm->size = 8192*4+ PAGE_SIZE(4096)。vm->addr即0xc000a100分配所得的区间第一块内存块的线性地址。最后在模块退出时调用free_vm_area( )函数用来释放由__get_vm_area( )函数创建的内核虚拟区间,参考该函数的分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值