obrire 发表于 2006-04-12 11:55

快速内存操作技术

我们总希望能在内核空间和用户空间自由交换数据,传统的方式是采用内核提供的vma机制,通过copy_to/from_user之类的方法来实现。这对于高速数据块传送是不可取的。
其实kswapd有时交换数据至外存时,性能相当差,一般而言,你的PC主存并不见得就用尽了,而且很多应用并是你所关心的,但却实实在在消耗你的计算资源,此时,你可能会想到采用实地址操作你的应用(尽管有MMU的支持),在uClinux中,当没有MMU时,工作起来是挺爽的。
最方便的,最高效的,无非是实地址下,操作物理内存,相当于DMA。尽管Linux 2.6内核在VMA方面的性能要优于2.4,但swap机制有一定的缺限。在VxWorks中,对内存的管理是很细致且精确的。如果你在Linux下申请大块内存操作时,当触发kswap快速交换回主存时,你会发现你的计算机
哪一段时间,几乎要休息几分钟,尽管你看起来free输出的頁面已经很多了,但此时的外存几乎一直忙着,且CPU负荷相当重,这时也可能你根本就没做任何操作。
有没有办法既在VMA机制下工作,又能直接处理主存数据呢?
回答是肯定的:
内核启动后,会将主存映射为/dev/mem,当我们在VMA中申请一块逻辑区间后,将转换的物理地址传与用户空间,用户空间就可以线性操作这段区间了,直接采用mmap就可以在物理主存中读写。
还有更快的方式吗?不采用mmap行吗?
当然有,当VMA将物理区块地址及大小传与用户空间后,用户完全可以采用地址读写模式,这几近于机器指令操作了。(可以独立于OS之外)
此种实现方式很简单,首先打开/dev/mem,直接定位至VMA传上来的地址就可以操作了,无需mmap。通知用户空间,可以采用procfs/sysfs等。
强烈建议:在边界控制上,一定要精确细致,不推荐初学者采用,一旦越界,可能引起“Kernel Panic”
更有可能就DOWN了。
对于此实现方式,建议参考mapper(LDD3)程序。
同时,也可以用mapper检查读写是否正确。

新的IA32中,PAGE_SIZE = 4K
            MAX_ORDER = 11
gfp最大申请4M线性逻辑空间,减去PAGE_OFFSET即可得到物理地址。
如果采用了HIMEM和NUMA,请参见Kernel关于内存映射的算法。
当主存达到1G或超过时,请减小用户空间大小。
随着硬件技术的发展,VMA在主存相当大时,可以考虑进行修正,完全可以集中采用物理映射方式。没必要交换了。否则,反而影响性能。
32位平台,如果主存2G,采用SWAP会使得性能有较大下降。
而在大容量数据传输时,也不可能采用SWAP方式的,不允许换出。
建议Linus在VMA中加入进程分类,不平类别的应用,分配不同的内存块。
小数据PAGE_SIZE = 4K/大数据4M/128M
地址模式全转换为64位,兼容32位,当应用于Embedded系统时,直接使用32位模式。
如将做成多个微系统,不同微核,运行不同应用(不同的进程管理,内存管理,文件管理),只是接口可以统一,不同标志而已。

guotie 发表于 2006-04-12 12:36

非常好!

xiaozhaoz 发表于 2006-04-13 09:40

个人觉得,根本不可行!

首先, 你提到的在vma存在的情况下, swap存在的情况下, 直接访问物理内存. 而且,看情况这块物理内存是用户空间分配的.
在mmu的CPU中, page frame映射到 page中, 不是固定的, 更确切的说, 一块物理页, 如果是用户空间分配的, 不是只给一个任务使用的, 因为swap处于运行中.别以为你直接访问物理内存, swap就不运行了, 你要用内核的分配物理页函数, 就可能触发kswap

直接访问page frame, 可能导致访问到的page frame存放的是已经被切换出去的任务的数据. 即使你非常注意访问的准确性.

