免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345下一页
最近访问板块 发新帖
查看: 22899 | 回复: 46
打印 上一主题 下一主题

一个cache相关的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-04 21:47 |只看该作者 |倒序浏览
这周碰到的一个问题,在解决的过程中得到不少高手的热心帮助,把一些总结贴出来,欢迎大家指点。

写一个屏驱动的时候,需要把一块内核中用kmalloc分配的内存映射到应用层中使用。这是一个很simple的需求,很轻松的就可以通过mmap搞定:

驱动部分代码:
1698         if((mmap_addr = kmalloc(PAGE_SIZE, GFP_KERNEL)) == NULL){
1699                 ret = -ENOMEM;
1700                 goto out;
1701         }
1702         SetPageReserved(virt_to_page((mmap_addr)));

....

899         long length = vma->vm_end - vma->vm_start;
900
901         if (length > PAGE_SIZE)
902                 return -EIO;
903
904         if ((ret = remap_pfn_range(vma,vma->vm_start,virt_to_phys((void *)mmap_addr) >> PAGE_SHIFT,length,vma->vm_page_prot)) < 0) {
905                 return ret;

....


应用层通过
401         if( ( addr = mmap(NULL, 4096, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0 )) == (void *)-1)
402         {
403                 perror("mmap error\n");
404                 return -1;
405         }
获得地址, 然后往内写入

这是一种通过普通内存设为保留,当成io内存映射并map出去的一种方式。经过测试,发现大部分时候数据是对的,但偶尔数据会出错。随后尝试不采用remap_pfn_range建立页表,而是通过缺页时返回分配页的动态方式来处理,结果仍然一样。

我们猜测是由于cache的原因导致的,于是在mmap的时候使其nocache,仍然无法解决。在实在没有办法的情况下,我们尝试采用在内核读取共享内存时执行flush_all_cache,果然,解决了问题,证明了确实是cache导致的。

那么为什么一开始我们种种尝试未能成功呢?因为我们弄反了方向。我们以为是应用层在读cache,内核读内存,实际上,由于采用remap_pfn_range,或者我们在mmap的时候指定了nocache的方式,应用层读取这片vma的时候是根据其指定的nocache属性去读内存,而内核访问kmalloc的时候却是读内存。如何让内核也读内存呢,很简单,通过ioremap_nocache把kmalloc得到的地址再做一次映射,然后给内核用就可以了。

这就是传说中的Cache Coherence ---缓存一致性。由于cache和内存在某些时候的不一致而导致的不同地址空间分别读写导致的问题。并不是所有体系结构都存在这种问题,比如x86.我曾经在x86上用过mmap并且使用良好,因为x86的体系结构确保了缓存一致性:其总线监听技术使当某片被cache的内存被其他请求操作时,会被立刻回写,确保cache与内存的一致性。但这种监听技术会带来性能上的损耗,所以arm是由软件来确保这个一致性的:一些时候,比如进程切换,必须通过flush整个cache获得正确的内存访问。

在这里例子里,我们是通过内核和应用都nocache的方式来进行内存共享的。那么双方能不能通过cache的方式来访问呢?我们必须知道,有两种cache:物理cache和逻辑cache,对于armv6以下的arm芯片,采用的是逻辑cache的方式,即cache在mmu之前,而armv6及以上的cpu,cache在mmu之后,cpu送出的要访问的地址先通过mmu进行虚拟/物理的转换,再送到cache。这意味着什么呢?意味着对于我们的cpu(v5),当应用层用其地址空间的地址把共享区从内存加到cache后,内核同样访问这片区域的时候,也可以按照其kmalloc分配的地址将同一片内存中的数据加载到cache的另一行中,这就意味着一个内存块会有2个cache拷贝,也就是传说中的别名。简单地说,如果你用arm11,由于使用物理cache,所以不会有问题,而arm9的话,就很麻烦了。

那为什么有时候访问正确,有时候访问错误呢?这就和cache的替换策略有关了。不像x86由于总线监视的原因,可以在相关内存被touch的时候回写,arm的cache只有当是dirty,并且被cache轮转策略选中需要换出的时候,才会被回写。所以有时候,某些加载共享内存的cache块没有被替换,而相应的内存块又被内核加载到cache形成别名,错误就自然产生了。

这就是cache导致的问题。如果双方采用一样的cache策略,自然cache就是透明的,但是如果是不一样的方式,那么可能就会有问题。具体会有哪些问题,如前所述,就和cpu,体系结构有着密切的关系了。

论坛徽章:
0
2 [报告]
发表于 2010-11-04 22:23 |只看该作者
本帖最后由 sep 于 2010-11-04 22:24 编辑

受教了。“我们以为是应用层在读cache,内核读内存”,开始我也这样以为的,本来还对snail同学存在一些疑问。嵌入式版块里一个tx的问题估计跟你的问题类似。

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
3 [报告]
发表于 2010-11-04 22:26 |只看该作者
谢谢分享
王齐在 linux  powerpc详解 提到了物理cache 和虚拟cache一说.
是不是就是lz说的物理cache和逻辑cache?
也就是你说的不一致实际原因是.虚拟cache根本不从物理cache装载数据?而是直接从物理内存装载数据?

论坛徽章:
0
4 [报告]
发表于 2010-11-04 22:37 |只看该作者
受教了。“我们以为是应用层在读cache,内核读内存”,开始我也这样以为的,本来还对snail同学存在一些疑问 ...
sep 发表于 2010-11-04 22:23


是的 这个想法误导了我很长时间 。也是我sx了, 设nocache就是给vma设的 居然认为会影响到内核

论坛徽章:
0
5 [报告]
发表于 2010-11-04 22:52 |只看该作者
谢谢分享
王齐在 linux  powerpc详解 提到了物理cache 和虚拟cache一说.
是不是就是lz说的物理cache和逻辑 ...
smalloc 发表于 2010-11-04 22:26



应该就是那个逻辑和物理cache吧
虚拟,也就是逻辑cache不是虚拟的cache的意思 而是指在cache中用逻辑地址寻址  物理cache同样   也就是离cpu之间隔一个mmu  而逻辑cache隔开cpu和mmu

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
6 [报告]
发表于 2010-11-04 22:58 |只看该作者
回复 5# duanius


    恩.你看看这句是不是笔误
应用层读取这片vma的时候是根据其指定的nocache属性去读内存,而内核访问kmalloc的时候却是读内存
看了半天不理解

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
7 [报告]
发表于 2010-11-04 23:02 |只看该作者
还有你现在出问题的板子上2种cache同时实现了吗?同时作用?
我看你前面的描述感觉并不是同时实现,好象说有的只实现物理 有的只实现逻辑
如果2个都是物理的或者逻辑的,那么一开始就不会出问题了,是这意思?

论坛徽章:
0
8 [报告]
发表于 2010-11-04 23:25 |只看该作者
回复  duanius


    恩.你看看这句是不是笔误
应用层读取这片vma的时候是根据其指定的nocache属性去读 ...
smalloc 发表于 2010-11-04 22:58



    我们的需求是内核读  应用层读写  ,我可能描述的不准确吧,总之,应用层访问那块vma是根据prog flag指定的来做的 比如不cache,不用写缓冲之类
不过说读也可以  因为arm只有读分配cache,写一般不分配,除非命中

论坛徽章:
0
9 [报告]
发表于 2010-11-04 23:27 |只看该作者
还有你现在出问题的板子上2种cache同时实现了吗?同时作用?
我看你前面的描述感觉并不是同时实现,好象说有的 ...
smalloc 发表于 2010-11-04 23:02



不不  逻辑cache和物理cache只是一种cache的组织形式 没法同时存在
比如x86,arm11 用的是物理cache,而arm9用的是逻辑cache  只会有一种cache存在
对于arm11 只要同时cache或者同时nocache就可以了
而arm9,则必须只能同时nocache 原因就是我倒数第三段所说的别名的原因

论坛徽章:
7
丑牛
日期:2013-10-18 14:43:21技术图书徽章
日期:2013-11-03 09:58:03辰龙
日期:2014-01-15 22:57:50午马
日期:2014-09-15 07:04:39丑牛
日期:2014-10-16 14:25:222015年亚洲杯之伊朗
日期:2015-03-16 10:24:352015亚冠之城南
日期:2015-05-31 09:52:32
10 [报告]
发表于 2010-11-05 13:07 |只看该作者
回复 9# duanius


    我还有点疑问.可否告知下,前面说内核中读会出错,大概错了多少字节?
另一个就是这个内核读是什么发动的?在硬件中断中?软中断中?内核线程?还是本进程的某个系统调用?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP