get_free_page

如果模块需要分配大块的内存,使用面向页的分配会有很多优点;

分配页面可使用下面的函数:

 unsigned long get_zeroed_page(gfp_t gfp_mask)

返回指向新页面的指针并将页面清零;

 unsigned long __get_free_page(gfp_t gfp)

返回指向新页面的指针,不清零页面;

 unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)

分配若干(物理连续的)页面,并返回指向该内存区域第一个字节的指针,不清零页面;其中order是要分配的页面数以2为底的对数,例如,0表示一个页面,3表示8个页面;get_order函数使用一个整数参数,可根据宿主平台的大小返回order值,可允许的最大的order值是10或者11(对应于1024或者2048个页),这依赖于体系结构;

当程序不需要使用页面时,可以使用下面的函数之一来释放它们;

 void free_page(unsigned long addr)

 void free_pages(unsigned long addr, unsigned int order)

如果试图释放和先前分配数目不等的页面,内存映射关系就会被破坏,随后系统就会出错;

只要符合和kmalloc同样的规则,get_free_pages和其他函数都可以在任何时间调用;某些情况下函数会分配内存失败,特别是子啊使用了GFP_ATOMIC的时候,因此必须在分配出错时提供相应的处理;

尽管kmalloc(GFP_KERNEL)在没有空闲内存时有时会失败,但内核会尽可能满足这个内存分配请求;因此,分配太多的内存,系统响应性能就很容易下来;系统为满足kmalloc分配请求而试图换出尽可能多的内存页时,就会变慢;甚至无法为解决这个问题而生成新的进程;

基于页的分配策略的优点实际不在速度上,而在于更有效的使用内存;按页分配不会浪费内存空间,而kmalloc函数则会因分配力度的原因而浪费一定数量的内存;并且当分配的页面完全属于我们自己时,可以通过适当的调整页表把它们合并成一个线性区域,例如允许用户进程对这些单一互不相关的内存区域进行mmap;

alloc_pages

struct page是内核用来描述单个内存页的数据结构;内核在很多地方使用page结构,尤其是在需要高端内存(高端内存在内核空间没有对应不变的地址)的地方;

Linux页分配器的核心代码称为alloc_pages_node函数;

 struct page *alloc_pages_node(int nid, gfp_t gfp_mask,
unsigned int order)

这个函数具有两个变种,大多数情况下我们使用这两个宏;

 #define alloc_pages(gfp_mask, order)
#define alloc_page(gfp_mask)

alloc_pages_node要求传入三个参数,nid是NUMA节点的ID号,表示要在其中分配内存,mask是通常的GFP_分配标志,order是要分配的内存大小;该函数的返回值指向一个page结构(可能返回多个页)的指针,它描述了已分配的内存;或者而在失败时返回NULL;

alloc_pages通过在当前的NUMA节点上分配内存而简化了alloc_pages_node函数,它将numa_node_id的返回值nid参数而调用了alloc_pages_node函数,另外,alloc_page函数显然忽略了order参数而只分配单个页面;

为了释放通过上述途径分配的页面,我们应该使用下面的函数:

 #define __free_page(page) __free_pages((page), 0)
void __free_pages(struct page *page, unsigned int order)
void free_hot_cold_page(struct page *page, bool cold)

在知道某个页面的内容是否在处理器告诉缓存中时,则应该使用free_hot_cold_page来和内核通信,这个信息可以帮助内存分配器优化内存使用;

Linux设备驱动程序 之 get_free_page的更多相关文章

  1. Linux设备驱动程序学习之分配内存

    内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题. 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间. kmalloc 函数内幕 ...

  2. linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)

    原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是 ...

  3. 【转】linux设备驱动程序中的阻塞机制

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/04/2275272.html 阻塞与非阻塞是设备访问的两种方式.在写阻塞与非阻塞的驱动程序时,经 ...

  4. Linux设备驱动程序 第三版 读书笔记(一)

    Linux设备驱动程序 第三版 读书笔记(一) Bob Zhang 2017.08.25 编写基本的Hello World模块 #include <linux/init.h> #inclu ...

  5. 教你写Linux设备驱动程序:一个简短的教程

    教你写Linux设备驱动程序:一个简短的教程 http://blog.chinaunix.net/uid-20799298-id-99675.html

  6. linux设备驱动程序_hello word 模块编译各种问题集锦

    在看楼经典书籍<linux设备驱动程序>后,第一个程序就是编写一个hello word 模块. 原以为非常easy,真正弄起来,发现问题不少啊.前两天编过一次,因为没有记录,今天看的时候又 ...

  7. Linux设备驱动程序学习----1.设备驱动程序简介

    设备驱动程序简介 更多内容请参考Linux设备驱动程序学习----目录 1. 简介   Linux系统的优点是,系统内部实现细节对所有人都是公开的.Linux内核由大量复杂的代码组成,设备驱动程序可以 ...

  8. Linux设备驱动程序学习----2.内核模块与应用程序的对比

    内核模块与应用程序的对比 更多内容请参考Linux设备驱动程序学习----目录 1. 内核模块与应用程序的对比 内核模块和应用程序之间的不同之处: 大多数中小规模的应用程序是从头到尾执行单个任务,而模 ...

  9. Linux设备驱动程序学习----3.模块的编译和装载

    模块的编译和装载 更多内容请参考Linux设备驱动程序学习----目录 1. 设置测试系统 第1步,要先从kernel.org的镜像网站上获取一个主线内核,并安装到自己的系统中,因为学习驱动程序的编写 ...

随机推荐

  1. es6中Array.from()

    Array.from()方法就是将一个类数组对象或者可遍历对象转换成一个真正的数组. 那么什么是类数组对象呢?所谓类数组对象,最基本的要求就是具有length属性的对象. 1.将类数组对象转换为真正数 ...

  2. pycharm2017.3版本永久激活

    1.下载破解文件 链接:https://pan.baidu.com/s/1nwI278l 密码:j3gt 2.修改检测文件 ,在文件后缀是vmoptions的 文件中加入(注意是文件中,不是文件后缀上 ...

  3. linux命令返回值 / $?

    原文:http://blog.csdn.net/wyabc1986/article/details/7876673 在 Linux 下,不管你是启动一个桌面程序也好,还是在控制台下运行命令,所有的程序 ...

  4. Python更改pip源

    Python更改pip源 pip源有以下 新版ubuntu要求使用https源,要注意.清华:https://pypi.tuna.tsinghua.edu.cn/simple阿里云:http://mi ...

  5. k2系列-开发篇

    上一篇讲到K2安装的具体操作,本篇我们具体讲一下在VS环境下如何开发K2工作流. 常用工具控件说明: 节点关联线:流程各节点之间的关联线 客户端节点:流程的基本元素 服务器端节点:流程的完成标识节点 ...

  6. APP微信登录 服务器处理代码

    采用框架THINKPHP5 需要客户端传的参数有  udid openid nickname avatar_path /* * @param 第三方微信登录 * @param openid udid ...

  7. 注册表操作 Microsoft.Win32.Registry与RegistryKey类

    一.注册表操作简介 Registry 类,RegistryKey 类提供了操作注册表的接口 RegistryValueKind:用于指定操作注册表的数据类型 一.注册表巢 在注册表中,最上面的节点是注 ...

  8. 同一网断多套keepalived,vrid冲突问题排查

    注意: 同一网段中virtual_router_id的值不能重复,否则会出错,相关错误信息如下. Keepalived_vrrp[27120]: ip address associated with ...

  9. duilib学习领悟(2)

    再次强调,duilib只不过是一种思想! 在上一节中,我剖析了duilib中窗口类的注册,其中遗留两个小问题没有细说的? 第一个问题:过程函数中__WndProc()中有这么一小段代码: pThis ...

  10. XML 命名规范

    XML 元素必须遵循以下命名规则: 名称可以含字母.数字以及其他的字符 名称不能以数字或者标点符号开始 名称不能以字符 "xml"(或者 XML.Xml)开始 名称不能包含空格 可 ...