免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: qq1158291633
打印 上一主题 下一主题

[内存管理] alloc_pages 申请的高端内存如何映射呢 [复制链接]

论坛徽章:
46
2015小元宵徽章
日期:2015-03-06 15:58:18羊年新春福章
日期:2015-04-14 10:37:422015年亚洲杯之阿曼
日期:2015-04-14 10:41:50NBA常规赛纪念章
日期:2015-05-04 22:32:03NBA季后赛大富翁
日期:2015-05-04 22:34:11菠菜明灯
日期:2015-05-04 22:35:49新奥尔良黄蜂
日期:2015-05-04 22:49:2315-16赛季CBA联赛之广夏
日期:2015-12-11 15:02:342015年亚洲杯之巴勒斯坦
日期:2015-03-04 19:56:562015年亚洲杯之阿联酋
日期:2015-03-04 11:19:04休斯顿火箭
日期:2015-03-02 16:32:11纽约尼克斯
日期:2015-03-02 16:09:04
11 [报告]
发表于 2014-08-05 17:56 |只看该作者
回复 10# humjb_1983
用vmalloc能保证他的需求吗?(需求:就是用固定大小的地址空间去访问任意大小的物理内存),我觉得不能吧

   

论坛徽章:
0
12 [报告]
发表于 2014-08-05 17:58 |只看该作者
回复 10# humjb_1983


    我需要的虚拟地址空间不多,4M足以,
    物理页面也是按照4M一个块来申请

  然后用这个4M的地址空间去映射不用的物理内存区域

  但是kmap一次只能映射一个页,这样的话 效率就太低下了,
  我需要的函数是一次性能将一定大小的虚拟地址空间和物理页映射起来的函数(1M,2M。。都行)

不知道linux下有没有可以直接使用的函数

要是非要自己去操作页表相关结构体,那就太麻烦了

论坛徽章:
0
13 [报告]
发表于 2014-08-05 17:59 |只看该作者
qq1158291633 发表于 2014-08-05 17:58
回复 10# humjb_1983


vmalloc不行的

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
14 [报告]
发表于 2014-08-05 18:25 |只看该作者
qq1158291633 发表于 2014-08-05 17:58
回复 10# humjb_1983

我的意思不是直接使用vmalloc,而是使用vmalloc区中的内存区,因为内核的虚拟地址空间已经划分完了
0-896M线性映射,896-1024M为vmalloc、kmap和固定映射区,已经没有空闲的虚拟地址空间给你用了
所以,如果你要将alloc_pages映射到内核的虚拟地址空间中的话,就只能利用现有的地址空间,0-896M
是线性映射区,显然你不能用,能用的恐怕就只有vmalloc区了,可以模仿ioremap(也是用的vmalloc区)
的实现:在vmalloc区中找到合适vm_struct区域后,进行映射(即修改页表)。

大概的思路应该为:
get_vm_area_node(找到合适的vm_struct区域) --> 手工将你之前alloc_pages分配而来的page赋给vm_struct->pages --> map_vm_area(或者直接手工修改页表)

具体可以参考vmalloc的实现,或者参考ioremap的实现。


论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
15 [报告]
发表于 2014-08-05 18:26 |只看该作者
super皮波 发表于 2014-08-05 17:56
回复 10# humjb_1983
用vmalloc能保证他的需求吗?(需求:就是用固定大小的地址空间去访问任意大小的物理 ...

不能直接用。。。

论坛徽章:
0
16 [报告]
发表于 2014-08-05 18:53 |只看该作者
humjb_1983 发表于 2014-08-05 18:25
我的意思不是直接使用vmalloc,而是使用vmalloc区中的内存区,因为内核的虚拟地址空间已经划分完了
0-89 ...


恩 我试试,如果linux kernel真是开始就将虚拟地址空间用完,那这种做法真是好奇葩啊

像windows下面这种使用时申请,感觉对程序员更加友好

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
17 [报告]
发表于 2014-08-05 19:10 |只看该作者
qq1158291633 发表于 2014-08-05 18:53
恩 我试试,如果linux kernel真是开始就将虚拟地址空间用完,那这种做法真是好奇葩啊

像windows下面 ...

或许这个也可以参考:
http://lwn.net/Articles/305919/

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
18 [报告]
发表于 2014-08-05 23:16 |只看该作者
本帖最后由 Tinnal 于 2014-08-06 00:28 编辑

回复 9# qq1158291633


我大概明白你的意思了。我描述一下,看看是不是你的场景。

你要MAP很大一块物理内存(远大于128M),因此vmalloc的想法肯定是不行了,因为没这么多虚拟地址。这一点你也明白,并且你也说了,window也没有这么多。你想要的是内核给你一段连续的虚拟地址,例如30M,然后你还想内核给你一个函数,每一次能让你map 30M物理内存到这段虚拟地址。究竟每次map哪50M,由你自己决定。

其实如果那个50M变成4K,就是你想要的效果。你只是嫌弃这样每次能用的只有4K,可能连最基本的业务都运行不起来,或者切太碎不好管理。

  
如果我的理解没有错,内核其实有对应的函数,只是模块不会这么用而已,内核自己已经这么用了。
具体的代码其实就是ioremap(如果需要cache,还有ioremap_fullcache), 这个函数你给他一段物理地址,它会给你map成连续的虚拟地址,直接用它在你这种场景不适合,因为1)每次都得iounmap再ioremap;2)每次ioremap有可能返回地地址不一样。

