欢迎来到皮皮网网首页

【前端源码泄露】【systemctl源码】【战神源码】mmu源码分析

来源:安卓指南针源码 时间:2024-11-24 14:49:40

1.LINUX系统介绍
2.浅度剖析 SeaBIOS 基础组件之 PCI 枚举
3.如何学习嵌入式
4.Ariane处理器源码剖析(五)续:MMU
5.linux内核$(kallsyms.o)详解续篇 --- 内核符号表的码分生成和查找过程
6.MappedByteBuffer VS FileChannel 孰强孰弱?

mmu源码分析

LINUX系统介绍

       åµŒå…¥å¼Linux系统的设计与应用

       æ‘˜è¦ï¼šéšç€åµŒå…¥å¼Linux系统的迅速发展,嵌入式Linux已发展成为嵌入式操作系统的一个重要分支。本文介绍了嵌入式Linux的设计和几种流行的嵌入式Linux系统。

       å…³é”®è¯ï¼šåµŒå…¥å¼Linux

       ä¸€ã€å¼•è¨€

       åµŒå…¥å¼ç³»ç»Ÿ(Embedded Systems)是根据应用的要求,将操作系统和功能软件集成于计算机硬件系统之中,从而实现软件与硬件一体化的计算机系统。嵌入式系统出现于年代晚期,它最初被用于控制机电电话交换机,如今已被广泛的应用于工业制造、过程控制、通讯、仪器、仪表、汽车、船舶、航空、航天、军事装备、消费类产品等众多领域。嵌入式系统在数量上远远超过了各种通用计算机系统:计算机系统核心CPU,每年在全球范围内的产量大概在二十亿颗左右,其中超过%应用于各类专用性很强的嵌入式系统。

       ä¸€èˆ¬çš„说,凡是带有微处理器的专用软硬件系统都可以称为嵌入式系统。和通用的计算平台相比,嵌入式系统往往具有功能单一、体积小、功耗低、可靠性高、剪裁性好、软硬件集成度高、计算能力相对较低等特点。多年来,嵌入式设备中没有操作系统,其主要原因有二:首先,诸如洗衣机、微波炉、电冰箱这样的设备仅仅需要一道简单的控制程序,以管理数量有限的按钮和指示灯,没有使用操作系统的必要;其次,它往往只具有有限的硬件资源,不足以支持一个操作系统。

       ç„¶è€Œï¼Œéšç€ç¡¬ä»¶çš„发展,嵌入式系统变得越来越复杂,最初的控制程序中逐步的加入了许多功能,而这些功能中有很多可以由操作系统提供。于是,在年代末期出现了嵌入式操作系统(Embedded Operating Systems),它的出现大大简化了应用程序设计,并可以有效的保障软件质量和缩短开发周期。简单的ES一般并不使用操作系统,只包含一些控制流程,但是随着嵌入式操作系统在复杂性上的增长,简单的流程控制就不能满足系统的要求,这是就必须考虑使用操作系统做系统软件。因此,嵌入式操作系统就应运而生。

       éšç€EOS的广泛应用,业界已推出一些应用比较成功的EOS产品。归纳起来EOS应该具有以下几个特点:小巧、实时性、可装卸、固化代码、弱交互性、强稳定性和统一的接口。目前使用最多的EOS产品包括有:Vxwork、QNX、PalmOS、WindowsCE、pSOS、Hopen OS(国内凯思集团公司自主研制开发)等。其中,Vxwork使用最为广泛、市场占有率最高,其突出特点是实时性强(采用优先级抢占和轮转调度等机制),除此之外,其可靠性和可剪裁性也相当不错。QNX是一种伸缩性极佳的系统,其核心加上实时POSIX环境和一个完整的窗口系统还不到一兆。相比之下,Microsoft WinCE的核心体积庞大,实时性能也差强人意,但由于Windows系列友好的用户界面和为程序员所熟悉的API,并捆绑IE、Office等应用程序,正逐渐获得更大的市场份额。而与这些商业化的操作系统相比,Linux已经越来越受到人们的注意。

       äºŒã€åµŒå…¥å¼Linux概述

       Linux是一个成熟而稳定的网络操作系统。将Linux植入嵌入式设备具有众多的优点。首先,Linux的源代码是开放的,任何人都可以获取并修改,用之开发自己的产品。其次,Lirmx是可以定制的,其系统内核最小只有约kB。一个带有中文系统和图形用户界面的核心程序也可以做到不足1MB,并且同样稳定。另外,它和多数Unix系统兼容,应用程序的开发和移植相当容易。同时,由于具有良好的可移植性,人们已成功使Linux运行于数百种硬件平台之上。

       ç„¶è€Œï¼ŒLinux并非专门为实时性应用而设计,因此如果想在对实时性要求较高的嵌入式系统中运行Linux,就必须为之添加实时软件模块。这些模块运行的内核空间正是操作系统实现进程调度、中断处理和程序执行的部分,因此错误的代码可能会破坏操作系统,进而影响整个系统的可靠性和稳定性。Linux的众多优点还是使它在嵌入式领域获得了广泛的应用,并出现了数量可观的嵌入式Linux系统。其中有代表性的包括:uClinux、ETLinux、ThinLinux、LOAF等。ETLinux通常用于在小型工业计算机,尤其是PC/模块。ThinLinux面向专用的照相机服务器、X-控制器、MP3播放器和其它类似的嵌入式应用。LOAF是Linux On A Floppy的缩略语,它运行在平台上。

       ä¸‰ã€Linux作为嵌入式操作系统的优势

       Linux作为嵌入式操作系统的优势主要有以下几点:

       1、 可应用于多种硬件平台。Linux已经被移植到多种硬件平台,这对于经费,时间受限制的研究与开发项目是很有吸引力的。原型可以在标准平台上开发后移植到具体的硬件上,加快了软件与硬件的开发过程。Linux采用一个统一的框架对硬件进行管理,从一个硬件平台到另一个硬件平台的改动与上层应用无关。Linux可以随意地配置,不需要任何的许可证或商家的合作关系,源代码可以免费得到。这使得采用Linux作为操作系统不会遇到任何关于版权的纠纷。毫无疑问,这会节省大量的开发费用。本身内置网络支持,而目前嵌入式系统对网络支持要求越来越高。Linux的高度模块化使添加部件非常容易。

       2、 Linux是一个和Unix相似、以内核为基础的、具有完全的内存访问控制,支持大量硬件(包括X,Alpha、ARM和Motorola等现有的大部分芯片)等特性的一种通用操作系统。其程序源码全部公开,任何人可以修改并在GUN通用公共许可证(GNU General Public License)下发行。这样,开发人员可以对操作系统进行定制,适应其特殊需要。

       3、 Linux带有Unix用户熟悉的完善的开发工具,几乎所有的Unix系统的应用软件都已移植到了Linux上。Linux还提供了强大的网络功能,有多种可选择窗口管理器(X Windows)。其强大的语言编译器GCC,C++等也可以很容易得到,不但成熟完善,而且使用方便。

       å››ã€åµŒå…¥å¼Linux的建立

       å®Œæ•´çš„嵌入式Linux解决方案应包括嵌入式Linux操作系统内核、运行环境、图形化界面和应用软件等。由于嵌入式设备的特殊要求,嵌入式Linux解决方案中的内核、环境、GUI等都与标准Linux有很大不同,其主要挑战是如何在狭小的FLASH、ROM和内存中实现高质量的任务实时调度、图形化显示、网络通信等功能。

       1、 精简内核

       Linux内核有自己的结构体系,其中进程管理、内存管理和文件系统是其最基本的3个子系统。图1简单表示了它的框架。用户进程可直接通过系统调用或者函数库来访问内核资源。正因为Linux内核具有这样的结构,因此修改内核时必须注意各个子系统之间的协调。

       åµŒå…¥å¼Linux内核一般由标准Linux内核裁剪而来。用户可根据需求配置系统,剔除不需的服务功能、文件系统和设备驱动。经过裁剪、压缩后的系统内核一般只有k左右,十分适合嵌入式设备。同标准Linux不同的是嵌入式Linux必须要实现从FLASH或ROM的启动。标准Linux启动代码实现了系统初始化和从软盘、硬盘O盘区引导内核。嵌入式Linux一般保存在FLASH或ROM中,标准LILO无法引导。在支持直接从FLASH设备引导的系统中,如华恒公司的uClinux,引导程序主要完成对硬件系统的初始化工作和操作系统的解压、移位工作。在不支持直接从FLASH引导的系统中,FLASH设备只能作为非引导磁盘使用。此时,可采用先从硬盘或软盘加载一个小操作系统,如嵌入式DOS,然后再执行"Loadlin"加载程序从FLASH引导嵌入式Linux。

       å¯¹æ ‡å‡†Linux的修改主要是虚拟内存和调度程序部分的改动。因为标准Linux系统使用虚拟内存管理的目的是为了能同时运行多个进程,但是这样每个待运行的进程所能分配的CPU时间片就受限制,资源的使用效率就低。这样对于实时性要求较高的嵌入式系统来说,实时任务往往要求CPU具有很高的突发处理能力,即在有些时候需要极高的处理效率,因此需要屏蔽内核的虚拟内存管理机制。对于无硬盘设备的嵌入式系统,不必采用虚存管理。强实时需求的嵌入式应用可以通过修改任务调度模块实现,主要是在内核和设备驱动程序中加入了许多切换点。在该点处,系统检测是否存在未处理的紧急中断,有则剥夺内核的运行,及时处理中断。实现实时性服务的一个较好的方法是在标准的Linux内核上增加一个实时内核,标准Linux内核作为一个任务运行于实时内核上,强实时性任务也直接运行在实时内核上,如RT-Linux等。

       æ–‡ä»¶ç³»ç»Ÿæ˜¯åµŒå…¥å¼Linux操作系统必不可少的。但标准Linux支持大量的文件系统,因此除了满足系统的正常运行需要而保留一种外,其它的全部可以删除,利用原有的设置选项可以移除。一般嵌入式设备文件系统主要使用RamDisk技术和网络文件系统技术。RamDisk可驻留于Flash,运行时加载到内存中。

       2、 精简运行环境

       Linux通常的运行环境指用户运行任何应用的基础设施,主要包括函数库和基本命令集等。标准Linux系统同时向用户提供了静态和动态函数库。静态函数库在生成应用时直接链接到用户应用中。动态库在应用运行时才链接。由于嵌入式系统应用一般都是在开发平台上预先生成的,因此嵌入式系统只需向应用提供动态函数库。Linux应用运行所需的函数库主要有C库、数学库、线程库、加密库、网络通信库等。其中最基本的是C语言的运行库glib。这个库主要完成基本的输入输出,内存访问,文件处理。一个标准的glib库大约要kB存储空间,考虑到嵌入式Linux内核往往很小,这种运行库实在太大,我们做了一些精简的工作,方法有两种:(1)、使用静态连接的方法,完全不使用运行库动态连接;(2)、对这个库的函数进行精简。

       åœ¨ä¸€ä¸ªæ¡Œé¢ç³»ç»Ÿä¸Šï¼Œä½¿ç”¨åŠ¨æ€è¿žæŽ¥å¯ä»¥å¸¦æ¥è®¸å¤šå¥½å¤„。使用动态连接库,可以让应用程序跟函数库的更新、升级分离,便于维护,可以让同时运行的多个程序共享一段代码。但是,在嵌入式系统中,很少有多个程序并行的可能,程序的维护,尤其是库函数的维护更新是不常见的。这时,使用静态连接的优势就极为明显。因为静态连接可以只将库中用到的部分连接进程序。在应用程序较少(小于5)的情况下,静态连接可以达到较好的结果。为了便于将来扩充的需要,我们也采用第二种方法,针对我们的需要,对库函数的内容进行精简,只保留一些基本功能,还有一种方法是采用其它的C语言运行库。但是这些库对兼容性影响很大。

       åŸºæœ¬å‘½ä»¤é›†åŒæ ·æ˜¯è¿è¡Œç”¨æˆ·åº”用的基础,主要包括初始化进程init,终端获取getty、Shell和基本命令等。嵌入式系统的启动过程可能与标准Linux不同,例如跳过登录过程直接启动GUI等。这就要求修改init,getty等。标准Linux命令集同样由于体积问题无法直接应用于嵌入式环境。目前,小命令集的解决方法主要有集成方法和汇编方法两种。集成方法采用集成公共部分减少命令集整体体积,用C实现,有较好的平台移植性;汇编方法则采用汇编编程减少每个命令的体积.这样可使体积很小但其平台移植性较差。

       3、 嵌入式Linux下的GUI

       GUI在嵌入式系统或者实时系统中的地位越来越重要,比如PDA、DVD播放机、WAP手机等,都需要一个完整.漂亮的图形用户界面。这些系统对GUI的基本要求包括:(1)、轻型、占用资源少;(2)、高性能;(3)、高可靠性;(4)、可配置。这些也成为评价嵌入式系统的重要指标。目前,嵌入式Linux上的GUI主要有winCE、Micro Window、紧缩的X Window、MiniGUI(国内做得较好的自由软件之一)。标准Linux的Xfree由于体积庞大,运行环境要求高,无法运行于嵌入式环境。嵌入式GUI主要通过削减功能,降低性能来实现体积小和占用资源少。目前嵌入式Linux上的GUI环境主要有两类:X类和win类。Xç±»GUI分为服务方和客户方两方。服务器方提供鼠标、键盘处理和显示功能,客户方是用户应用,服务方和客户方通过socket接口和X协议通信。采用该方式十分有利于远程网络图形化服务,客户方和服务方可通过网络实现X协议和图形显示。典型的Xç±»GUI有Micro Window、紧缩的X Window等。win类的GUI不存在客户方和服务方,每个任务都自成一体,任何任务间的切换、事件分发由专门的管理任务负责。如wiCE、MiniGUI就是类似于win类的GUI。

       äº”、当前流行的几种嵌入式Linux系统

       é™¤äº†æ™ºèƒ½æ•°å­—终端领域以外,Linux在移动计算平台、智能工业控制、金融业终端系统,甚至军事领域都有着广泛的应用前景。这些Linux被统称为"嵌入式Linux"。

       1、RT-Linux

       è¿™æ˜¯ç”±ç¾Žå›½å¢¨è¥¿å“¥ç†å·¥å­¦é™¢å¼€å‘的嵌入式Linux操作系统。到目前为止,RT-Linux已经成功地应用于航天飞机的空间数据采集、科学仪器测控和电影特技图像处理等广泛领域。RT-Linux开发者并没有针对实时操作系统的特性而重写Linux的内核,因为这样做的工作量非常大,而且要保证兼容性也非常困难。为此,RT-Linux提出了精巧的内核,并把标准的Linux核心作为实时核心的一个进程,同用户的实时进程一起调度。这样对Linux内核的改动非常小,并且充分利用了Linux下现有的丰富的软件资源。

       2、uClinux

       uCLinux是Lineo公司的主打产品,同时也是开放源码的嵌入式Linux的典范之作。uCLinux主要是针对目标处理器没有存储管理单元MMU(Memory Management Unit) 的嵌入式系统而设计的。它已经被成功地移植到了很多平台上。由于没有MMU,其多任务的实现需要一定技巧。uCLinux是一种优秀的嵌入式Linux版本,是micro-Conrol-Linux的缩写。它秉承了标准Linux的优良特性,经过各方面的小型化改造,形成了一个高度优化的、代码紧凑的嵌入式Linux。虽然它的体积很小,却仍然保留了Linux的大多数的优点:稳定、良好的移植性、优秀的网络功能、对各种文件系统完备的支持和标准丰富的API。它专为嵌入式系统做了许多小型化的工作,目前已支持多款CPU。其编译后目标文件可控制在几百KB数量级,并已经被成功地移植到很多平台上。

       3、Embedix

       Embedix是由嵌入式Linux行业主要厂商之一Luneo推出的,是根据嵌入式应用系统的特点重新设计的Linux发行版本。Embedix提供了超过种的Linux系统服务,包括Web服务器等。系统需要最小8MB内存,3MB ROM或快速闪存。Embedix基于Linux 2.2内核,并已经成功地移植到了Intel x和PowerPC处理器系列上。像其它的Linux版本一样,Embedix可以免费获得。Luneo还发布了另一个重要的软件产品,它可以让在Windows CE上运行的程序能够在Embedix上运行。Luneo还将计划推出Embedix的开发调试工具包、基于图形界面的浏览器等。可以说,Embedix是一种完整的嵌入式Linux解决方案。

       4、Xlinux

       XLinux是由美国网虎公司推出,主要开发者是陈盈豪。他在加盟网虎几个月后便开发出了基于XLinux的、号称是世界上最小的嵌入式Linux系统,内核只有KB,而且还在不断减小。XLinux核心采用了"超字元集"专利技术,让Linux核心不仅可能与标准字符集相容,还含盖了1 2个国家和地区的字符集。因此,XLinux在推广Linux的国际应用方面有独特的优势。

       5、PoketLinux

       ç”±Agenda公司采用、作为其新产品"VR3PDA"的嵌入式Linux操作系统。它可以提供跨操作系统构造统一的、标准化的和开放的信息通信基础结构,在此结构上实现端到端方案的完整平台。PoketLinux资源框架开放,使普通的软件结构可以为所有用户提供一致的服务。PoketLinux平台使用户的视线从设备、平台和网络上移开,由此引发了信息技术新时代的产生。在PoketLinux中,称之为用户化信息交换(CIE),也就是提供和访问为每个用户需求而定制的"主题"信息的能力,而不管正在使用的设备是什么。

       6、MidoriLinux

       ç”±Transmeta公司推出的MidoriLinux操作系统代码开放,在GUN普通公共许可(GPL)下发布,可以在上立即获得。该公司有个名为"MidoriLinux计划"。"MidoriLinux"这个名字来源于日本的"绿色"---Midori,用来反映其Linux操作系统的环保外观。

       7、红旗嵌入式Linux

       ç”±åŒ—京中科院红旗软件公司推出的嵌入式Linux是国内做得较好的一款嵌入式操作系统。目前,中科院计算所自行开发的开放源码的嵌入式操作系统---Easy Embedded OS(EEOS)也已经开始进入实用阶段了。该款嵌入式操作系统重点支持p-Java。系统目标一方面是小型化,另一方面能重用Linux的驱动和其它模块。由于有中科院计算所的强大科研力量做后盾,EEOS有望发展成为功能完善、稳定、可靠的国产嵌入式操作系统平台。

       å…­ã€ç»“束语

       ç”±äºŽLinux是一个内核源代码开放、具备一整套工具链、有强大的网络支持及成本低廉的操作系统,因此嵌入式Linux自诞生起就秉承了这众多独特优势,这使它正在并越来越多地受到人们的关注。据Even Data数据显示,期望使用嵌入式Linux的用户从年的%增到年%,而同期Vxwork只是从%到%,Win CE从9%到%。另外,在嵌入式Linux的各种应用市场中,通信(语音和数据)名列第一,年的销售额是万美元,而年预计将达到1.亿美元,可以预见,嵌入式Linux将在未来的通信用嵌入式操作系统中占据强有力的地位

       Linux是目前十分火爆的操作系统。它是由芬兰赫尔辛基大学的一个大学生Linus B. Torvolds在年首次编写的。标志性图标是一个可爱的小企鹅。

       Linux是一种类Unix系统,Linus当时编写它的目的是为了替代一种名叫Minix的操作系统。Minix是由一个名叫Andrew Tannebaum的计算机教授编写的,当时由于Unix是一个商业软件,其源代码是不能拿来进行教学的,Andrew教授就自己编写了一个系统用于教学。最

       åˆçš„Minix用一张软盘就能装下,麻雀虽小、五脏俱全,Minix具有一般操作系统的特征,它同时兼容Unix系统。

       Linux是一个免费的操作系统,用户可以免费获得其源代码,并能够随意修改。它是在共用许可证GPL(General Public License)保护下的自由软件,也有好几种版本,如Red Hat Linux、Slackware,以及国内的Xteam Linux等。

       Linux具有许多Unix系统的功能和特点,能够兼容Unix,但无需支付Unix高额的费用。比如一个Unix程序员在单位可以在Unix系统上进行工作,回到家里在Linux系统上也能完成同样的工作,而不必重新购买Unix。要知道Unix的价格比常见的Windows要高出若干倍,和Linux的低廉更是相距甚远。

       Linux的应用也十分广泛。Sony最新的PS2游戏机就采用了Linux作为系统软件,使PS2摇身一变,成为了一台Linux工作站。著名的电影《泰坦尼克号》的数字技术合成工作就是利用多台Linux服务器来完成的。

       å¹´8月日,Linux发布了最新的Linux 2.4.9版,它也已经十岁了。

       Linux的优点

       Linux的流行是因为它具有许多诱人之处。

       1、完全免费

       Linux是一款免费的操作系统,用户可以通过网络或其他途径免费获得,并可以任意修改其源代码。这是其他的操作系统所做不到的。正是由于这一点,来自全世界的无数程序员参与了Linux的修改、编写工作,程序员可以根据自己的兴趣和灵感对其进行改变。这让Linux吸收了无数程序员的精华,不断壮大。

       2、完全兼容POSIX 1.0标准

       è¿™ä½¿å¾—可以在Linux下通过相应的模拟器运行常见的DOS、Windows的程序。这为用户从Windows转到Linux奠定了基础。许多用户在考虑使用Linux时,就想到以前在Windows下常见的程序是否能正常运行,这一点就消除了他们的疑虑。

       3、多用户、多任务

       Linux支持多用户,各个用户对于自己的文件设备有自己特殊的权利,保证了各用户之间互不影响。多任务则是现在电脑最主要的一个特点,Linux可以使多个程序同时并独立地运行。

       4、良好的界面

       Linux同时具有字符界面和图形界面。在字符界面用户可以通过键盘输入相应的指令来进行操作。它同时也提供了类似Windows图形界面的X-Windows系统,用户可以使用鼠标对其进行操作。在X-Windows环境中就和在Windows中相似,可以说是一个Linux版的Windows。

       5、丰富的网络功能

       äº’联网是在Unix的基础上繁荣起来的,Linux的网络功能当然不会逊色。它的网络功能和其内核紧密相连,在这方面Linux要优于其他操作系统。在Linux中,用户可以轻松实现网页浏览、文件传输、远程登陆等网络工作。并且可以作为服务器提供WWW、FTP、E-Mail等服务。

       6、可靠的安全、稳定性能

       Linux采取了许多安全技术措施,其中有对读、写进行权限控制、审计跟踪、核心授权等技术,这些都为安全提供了保障。Linux由于需要应用到网络服务器,这对稳定性也有比较高的要求,实际上Linux在这方面也十分出色。

       7、支持多种平台

       Linux可以运行在多种硬件平台上,如具有x、x0、SPARC、Alpha等处理器的平台。此外Linux还是一种嵌入式操作系统,可以运行在掌上电脑、机顶盒或游戏机上。年1月份发布的Linux 2.4版内核已经能够完全支持Intel 位芯片架构。同时Linux也支持多处理器技术。多个处理器同时工作,使系统性能大大提高。

       Linux的不足

       ç”±äºŽåœ¨çŽ°åœ¨çš„个人电脑操作系统行业中,微软的Windows系统仍然占有大部分的份额,绝大多数的软件公司都支持Windows。这使得Windows上的应用软件应有尽有,而其他的操作系统就要少一些。许多用户在换操作系统的时候都会考虑以前的软件能否继续使用,换了操作系统后是否会不方便。虽然Linux具有DOS、Windows模拟器,可以运行一些Windows程序,但Windows系统极其复杂,模拟器所模拟的运行环境不可能完全与真实的Windows环境一模一样,这就使得一些软件无法正常运行。

       è®¸å¤šç¡¬ä»¶è®¾å¤‡é¢å¯¹Linux的驱动程序也不足,不少硬件厂商是在推出Windows版本的驱动程序后才编写Linux版的。但一些大硬件厂商在这方面做得还不错,他们的Linux版驱动程序一般都推出得比较及时。

       è½¯ä»¶æ”¯æŒçš„不足是Linux最大的缺憾,但随着Linux的发展,越来越多的软件厂商会支持Linux,它应用的范围也越来越广。这只小企鹅的前景是十分光明的。