再者,你这里说得所有东西都没考虑到, 用户任务分配好vma后, 物理地址根本是不确定的. 要不内核的lazy map机制就没用了.

最后, 内核现在的实现已经有非常好的扩展性, 可能是你了解不多. 根本不需要你说得这么多复杂的东西.
在嵌入式mmu CPU环境下,通过 mlock + 锁的技术,可以在内核和用户空间直接在有限的物理页上交换数据. 用户空间malloc几页物理内存, 然后在每页中写入一两个字符, 以完成内核的page frame 到page的映射, 然后用mlock()锁定这几页, 不然swap运行. 然后就可以用这几页来完成用户空间和内核的数据交互. 不过锁的实现都要考虑.

还有, 嵌入式环境没有磁盘, 一般需要将swap off, 就是设置内核的watermark level为0,这样kswap就不会将物理页交换. 直接调swapoff命令. 或者写/proc/sys/vm/swappiness

内核对vm分配也有限制, 所以用户空间malloc过大的空间,也可能不成功, 这时内核的 over commit功能.

albcamus 发表于 2006-04-13 09:55

原帖由 xiaozhaoz 于 2006-4-13 09:40 发表
个人觉得,根本不可行!

首先, 你提到的在vma存在的情况下, swap存在的情况下, 直接访问物理内存. 而且,看情况这块物理内存是用户空间分配的.
在mmu的CPU中, page frame映射到 page中, 不是固定的, 更确切的说, ...

正看的过瘾呢, 是不是还没打完字呀? :P

xiaozhaoz 发表于 2006-04-13 10:37

原帖由 albcamus 于 2006-4-13 09:55 发表


正看的过瘾呢, 是不是还没打完字呀? :P

没了:D, 就这些东西, 对内存这块不怎么懂, 不敢乱说.

不过将vm分成 3G/IG, 2G/2G, 1G/3G的选项已经合入最新的内核2.6.17-RC1, 正在看实现.

讨论在:
http://groups.google.com/group/linux.kernel/browse_thread/thread/6eb0e7bfeba04f5a/f99732a73435db13?lnk=st&q=2G+split+group%3Alinux.kernel&rnum=2#f99732a73435db13

思一克 发表于 2006-04-13 11:15

争论的很激烈吗

obrire 发表于 2006-04-13 23:07

回复 5楼 xiaozhaoz 的帖子

首先,在普通的PAGE_SIZE情况下,如4K不是4M,能得到的order最大为11,其实一般是<11
也就是取10,源码中有定义,只能用到4M Logical Memory,也就是只能得到4M线性物理地址.
而在uClinux中,虽然没有kswapd,但当你的应用free或destroy时,内核并不能如你所想,全
然释放.
至于上有人提到内存分配问题,这是在Module中分配的.不会有在初始化时加入mem=xxM的限制
这些内存在module unload时,可以回归内核管理.
至于用户空间所采用的malloc,其实只是让内核知道这段内存的申请是合法的,最后还是通过page
来实现的.
当然,如果纯64位平台,可以采用4M的PAGE_SIZE
如果定义MAX_ORDER <= 1024, 可以使用4G的Memory.
以前有Intel的朋友试着做过这些分配,或有人在2.6.14以后加入relayfs,其实这都不可能保证性线.

如果我们采用Multi Micro Kernel, 就有点像IBM的虚拟机了,可以同时运行多种OS,多种管理模式,
不过管理调度是相当复杂的, AIX中有加入对SMP和多种微环境支持.

VMware中有一定的实现功能, 性能也还可以,但在要求苛刻的应用下,如同步数传系统中,当前的内核
就不足以应对了. 2.6的VMA制式,在通常用户计算环境中,性能是出色,好像在2004年Moto中有人做
个这种测试,有机会传上来看看.