看上去不合适你用户,但打开这个函数实现后,你就会豁然开朗。

void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
{
        。。。。。省略一大堆安全判断 。。。。。。。。

         //下面是页表属性设定,抄就行了。唯一的改动也就是根据是否采用cache改改flags的值。
        prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY
                        | _PAGE_ACCESSED | flags);

        。。。省略对齐操作,这工作我知到你肯定会做的 。。。。。。。。

        //呵呵,下面的接口不就是你想要的一次申请一段虚拟工间的接口吗?乐死了吧!
        //不过get_vm_area接口没有导出,不能在模块里用,已导出的接口为alloc_vm_area。已经有内核模块在你这个接口了,可以放心使用。
        area = get_vm_area(size, VM_IOREMAP | (flags << 20));
        if (!area)
                return NULL;
        area->phys_addr = phys_addr;
        addr = (void __iomem *) area->addr;


        //下面的函数也没有导出,要不把它导出来用。
        //要不戏参照alloc_vm_area的另一个用户grant-table.c,使用已经导出的apply_to_page_range函数。
        if (ioremap_page_range((unsigned long) addr,
                        (unsigned long) addr + size, phys_addr, prot)) {
                vunmap((void __force *) addr);
                return NULL;
        }
        return (void __iomem *) (offset + (char __iomem *)addr);


总得来于有两套方案:
1. 参照ioremap, 把get_vm_area、ioremap_page_range都导出去,再实现你的算法。代码量少。
2. 参照grant-table.c, 使用已导出的alloc_vm_area、apply_to_page_range接口。代码量也不太,但apply_to_page_range有一个回调要注册。
3. 内核vmap的实现也能参考,呵呵。


Over,唉,又长又臭。我也臭了,洗操去。

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
19 [报告]
发表于 2014-08-05 23:25 |只看该作者
humjb_1983 发表于 2014-08-05 18:26
不能直接用。。。


还没洗,看到humjb_1983的回复,又去看了一眼,这个函数能达到操作很大的物理内存的目的,但每次只能操作4K也。说白了,就是kmap的封装而已。
qq1158291633之前好像嫌弃过这一点:
回复 6# super皮波


    是的 win下是有对应的api
linux下就找到一个kmap函数,但是一次只能映射一个物理页

论坛徽章:
9
辰龙
日期:2014-08-18 20:38:42未羊
日期:2014-09-04 08:50:45丑牛
日期:2014-09-06 00:12:55寅虎
日期:2014-12-22 20:50:56摩羯座
日期:2015-01-14 22:28:15巳蛇
日期:2015-01-23 20:39:272015年辞旧岁徽章
日期:2015-03-03 16:54:1515-16赛季CBA联赛之青岛
日期:2016-03-13 23:37:1915-16赛季CBA联赛之深圳
日期:2016-03-29 18:52:38
20 [报告]
发表于 2014-08-05 23:28 |只看该作者
qq1158291633 发表于 2014-08-05 18:53
恩 我试试,如果linux kernel真是开始就将虚拟地址空间用完,那这种做法真是好奇葩啊

像windows下面 ...


这不能算奇葩吧。不同的规划而已。而且768M这根线是可以调整的,在内核配置里有,make menuconfig就可以改了。我们公司也喜欢一大块一大块内存的vmalloc,因此我们有些产品也调低了这个值。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP