皮皮网

【主力跟随源码】【ultrapowa源码】【DDI源码】mmu源码

时间:2024-11-26 15:32:11 分类:休闲 来源:源码 自动跟庄

1.Ariane处理器源码剖析(五)续:MMU
2.MappedByteBuffer VS FileChannel 孰强孰弱?
3.linux内核$(kallsyms.o)详解续篇 --- 内核符号表的生成和查找过程
4.uclinux缺点

mmu源码

Ariane处理器源码剖析(五)续:MMU

       虚拟存储器概念

       在没有使用虚拟地址的系统中,处理器输出的地址直接送到物理存储器。而使用虚拟地址时,处理器输出的地址为虚拟地址,不会直接送到物理存储器,需要先进行地址转换。主力跟随源码负责转换的部件称为MMU。

       使用虚拟存储器不仅可以减少物理存储器容量需求,还有保护和共享等好处。虚拟地址通过页表(PT)映射到物理地址。页表存储虚拟地址到物理地址(***到PFN)的对应关系,表格大小取决于系统可用内存。页表结构不同于Cache,直接使用***寻址,无需Tag。

       访问虚拟地址时,可能需要两次物理内存访问:先访问页表获取物理地址,ultrapowa源码再使用物理地址访问内存。现实中,处理器使用TLB和Cache加速过程。多级页表减少页表占用空间,TLB负责快速查找。缺页(Page Fault)发生时,从下级存储取页并更新页表。

       操作系统使用页表控制每个页的访问权限,实现程序权限管理。写通(Write Through)方式在某些Cache间使用,写回(Write Back)类型Cache中,指令执行时仅更新D-Cache,物理内存更新可能延迟。

       TLB(Translation Lookaside Buffer)作为页表缓存,提高访问速度。现代处理器采用两级TLB,DDI源码容量和替换策略影响性能。TLB缺失可能由软件或硬件触发,随机替换算法适用于TLB。TLB写入确保页不被替换。控制TLB和Cache需管理进程ID等信息。

       虚拟Cache通过虚拟地址寻址,与物理Cache不同,仍需TLB加速访问。虚拟Cache引入同义和同名问题,通过进程ID解决。控制Cache包括写操作、寻址策略等。将TLB和Cache放入流水线优化性能,限制了Cache大小。使用Virtually-Indexed, Virtually-Tagged方式,虚拟Cache与物理Cache结合解决重名问题。六一源码

       MMU模块、TLB、虚拟内存系统、PTW等组件实现虚拟存储器功能。通过不同策略优化访问速度和内存使用。