如果有两枚,或非SMP(3-5枚)CPU,有可能我要求一段内存完成100M的线性DMA转发数据,<1ms的
时延,这时可安排其中一枚来做这件事,这是可行的,有时更不需要1ms,只是数据后处理要求时间稍长.

非对称模式,或称混合网络计算模式,单主机也可以实现. 以前有些SuperComputer采用背板高速串行
数据交换,可以有首效隔离,采用BLADE单元计算,但这不能共享非空时段内的Memory资源.

如果没有负荷时,有些内存需要为主运算平台的诸如DB/WWW服务,可以通过一些机制来完成动态remap.

大家有兴趣研究一下SMP/及非对称多CPU共存计算环境.

CELL将很多核做进一个Chip, 但不如通过其它IO总线,扩展多路CPU,既可以每路CPU自带MEMORY和CACHE,
也可以动态向主OS动态申请,且加入是动态的,不需要主OS环境停机.

是不是很爽呀, 你突然发现图形处理不过来了,接上USB外置处理器,负荷转移置专用CPU上,一下快多了
不用时,unload就好了.主存自动回归原计算环境.真是CBL.

社会本就多态, 有什么花样, 就突破限制.
F.E.U
Future Extension Union

[ 本帖最后由 obrire 于 2006-4-13 23:24 编辑 ]

obrire 发表于 2006-04-13 23:29

原帖由 xiaozhaoz 于 2006-4-13 09:40 发表
个人觉得,根本不可行!

首先, 你提到的在vma存在的情况下, swap存在的情况下, 直接访问物理内存. 而且,看情况这块物理内存是用户空间分配的.
在mmu的CPU中, page frame映射到 page中, 不是固定的, 更确切的说, ...
在内核空间申请
在用户空间不用mmap
直接open /dev/mem
lseek xxxxx
一切就哪样简单,就像汇编,写进去就行了.
这可是直接物理内存操作呀.
其实在性能要求高的环境,不需要外存的.有些Super Computer就是这样的.
结果直接就通过网络送走了.

obrire 发表于 2006-04-13 23:39

回复 3楼 xiaozhaoz 的帖子

即便是MVista提供的核心中,也不见得保证VMA工作得很好.
内存一大,释放就可能变得很有效.当我用MPlayer static版时,退出时,好像内存并未很快释放.
如果还像MV采用spin_lock,就不用我写这部分了.在block操作时,只有memcpy,memset.

DMA操作时,如果映射都是10M以上的,怎么办?如果有硬时钟要求,每秒要提取序列,怎么实现???
目前有哪家的Linux能达到VMA全速实时?电信用户可不像IA产品.

即便是100Mbps的网卡,也不像10M同步信号要求那么高.

严重声明:
      采用这种方式, 是不需要在用户空间用malloc的(没有任何加锁时延及浪费),完全就是Register
   操作方式,直接置数.
    一般在procfs中读取时,如你用了系统的task_lock,这对要求不高的应用是可行的.
   至于在IA32中采用2G/2G/1G/3G,目前内核都没有问题.
   
当大容量内存在内核空间申请时,启用VMA,有时不见得成功,反而会触发系统自动将外存的数据换回主存.
这时系统几乎很少响应其它应用,且长时间调整(特别是换回在100M以上时).

至于细节,不便公开,望诸位见谅.以上只说明实现方式,是可行的.
有人问过Linus,但他只提及采用其它方式,或将用户空间缩小.所以我建议他们两个主创修改这部分实现.
反正他们自己也在争论.

尊重他们,体系可以不变,但可以变通的是方法.

如果大家对嵌入式哪么了解, 我可以推荐.

[ 本帖最后由 obrire 于 2006-4-13 23:56 编辑 ]

guotie 发表于 2006-04-14 00:32

支持!

linux还是有很多可以改进德地方德,以前也遇到需要分配大于4M空间德情况,郁闷!
页: [1] 2 3 4 5 6
查看完整版本: 快速内存操作技术