浅度剖析 SeaBIOS 基础组件之 PCI 枚举

       欢迎关注我的公众号:窗有老梅

       本文是一篇关于《QEMU/KVM 源码解析与应用》系列读书笔记的番外篇,深入浅出地分析了 SeaBIOS 中 PCI 枚举的码分实现,并探讨了 PCI 体系下的码分几个有趣细节。以下内容将引导您了解 PCIe 总线基本架构、码分SeaBIOS PCI 枚举的码分实现、以及探讨设备如何得知自己的码分前端源码泄露 bus、device 和 function 号,码分最后讨论一条总线上最多能挂载的码分设备数量。

       在 PCIe 总线的码分基本架构中,图1展示了一个直观的码分总线结构图。理解 PCIe 总线中的码分 bridge 概念对于深入学习 PCI 架构至关重要,尽管关于 bridge 在 PCI 和 PCIe 下的码分不同含义,文中并未详细区分。码分

       SeaBIOS 枚举 PCI 的码分基本流程如下:遍历一条 bus 上的所有 device,以实现系统对硬件设备的码分全面识别与管理。这一过程对于理解 BIOS 如何与硬件交互具有重要意义。

       接下来,本文将深入探讨 PCI 枚举代码背后的一些有趣细节。首先,systemctl源码设备是如何知道自己的 bus 号的。设备的标识 BDF(bus device function)需要通过主机桥在 PCI 总线扫描时分配给设备,此过程基于 DFS(深度优先搜索)策略。当访问到一个 bridge 时,主机桥会为其分配 primary 和 secondary bus number,subordinate bus number 则在 DFS 回溯到当前层时得知。设备在收到的配置报文中包含 bus 和 device 号,此时设备将其记录到寄存器中,类似于当有人敲门告诉你所在的门牌号,你便能知道自己所处的位置。

       其次,设备如何得知自己的 device 号。设备的 device 号在与主机桥的交互过程中被确定,实际上,这是基于地址译码电路将 AD[:] 转换成片选信号,实现设备选择。PCI 总线推荐使用 AD[:] 进行地址译码,通过固化的战神源码映射关系,每种设备对应唯一的片选信号,从而确定设备号。

       设备如何知道自己的 function 号?对于单 function 设备,function 号默认为 0。而对于多 function 设备或支持虚拟 function 的设备,function 号由设备内部管理,无需通过总线枚举确定。

       一条总线上能挂载的设备数量受到多种因素限制。理论上,设备的 BDF 寄存器宽度允许最多 个设备。然而,实际限制还包括物理地址译码电路、负载能力,以及内存管理单元(MMU)对地址空间的支持。例如,AD[:] 的输入限制最多只能输出 路片选信号,实际的译码电路输入通常减少到 AD[:],进一步限制到 路。swd源码PCI 总线负载能力也限制了最多能挂接 个负载。

       通过本文的深入探讨,您可以对 PCI 架构及其在 SeaBIOS 中的应用有更全面的理解,同时对设备识别和硬件交互过程有更深的洞察。