MappedByteBuffer VS FileChannel 孰强孰弱?

        Java 在 JDK 1.4 引入了 ByteBuffer 等 NIO 相关的类,使得 Java 程序员可以抛弃基于 Stream ,从而使用基于 Block 的方式读写文件,另外,JDK 还引入了 IO 性能优化之王—— 零拷贝 sendFile 和 mmap。但他们的性能究竟怎么样? 和 RandomAccessFile 比起来,快多少? 什么情况下快?到底是 FileChannel 快还是 MappedByteBuffer å¿«......

        (零拷贝参考 Zero Copy I: User-Mode Perspective )

        天啊,问题太多了!!!!!!

        让我们慢慢分析。

        我们知道,Java 世界有很多 MQ:ActiveMQ,kafka,RocketMQ,去哪儿 MQ,而他们则是 Java 世界使用 NIO 零拷贝的大户。

        然而,他们的性能却大相同,抛开其他的因素,例如网络传输方式,数据结构设计,文件存储方式,我们仅仅讨论 Broker 端对文件的读写,看看他们有什么不同。

        下图是楼主查看源码总结的各个 MQ 使用的文件读写方式。

        那么,到底是 MMAP 强,还是 FileChannel 强?

        MMAP 众所周知,基于 OS 的 mmap 的内存映射技术,通过 MMU 映射文件,使随机读写文件和读写内存相似的速度。

        那 FileChannel 呢?是零拷贝吗?很遗憾,不是。FileChannel 快,只是因为他是基于 block 的。

        接下来,benchmark everything —— 徐妈.

        如何 Benchmark? Benchmark 哪些?

        既然是读写文件,自然就要看读写性能,这是最基本的。但,注意,通常 MQ 会使用定时刷盘,防止数据丢失,MMAP 和 FileChannel 都有 force 方法,用于将 pageCache 的数据刷到硬盘上。force 会影响性能吗? 答案是会。影响到什么程度呢? 不知道。每次写入的数据大小会影响性能吗,毫无疑问会,但规则是什么呢?FileOutputStream 真的一无是处吗?答案是不一定。

        一直以来,文件调优都是艺术,因为影响性能的因素太多,首先,SSD 的出现,已经让传统基于 B+ tree 的树形结构产生了自我疑问,第二,每个文件系统的性能不同,Linux ext3 和 ext4 性能天壤之别(删除文件的性能差距在 倍左右)。而 Max OS 的 HFS+ 系统被 Linus 称之为“有史以来最垃圾的文件系统”,幸运的是,苹果终于在 年推送了 macOS High Sierra 和 iOS .3 系统,这个两个系统都抛弃了 HFS+,换成了性能更高的 APFS。而每个文件系统又可以设置不同的调度算法,另外,还有虚拟内存缺页中断带来的性能毛刺.......

        (tips:良心的 RocketMQ 提供了 Linux IO 调优的脚本,这点做的不错 :)

        跑题了。

        楼主写了一个小项目,用于测试 Java MappedByteBuffer & FileChannel & RandomAccessFile & FileXXXputStream 的读写性能。大家也可以在自己的机器上跑跑看。

        CPU:intel i7 4æ ¸8线程 4.2GHz

        内存:GB DDR4

        磁盘:SSD 读写 2GB/s 左右

        JDK1.8

        OS:Mac OS ..6

        虚拟内存: 未关闭,大小 9GB

        测试注意点:

        1GB 文件:

        测试 MappedByteBuffer & FileChannel & RandomAccessFile & FileInputStream.

        从这张图里,我们看到,mmap 性能完胜,特别是在小数据量的情况下。其他的流,只有在4kb 的情况下,才开始反杀 mmap。因此,读 4kb 以下的数据,请使用 mmap。

        再放大看看 mmap 和 FileChannel 的比较:

        根据上图,我们看到,在写入数据包大于 4kb 以上的情况下,FileChannel 等一众非零拷贝,基本完胜 mmap,除了那个一次读 1G 文件的 BT 测试。

        因此,如果你的数据包大于 4kb,请使用 FileChannel。

        1GB 文件:

        测试 MappedByteBuffer & FileChannel & RandomAccessFile & FileInputStream.

        从上图,我们可以看出,mmap 性能还是一样的稳定。FileChannel 也不差,但是在 字节数据量的情况下,还差点意思。

        再看缩略图:

        我们看到,字节 是 FileChannel 和 mmap 性能的分水岭,从 字节开始,FileChannel 一路反杀,直到 BT 1GB 文件稍稍输了一丢丢。

        因此,我们建议:如果你的数据包大小在 字节以上,请使用 FileChannel 写入。

        我们知道,RocketMQ 使用异步刷盘,那么异步 force 对性能有没有影响呢?benchmark everything。我们使用异步线程,每 kb 刷盘一次,看看性能如何。

        mmap 一直落后,且性能很差,除了在 字节那里有一点点抖动,基本维持 在 左右,而没有 force 的情况下,则在 左右。而 FileChannel 则完全不受 force 的影响。在我的测试中,1GB 的文件,一次 force 需要 毫秒左右。buffer 越大,时间越多,反之则越小。

        说个题外话,Kafka 一直不建议使用 force,大概也有这个原因。当然,Kafka 还有自己的多副本策略保证数据安全。

        这里,我们得出结论,如果你需要经常执行 force,即使是异步的,也请一定不要使用 mmap,请使用 FileChannel。

        基于以上测试,我们得出一张图表:

        假设,我们的系统的数据包在 - 左右,我们应该使用什么策略?

        答:读使用 mmap,仅仅写使用 FileChannel。

        再回过头看看 MQ 的实现者们,似乎只有 QMQ 是 这么做的。当然,RocketMQ 也提供了 FileChannel 的写选项。但默认 mmap 写加异步刷盘,应该是 broker busy 的元凶吧。

        而 Kafka,因为默认不 force,也是使用 FileChannel 进行写入的,为什么使用 FileChannel 读呢?大概是因为消息的大小在 4kb 以上吧。

        这样一揣测,这些 MQ 的设计似乎都非常合理。

        最后,能不用 force 就别用 force。如果要用 force ,就请使用 FileChannel。