如何学习嵌入式

       ä½œè€…:匿名用户

       é“¾æŽ¥ï¼š/question//answer/

       æ¥æºï¼šçŸ¥ä¹Ž

       è‘—作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

       å­¦ä¹ åµŒå…¥å¼ç³»ç»Ÿï¼Œé¦–先应该明确什么是嵌入式系统,否则费力去学,却不知所学为何物,岂不惘然?嵌入式系统的定义很多,这也是困扰嵌入式系统学习的一个因素。笔者根据自己开发和教学过程中的理解,以及对各种嵌入式系统的应用进行总结,提出了嵌入式系统的简单定义:嵌入式系统是嵌入式计算机系统的简称,这个定义突出嵌入式计算机系统和普通计算机系统的共性。下表列出了嵌入式系统的一些典型的应用:

       æ™ºèƒ½æœºå™¨äººï¼ˆS D R 4,火星登陆车)

       å¨±ä¹å’Œæ¶ˆè´¹ç”µå­ï¼ˆGameboy Advance,SonyPSP)

       ç½‘络通信产品(Smartphone)

       å†›ç”¨è®¾å¤‡ï¼ˆå†›ç”¨PDA )

       æ±½è½¦ï¼ˆè½¦è½½å¯¼èˆªï¼Œè‡ªåŠ¨é©¾é©¶ï¼Œå¨±ä¹ç³»ç»Ÿï¼‰

       æ™ºèƒ½ä»ªå™¨ï¼ˆè™šæ‹Ÿä»ªå™¨ï¼‰

       å®‰å…¨é˜²æŠ¤ï¼ˆé˜²ç«ï¼Œé˜²ç›—)

       çŽ¯å¢ƒä¿æŠ¤ï¼ˆæŽ¢ç©ºæ°”球)

       é“¶è¡Œå’Œå•†ä¸šæ¶ˆè´¹ï¼ˆATM)

       ä»¥ç«æ˜Ÿç™»é™†è½¦ä¸ºä¾‹æ¥åˆ†æžä¸€ä¸‹åµŒå…¥å¼ç³»ç»Ÿçš„定义。火星登陆车虽然听起来感觉在技术上有些高不可测,但是本质就是嵌入式计算机系统的应用,其核心就是一个计算机系统,而这个计算机系统的组成同传统的计算机系统在本质上没有什么差别。两者的显著不同之处就在于,用于火星登陆车的计算机系统被安装到了火星登陆车上。当然,一个计算机系统能够被安装在火星登陆车上,是需要进行很多特殊设计的。但是从本质上讲,嵌入式系统的核心概念还在计算机系统。嵌入式系统学习的重点也在计算机系统上。一方面,学习者需要牢固掌握计算机系统本身的概念,更重要的是学习嵌入系统的开发过程同传统计算机系统开发过程的差别。这里需要指出的是,很多学习者本来就没有从事过完整计算机系统的开发,高校的教学是以程序设计为中心的,计算机系统的构成,操作系统的原理,编程语言等课程都是为了能够让学生更好的使用计算机系统进行程序设计,在现有的计算平台上来设计实现各种应用,学生一般没有机会学习一个完整的计算机系统是如何构建,并亲身参与到构建的每一个过程。而对于嵌入式系统而言,从事平台开发的人就是要亲自去开发出一个完整的计算机系统,这个过程包括

       1. 需求分析

       2 硬件设计

       3 驱动程序

       4 Bootloader & BSP (板级支持包)

       5 操作系统的移植

       6 应用程序的开发

       7 性能检查

       åµŒå…¥å¼ç³»ç»Ÿæ•™å­¦çš„目的就是教会学生如何根据需求去建立满足某种特殊行业需求的嵌入式计算机系统。让学生学会如何构件硬件平台,进行硬件设计,选择能够满足应用要求的最佳的嵌入式操作系统,并完成Bootloader,BSP和驱动程序的编写,移植,调试等过程。为了满足行业需求,最终要在所建立的系统上编写调试相应的应用程序,并进行性能的测试和检查。

       ä½ æ˜¯è°,你需要学习哪些东西?

       å¦‚果你的工作只是需要在PC 机上编写一个图片浏览程序,那么你就没有必要去了解当系统收到一个ARP请求包后应该如何回应。同样的道理,嵌入式系统的学习也是有很多方面的。就嵌入式系统的设计和实现而言,基本上需要四种不同的工作:系统设计工作,硬件设计工作,驱动程序和操作系统移植工作和应用程序设计开发工作。

       1.系统设计工作

       åœ¨ç³»ç»Ÿçš„设计阶段,系统分析师将根据需求确定系统的硬件的基本构成,根据系统的需求选择使用那种处理器,使用哪种操作系统,使用那些软件开发工具。系统分析师往往是较为完整的参与过嵌入式系统设计的全过程,对于系统应用的行业较为了解,对于嵌入式系统本身的开发流程十分清楚的人。

       2.硬件设计工作

       ç³»ç»Ÿç¡¬ä»¶è®¾è®¡äººå‘˜éœ€è¦æ ¹æ®ç³»ç»Ÿåˆ†æžå¸ˆçš„设计结果,进行硬件原理图的设计。通常需要硬件设计人员熟悉嵌入式系统的硬件构成。硬件设计人员需要了解常用的嵌入式系统处理器,存储器(Flash,SDRAM),以太网MAC芯片,音频/视频编解码芯片,电源管理芯片,总线接口电路 (USB,PCI),液晶显示模块,可编程逻辑器件(FPGA/CPLD),无线网络通信模块(Bluetooth,WLAN,GPRS)等硬件电路构成元素的基本工作原理,连接使用方法,使用注意事项,基本调试方法等内容。在网络上能找到很多公司的评估板的原理图,对于这些原理图要仔细研究,摸清处理器同存储器,网卡,液晶模块等器件的连接方法和原因。通过对这些电路的研究,能够较快地了解整个嵌入式系统的构成,这些电路同实际产品中的电路虽有一定差别的,特别是对于手持设备,但这些差别不影响初学者学习嵌入式系统的硬件设计基本构成。

       ä»¥ä¸Šè¿™äº›çŸ¥è¯†ï¼Œå¾€å¾€éœ€è¦è¾ƒé•¿æ—¶é—´çš„学习和积累,需要亲自参与实践的机会。对于刚刚接触嵌入式系统硬件开发的学生来讲,一般不可能全部了解这些知识,但也不会是通通一无所知。笔者结合自己开发和教学的经验认为:首先应该选定一款主流且较为简单的嵌入式系统处理器,比如基于ARM7TDMI 内核的ATM,S3CB0 等嵌入式系统处理器,学习 位RISC处理器的编程模型,指令集。高校教学中,单片计算机课程一般以系列单片为核心讲解,由于现代位处理器的结构和开发方式同8位单片机有着较大的差别,学习者还是需要花一点力气来研究以下位处理器的。以ARM处理器为例,学习者就需要理解处理器的多种工作模式,备份寄存器,RISC 指令集的特点,MMU 和虚拟地址,中断处理过程等内容。在学习指令集的过程中,最好能够每学习几条指令,就使用这几条指令在模拟器上实验以下,观察处理器执行的结果。这个过程一方面是学习者对于指令本身的学习能够取得一个比较好的效果,另外也是对开发工具本身的一种学习。接着,就可以开始学习片上资源的使用和配置方法。这时就需要一个方便使用的开发板,学习者能够通过JTAG仿真器将开发板同调试PC机相连,进行程序的下载,调试。特别是要仔细研究系统的初始化过程和中断处理的过程。在开发过程中如果遇到问题,应自己分析问题产生的原因,通过分析缩小问题可能产生的范围,最终找到问题的所在。最重要的就是要保持一种解决问题的信心,面对困难如何处理,往往能够决定最终系统是否能够调试成功。然后,学习者可以开始仔细学习处理器同存储器的连接,存储空间的配置,各种外扩器件,如网卡,AC声卡的工作原理和使用方法。嵌入式系统硬件设计中往往需要使用可编程器件,学习者还需要一定的时间来学习使用常用的可编程器件(CP L D / F P G A),常用的有Xilinx和Altera公司的产品。进行系统硬件原理图设计,就需要使用原理图设计的EDA工具,常用的EDA 原理图设计工具主要包括Cadence公司的Capture,Protel公司的ProtelSE等。接下来就可以参照评估板的电路图,根据系统的设计要求,开始进行原理图的绘制了。在原理图绘制过程中,一定要搞清评估板电路连接的原因,对于一时没有搞清楚的问题切不可蒙混过关。例如,有些处理器的地址线是以字节位单位的,而另一些处理器的地址线则是以两个字节为单位的,当连接位的存储器的时候,切不可想当然的把处理器的A 0 直接连接到存储器的A 0 上面。另外,学生还应具有一定的PCB板图绘制能力,因为在现阶段,很多公司还不能完全把原理图的设计工作和PCB 的绘制工作分开,往往要求硬件设计人员既能进行原理图设计又能进行板图设计。即使是PCB设计和原理图设计分开的公司,也需要原理图设计者能为PCB 的设计者对于不同的信号提出布板要求。

       3.驱动程序和操作系统移植工作

       çŽ°ä»£åµŒå…¥å¼ç³»ç»Ÿçš„开发同传统8位单片机系统的开发相比,一个显著的区别就是嵌入式操作系统的广泛使用。在拿到焊接完毕的电路板,并进行基本的测试后,就要进行驱动程序和操作系统的移植工作了。首先要进行的Bootloader的编写和移植工作。Bootloader相当于PC系统的BIOS。对于有些嵌入式操作系统,如uc/OSII没有bootloader同样可以开发调试。但是对于WindowsCE和嵌入式linux系统而言Bootloader就是必须的了。本文以Windows CE 为例,做一个简要的说明。

       Windows CE 系统的移植工作主要就是BSP(板级支持包)的开发过程。BSP将具体的硬件差异同操作系统的核心隔离开来,主要由Bootloaer ,OAL(OEMAbstraction Layer)和设备驱动程序三部分组成。WindowsCE系统中Bootloader叫做Eboot。Eboot被写入系统的引导Flash。系统启动时运行Eboot,完成通过网卡将调试PC 机中WindowsCE 操作系统映像下载到目标系统的SDRAM中并开始执行的功能。对于一个系统移植人员,首先需要阅读文档,了解WindowsCE系统Bootloader和BSP的基本概念和开发过程。(呵,还要做这工作啊,我还没想到(初学^_^))Windows CE的开发系统Platform Builder提供了详细的文档和例程,开发人员需要仔细的阅读文档和例程。搞清楚各个函数之间的调用关系。在开发过程中的一个重要的步骤就是打通串口,使得目标板能够通过PC机串口向调试PC 机发送数据。由于ARM系统的仿真器比较昂贵,而且操作系统的调试往往不使用JTAG调试器进行单步调试。所以能从串口观察程序的执行过程和结果对于调试就显得十分重要了。串口打通之后一个比较棘手的问题就是网卡芯片的调试。刚刚接触嵌入式系统开发的人往往没有直接在寄存器级上使用网卡芯片的经验,而网卡芯片的说明一般都较为简短,这就要求开发者学习一些以太网的基础知识,对以太网的MAC 层有一个基本的认识。另外,各种网络调试(抓包)工具的使用也能大大降低系统调试的难度。系统的OAL需要根据具体硬件的不同做出相应的修改,这个部分可参照文档进行,在调试过程中根据串口的信息分析出错的地方。要充分发挥跨文件字符串搜索工具的功能,在浩如烟海的源文件中找到出错的位置。当然,随着开发者对系统文件目录结构的熟悉和了解,错误定位的速度会不断加快。WindowsCE 的驱动程序相对而言是比较好写的。

       4.应用程序的开发

       åµŒå…¥å¼ç³»ç»Ÿçš„应用程序开发同在PC 机上开发应用程序的区别不是很大。对于Windows CE系统而言,Microsoft已经提供了较为完善的开发工具。特别是.NET Compact work的使用,使得基于Windows CE.NETCompactwork的应用程序有了跨平台性。开发人员可以使用Windows 的C# 语言直接在PC 上进行http://CE.NET应用程序的开发和模拟调试,也可将目标系统同PC 机相连,进行联机调试。现在有很多系统支持J2ME(JAVA的嵌入式系统版本) ,这使得JAVA 在嵌入式系统应用开发中占有较大的优势。另外,作为专业的嵌入式系统软件开发人员,还需要充分了解面向对象技术和设计模式等方面的知识,当然作为初学者可以先不深入研究这方面的内容。

       å¸¸ç”¨åµŒå…¥å¼ç³»ç»Ÿå¤„理器和操作系统

       å¤„理器

       å¸¸ç”¨åµŒå…¥å¼ç³»ç»Ÿå¤„理器主要包括ARM 处理器,Power PC 处理器,基于MIPS 内核的嵌入式处理器,软核处理器(如Altera 的Nios和Xilinx的MicroBlaze等)和DSP(数字信号处理器)等。

       ARM 处理器的主要特点是具有较高的性能功耗比。ARM处理器被广泛的应用在手机,PDA等领域,其中较为著名的有Intel 公司生产的基于ARM 内核的XScale系列处理器。由于所有公司生产的基于ARM内核的处理器具有相同的编程模型,在手持和电池供电的系统中,基于ARM的嵌入式系统处理器往往被首先选用。PowerPC(简称PPC)处理器具有较强的运算性能和数据吞吐能力,在网络和数据通信领域基于PPC的嵌入式系统处理器有着广泛的应用。其中Motorola公司生产的MPC/MPC被大量地应用在嵌入式网络产品中。MIPS 处理器的特点表现在十分强大的处理能力上。作为高性能处理器,MIPS处理器适用于网络、企业及高级消费类电子应用,特别是在机顶盒系统中,MIPS处理器具有较高的市场占有率。随着可编程器件的规模不断扩大,使得人们能够根据需要定制处理器,并方便的将针对某种特殊应用定制的处理器方便的在可编程器件内部实现。除了处理器外,计算机系统还需要许多其他构成部分,比如在多通道媒体数据处理系统中,经常需要使用可编程器件来实现高速的数据处理功能,使用软核DSP来实现复杂的数字信号处理算法,同时还需要处理器进行事务处理,软核处理器将可编程器件,DSP同处理器结合在一起,为系统级设计提供了极大的灵活性。DSP(数字信号处理器)有别于通用处理器,集中表现在其强大的数字信号处理能力上。在DSP 内部提供了硬件乘累加器,处理器在设计上对于特殊的寻址方式做了优化,一些DSP 还支持零耗循环(Zero OverheadLoop)。为了方便嵌入式系统设计,主流DSP 一般也都提供了丰富的外设。特别值得一提的是ADI 公司的Blackfin 系列DSP和TI 公司的DMX系列DSP,两种处理器都提供了丰富的片上外设,非常适用嵌入式系统应用。

       æ“ä½œç³»ç»Ÿ

       http://WindowCE.NET/5.0

       ä½œä¸ºMicrosoft的产品,WindowCE.NE/5.0提供了功能完备的平台开发工具Platform Builder和应用开发工具Embedded Visual C++/Visual Studio 。WindowsCE由于拥有广大使用者所熟悉的windows界面,系统提供了众多驱动程序,并且有完备的文档支持。对于应用开发而言,熟悉Windows系统开发的程序员很容易转到WindowsCE 应用程序的开发。Windows CE将会是一个非常有前途的嵌入式操作系统。

       VxWorks

       VxWorks是由Windriver(风河)公司出品的嵌入式实时操作系统,大名鼎鼎的火星登陆车就是使用了VxWorks。Windriver为VxWorks提供了集成开发环境tornado。

       Ï…C/OSII

       Ï…C/OS是由Jean Labrosse设计编写的开放源代码的嵌入式实时操作系统,笔者最早接触的嵌入式操作系统就是它。阅读并深入理解υC/OS的源代码对于理解实时系统是大有裨益的。

       ARM Linux

       ARM linux是由Russell King和其他开发者开发移植的用于ARM 处理器的linux操作系统。ARM Linux系统在GNU GPL下发布。

       Ï…CLinux

       Ï…Clinux 是适用于没有MMU 的嵌入式处理的LinuxOS 版本。υ Clinux 同样在GNU GPL发布。

       åµŒå…¥å¼ç³»ç»Ÿå¼€å‘过程中的常见问题和解决方法

       Bootloader如何写入Flash ?

       åˆå­¦è€…一般都会遇到如何将程序写入处理器的问题。对于不同的处理器,可以采用不同的方法。例如Intel的Xscale处理器可以使用Intel公司提供的JFlash工具烧写。对于具有JTAG调试工具软件的处理器,可以使用如下思路:编写一段程序,这段程序能将位于SDRAM/SRAM 固定地址中的数据写入Flash中。烧写时,首先,将这段软件下载到SDRAM 中,然后通过调试软件将要写入Flash的数据下载到SDRAM/SRAM的某个固定地址开始的缓冲区,然后通过调试器开始执行程序,将数据写入Flash。除此以外,网络上还提供了很多专用的写Flash的工具,开发者可以根据自己的需要选用。(现在明白了我在学的那个BF为什么先下个flashProgramer.dxe先了)

       ä»€ä¹ˆæ˜¯arm-elf-gcc?

       arm-elf-gcc是一个交叉C语言编译器。我们在PC平台下编译程序,编译器运行的处理器同生成的代码将要运行的处理器相同。但是,在PC

       æœºä¸Šç¼–译ARM程序时,编译器运行的处理器同生成的代码运行的处理器不同,这种编译器叫做交叉编译器。其中的elf是指编译器生成的目标文件格式。(其实我们平时用的单片机编译器如GCC—AVR等已是交叉编译器了,我到现在才弄清楚什么是交叉编译器)

       èµ°äº†å“ªæ¡ç¼–译路径?

       ç³»ç»Ÿç¨‹åºå’Œé©±åŠ¨ç¨‹åºå¾€å¾€åŒ…含很多的编译选项,很多选项都是在编译时通过命令行定义的,如果想知道编译的是那一段程序可以使用如下的方法:

       #ifdef PLAT_AAA

       #error Code for Platform AAA

       #else

       #error Code NOT for Platform AAA

       #endif

       è¿™æ ·åœ¨ç¼–译的时候就知道,编译的是哪一条路经了。对于支持#pragma message( “I am here”)的编译器也可使用#pragma message预编译指令。

       æˆ‘怎么知道那段代码在那个文件中?

       ç³»ç»Ÿç¼–程中经常需要使用在多个文件中搜索字符串,在windows平台下可以使用平台提供的多文件字符串搜索工具。在linux平台下,可以使用grep来搜索字符串。Grep的搜索功能十分强大,支持正则表达式搜索,熟练使用grep对于阅读系统和驱动程序代码是很有帮助的。

       ç³»ç»Ÿæ˜¯ä»Žé‚£ä¸ªæ–‡ä»¶å¼€å§‹è¿è¡Œçš„?

       å¯¹äºŽWindows CE系统,一般从WINCE\PLATFORM\YourPlatform\KERNEL\HAL目录的某个汇编文件中。对于Linux系统版本不同会存在一定差异,以arm处理器为例,一般会在linux2.4.x\arch\arm\kernel的head-armv.S中。

       ç¨‹åºæ‰§è¡Œåˆ°äº†é‚£é‡Œï¼Ÿ

       å¯ä»¥åœ¨ç¨‹åºä¸­æ’入如下代码来实现

       printf( “I am here %s, %d\n”,__FILE__,__LINE__);

       ä»£ç å°†æ‰“出printf语句所在的文件名和行号。

       æŽ¨èä¹¦ç›®

       Jean J.Labrosse MicroC/OS-II The Real-TimeKernel,Second Edition这本书是笔者接触嵌入式实时系统的入门书,在国内能够买到中文版。这本书较为清楚地讲述了实时系统的概念,各个组成部分的工作原理,特别是公开了实时系统内核的源代码,仔细研究定会受益匪浅。有个小的提示,对于初学者,这本书可以先不看第一章,直接从第二章看起。

       Abraham Silberschatz, Peter Baer Galvin,GregGagne Operating System Concepts笔者在教学过程中发现,无论是计算机还是电子工程专业都有很多学生对于操作系统的基本概念都没有搞清,很少有学生有完整的系统编程经验。Operating System Concepts这本书对操作系统的概念讲述只能用经典来形容。对于嵌入式系统有兴趣深入研究的同学,首先要把基础打好,这本书就成了必读之物了。

       Andrew S. Tanenbaum Computer Networks 提起Andrew S. Tanenbaum 学习计算机的同学一定都知道OPERATINGSYSTEMs:Designand

       Implementation这本书,笔者对于Tanenbaum这样的教授由衷佩服。网络协议栈是嵌入式系统中的支柱性组成部分。愿意致力于网络深层技术研究的同学,这本书将为你们建立一个坚实的网络基础。

       Karim Yaghmour Building Embedded Linux Systems本书详尽的介绍了嵌入式linux系统的组成,基本概念和如何去建立各个部分。全书篇幅较小,可谓短小精悍。即可以作为嵌入式linux系统的入门读物,又是开发过程各个部分的指南。

       Advanced RISC Machines Ltd (ARM) ARM7 TDMI DataSheet Advanced RISC Machines Ltd (ARM) ARMTTechnical Reference Manual学习嵌入式系统不了解当前应用最广泛的嵌入式处理器怎么行?ARM7 TDMI 的 data sheet是学习ARM编程模型,指令集的好东西。在嵌入式系统中,MMU(内存管理单元)是很重要的部分,又是较难理解和掌握的部分。ARMTTechnical Reference Manual 正好可以帮你讲解这方面的内容。

       Perter Van Der LinDen Expert C Programming嵌入式系统级编程最常用的语言还是C 。很多同学都自认为自己的C语言学的很好,那好,就看看这本书吧,找找自己和Experts差距。

       åµŒå…¥å¼å¼€å‘与桌面开发既有不同,又有非常大的联系,而且十分注重实际操作能力。搞桌面开发的人在一开始接触嵌入式的时候,通常转换不过来,这主要体现在定位上。如文中所说,你是谁,你要做什么?我对硬件的了解仅限于编程领域,PCB设计一窍不通,但并不能说你不懂硬件就不能从事嵌入式开发。一个系统的开发设计方方面面,在自己感兴趣和熟悉的领域做出自己的贡献才是最主要的。

       1。硬件设计: 需要有硬件设计的经验,对各种嵌入式器件有很好的了解。

       2。系统移植:需要汇编经验,操作系统原理以及底层驱动的了解

       3。应用程序:需要桌面编程经验

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

       虚拟存储器概念

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

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

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

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

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

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

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

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

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

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

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

       系统映像文件(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()函数完成。

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。