linux内核$(kallsyms.o)详解续篇 --- 内核符号表的生成和查找过程

       在内核中,维护着一张符号表,记录着内核中的所有符号,包括函数与全局变量的地址与名称。这张表嵌入在内核镜像中,供内核运行时随时查找符号名。通过调用__print_symbol,内核代码能打印出符号名。

       接下来,我们将详细解析内核符号表的生成与查找过程。

       系统映像文件与/proc/kallsyms的ams源码区别与联系

       系统映像文件(System.map)在编译内核时生成,记录了内核中的所有符号及其在内存中的虚拟地址。文件由scripts/mksysmap脚本生成,依赖于nm命令。系统映像文件的每条记录包括地址、符号类型与符号名。符号类型包括函数、全局变量等。

       而/proc/kallsyms文件是在内核启动后自动生成,位于/proc目录下,其代码实现于kernel/kallsyms.c。区别在于它包含了内核模块的符号列表,并且允许用户态访问,非内核常规操作。通常,我们只需关注_stext ~ _etext 和 _sinittext ~ _einittext之间的符号。

       内核符号表的生成与查找

       内核在运行过程中可能需要查找地址对应的函数名,如Oops或调试信息输出。但内核并未依赖System.map或/proc/kallsyms文件,而是通过vmlinux中的符号表(.tmp_vmlinux2.o)实现快速查找。

       内核符号表结构

       内嵌符号表通过scripts/kallsyms工具生成,源码位于kallsyms.c。该表包含6个全局变量:kallsyms_addresses、kallsyms_num_syms、kallsyms_names、kallsyms_token_table、kallsyms_token_index与kallsyms_markers。其中,kallsyms_addresses记录所有符号地址,kallsyms_num_syms统计符号数量,kallsyms_names存放符号名,kallsyms_token_table与kallsyms_token_index用于压缩存储高频率字符串。

       压缩算法与优化

       内核使用压缩算法减少存储开销,将高频率字符串表示为token,并通过kallsyms_token_table与kallsyms_token_index实现压缩与解压。kallsyms_markers将符号每个分组,加速查找过程。

       查找过程实例与源码分析

       举例说明查找地址0xc对应的符号名。首先在System.map中定位到该地址位于__create_page_tables与__enable_mmu之间。在.tmp_kallsyms2.S文件中,利用二分查找定位符号地址,然后通过kallsyms_names与kallsyms_markers加速查找过程。最后解析压缩的符号名,得到结果为__enable_mmu。

       内核模块符号查找

       内核模块在启动时动态加载,其符号表存储在struct module结构中,所有已加载模块的struct module结构构成全局链表。查找内核模块中的符号时,调用kallsyms_lookup()函数,模块符号查找由get_ksymbol()函数完成。

uclinux缺点

       如同古训所述,“金无足赤,人无完人”,uClinux同样存在一些局限性:

       首先,它的文档资源有待完善。相比Linux等开源项目,uClinux的文档体系显得组织混乱,缺乏系统性和一致性。热点技术的文档虽然丰富,但分类杂乱,而对于非热点部分,文档甚至可能存在真空状态,开发者往往需要深入源代码内部才能找到所需信息,这无疑增加了开发的难度。

       其次,由于uClinux与硬件平台紧密关联,商业平台通常能享受到更快的代码更新和Bug修复,使得开发过程顺畅。然而,对于那些非商业支持的平台,其内核和应用代码的维护则相对滞后,这可能导致在编译时遇到问题,特别是当增加新应用或更新运行库时,经常会出现编译错误。这无疑增加了开发者的工作负担,可能导致开发进度的延误。

       总之,尽管uClinux在嵌入式系统领域有着广泛应用,但其文档和硬件平台支持的差异性问题,无疑对开发者提出了更高的技术要求和挑战。

扩展资料

       uclinux表示micro-control linux.即“微控制器领域中的Linux系统”,是Lineo公司的主打产品,同时也是开放源码的嵌入式Linux的典范之作。uCLinux主要是针对目标处理器没有存储管理单元MMU(Memory Management Unit)的嵌入式系统而设计的。它已经被成功地移植到了很多平台上。由于没有MMU,其多任务的实现需要一定技巧。

copyright © 2016 powered by 皮皮网   sitemap