QNX简介

来源:互联网 发布:阿里云研究报告 编辑:程序博客网 时间:2024/06/14 21:39
QNX简介:
体系结构:过去和现在 


从1981产生至今,QNX 的体系结构与当前的形式基本上保持类似。QNX 4.x 有一个非常小的微内核(约为12K),内核周边有一批协作进程,提供高层的 OS 服务.如今,QNX 广泛的用于那些实时性能、开发灵活性、网络灵活性为首要要求的应用。大量已安装的QNX系统证明微内核技术不仅经济上可行的而且适合关键性任务的应用,象过程控制、医疗器械、财政事务处理、数据通信、家用电器等等。事实上,这些应用对性能的需求是 QNX 发展的重要的推动力。 

在1989年,Posix 兼容的 QNX(4.0)版本的开发目标是把以前几代 QNX 的高性能和灵活性最大化。 本文详细描述此体系结构的特征,并讨论它的优点和局限,也包括将来开发的目标领域。 

一个真正的微内核

QNX 微内核实现四种服务:进程间通信,低层网络通信,进程调度,中断派遣。微内核有少量的与这些服务有关的内核调用。总体上,这些功能粗略的占用了12K的代码,并提供实时执行的功能和性能(参见附录A)。很小的内核可以让有相当数量的片上 cache 的处理器为应用程序提供优异的性能,原因是微内核和系统中断处理的活跃部分可以很容易地放在大小合适的CPU 片上 cache 中。 


QNX 微内核。 

微内核提供的消息传递设施实现的是阻塞的 Send(), Receive(), 和 Reply()。简介: 

(1) 一个进程发出一个向其他进程发出一个 Send(), 此进程将被阻塞,直到目标进程发出一个 Receive() ,处理消息,并发出一个Reply();此进程才被唤醒。 

(2)如果一个进程执行一个Receive() ,而此时没有等待处理的消息,此进程将被阻塞,直到其他进程执行一个 Send() 才被唤醒。 

(3)因为这些基本操作(或原语)不经排队地直接在进程间拷贝数据,消息传送的性能接近底层硬件的内存带宽。 

(4)在 QNX 中所有的系统服务都建立在消息传送的基本操作的基础上。


在这些 IPC 基本操作之上的变体(例如消息队列),业已轻松地作为使用这些低层服务的服务器实现了,用性能上的术语说,这 IPC 的变体是可以与单内核内实现的此类服务相比较的。 

进程可以要求这些要求消息以优先级的次序递送(而不是以提交时间为次序),在最高优先级执行的进程阻塞所有其他等待服务的进程。这种消息驱动的优先级机制巧妙的避免了优先级逆转。服务器进程被强制在它所服务的进程的优先级上执行,当然在一个更高的优先级进程在一个繁忙的服务器上阻塞时,服务器进程的优先级将自动的提高到适当级别。作为结果,一个低优先级进程,不能通过调用有更高优先级的服务器进程的服务的方式,来抢占高优先级进程的执行。 

译注:“优先级逆转指的是这样一种情形,低优先级的进程拥有高优先级所需要的资源,从而阻塞了高优先级的进程的执行”。 


典型的"发送-接受-回应"事务涉及的状态 。 

消息基本操作支持多块消息,这样一个从一个进程递送到另一个进程的消息不需要占用一块单一的连续的内存空间。实际上是,发送和接收进程可以指定一个 MX 表用来指示发送和接收的消息驻留在内存中的位置。这样就允许发送头部块和数据块分开的消息,而不用做消耗性能的复制的来生成一个连续的消息。除此之外,如果低层的数据结构是环状缓冲区,一个三部分的消息将被允许一个头和两个在环状缓冲区中区间不连贯的形式,并作为一个单一的原子的消息发送。提供给发送者和接收者的 MX 映射不必相同。 


多部分消息通过MX控制结构指定。微内核把它们组合进一个单一的数据流中。 

在微内核中直接设计了一个用于网络通信的低层“挂钩”这个挂钩被一个称为网络管理器(在后面描述)的可选的进程所使用。当选了网络管理器时,网络管理器被连接到微内核,并把在局域网上的微内核之间移动消息所需要的设施提供给微内核。通过在这个在系统中最基础的层次上提供网络服务,任何在 OS 体系结构中更高层次上提供的服务都可以被在局域网任何地方的任何进程透明的访问。这种实现的性能是优异的,尤其是跨网络的用户层进程间递送近乎电缆的吞吐率。 

QNX 的进程调度基本操作遵循 POSIX 1003.1b 标准的实时规范。QNX 提供了完整的、可抢先的、有优先级的环境切换,调度算法有:时间片轮转、FIFO、自适应调度。 

  资源管理和路径名空间管理 


为了使微内核提供 POSIX 标准和 UNIX 惯例所定义的功能,可以增加被称为资源管理器的可选的进程。可以从微内核建立一个最小化的系统(比如没有文件系统和设备输入输出系统),包括一个进程管理器,和一系列的应用程序进程。 

在 QNX 中第一个和唯一必须的资源管理器是进程管理器(Proc),它提供进程创建,进程记帐,内存管理,进程环境继承(对本地和网络远程进程都是),路径名空间管理。第一级路径名由 Proc 管理的原因是在 QNX中文件系统是可选择的,而不象单体内核系统中文件系统总是存在。无盘和基于ROM 的系统可能不使用文件系统,所以不强制必须包括文件系统。 

在其他资源管理器执行之前,Proc “拥有”整个的路径名空间(根目录和其下面的所有东西)。如果没有其他的资源管理器出来提供服务,这基本上是一个空的文件系统。Proc 允许其他资源管理器通过一个标准的 API来接受其想管理的那一部分名字空间(拥有认证域)。Proc 响应并维护一个前缀树(prefix tree)来跟踪这些拥有各种各样的部分名字空间的进程。 

当一个文件系统管理器例如 Fsys(POSIX 文件系统管理器)和一个设备管理器例如 Dev 运行了,前缀树看起来可能象下面这样: 

  / 基于磁盘的文件系统(Fsys) 
/dev 字符设备系统 (Dev) 
/dev/hd0 (Fsys)原始磁盘卷 
/dev/null 空(Null)设备 (Dev) 


当一个进程打开一个文件,open() 库例程首先把文件名发送到 Proc , Proc 会拿前缀树和路径名做比较,把open() 导向合适的资源管理器。在资源管理器的认证域有部分重叠的情况下,将选取路径名的最长的匹配。例如打开 /dev/tty0 最长的匹配发生在 /dev,导致打开指向 Dev 。路径名 /usr/fred 与 / 匹配 ,打开指向 Fsys。 

在网络上的每个计算机的进程管理器维护自身的前缀树,在每个节点上的进程可能看到的“网络范围路径名空间”可以是一致的也可以是不同的。以 / 开始的路径名的使用基于本节点的前缀树。也可得到网络上唯一的名字,这样就允许应用程序用此名字指定资源在网络范围路径名空间中的绝对位置。通过使用前缀别名( Proc 管理的在内存中的重映射表),部分名字空间可以映射到网络上其他节点的资源管理器上。例如,一个从 LAN 上引导的无盘工作站希望拥有自己的以其他节点为根的文件系统,它就可以把自己的文件系统的根定义为一个远程的 Fsys 进程的别名。 

当上面的别名存在时,对 /dev 的 open() 调用仍然被映射到本地的 Dev 进程来控制本地设备,但所有对文件的 open() 调用被转成一个 open 消息,此消息将被前面指定的远程节点的前缀映射表解析(通常把文件打开指向那个节点的 Fsys 进程)。通过连接到一个通常的根目录,在网络上任何地方的进程可以在一个单一的目录树中访问所有的网络文件系统。可替代的选择是,通过使用“网络绝对路径名”,网络路径名空间也可以作为一系列独立的根文件系统进行维护。 

通过在传统的文件名空间上实现单独的认证域,OS 的总体功能中的很多部分可以用运行时可选的方式实现。既然资源管理器进程在内核空间外存在,那么就在运行时被动态的增加和删除,而不需要用重新连接内核来包含不同层次的功能。这种在大小上的灵活性允许 OS 易于按应用程序的需要而放大或缩小。 

尽管对把资源管理器提供的服务放置在内核之外的第一印象是低效,但性能结果(参见附录)表明环境切换和 IPC 的性能充分的保持了硬件的原始性能。事实上,QNX 的快速环境切换允许 OS 的功能在协作进程间分配而不为此导致性能损失。这样就明确了这种结构在体系上的优势。 

这种分布式名字空间的网络透明性允许远程运行的进程和本地处理器上运行的进程在逻辑上等价。独立管理的路径名空间实现了无缝的混合,也就是对名字空间的行为没有什么“意想不到”的。继承整个父进程的环境,包括打开的文件描述符,环境变量,当前工作路径。即使在分布式网络环境下,进程间通信和 I/O 操作也与 POSIX 1003.1 定义相一致。 

Fsys - 文件系统管理
Fsys 是实现文件系统的多种资源管理器中的一种。Fsys 为 QNX 环境提供了一个高性能的 POSIX 兼容的文件系统。它实现了一个磁盘结构,用位图分配空闲空间,实现了延伸块(extent)的链表用来组织磁盘上的数据。这种实现允许系统提供给应用程序层次的的磁盘吞吐率接近硬件的原始能力(参见附录B)。Fsys 对保持文件系统完整性很关键的数据结构实行同步的写磁盘操作,这允许磁盘系统可以在意外的电源失效中幸存下来,在在磁盘上的数据结构中嵌入了特殊标志,令文件系统在灾难性错误事件后也能被重建。 

多线程的 Fsys 体系结构允许它处理并行的多路请求,例如在其他线程因为等待物理 I/O 发生而阻塞时,执行ramdisk 和 cache I/O 的线程可以运行。如果设备支持多路等待 I/O 请求,那么这些请求可以由驱动来服务,以驱动认为合适的顺序执行.那么这种并行性也可以延伸到驱动程序,提交的要求可以按任何适当的次序得到服务。进一步,通过 Fsys 层的文件 I/O 请求按延伸块编码,而不是按单独的磁盘块编码。这导致对磁盘驱动器所表达的工作单元自然的映射到磁盘驱动器指定喜欢的 I/O 模式上。结果是得到了现代磁盘驱动器的顺序读写的 I/O 速率,和实质的文件系统性能提高。 

从第一眼的印象上,一个消息传递的 OS 中的文件系统应该比单体内核的文件系统需要更多的数据复制。事实上不需要额外的复制。MX 的多块消息基本操作允许 Fsys 把应用在 read() 和 write() 调用中指定的连续的缓冲区映射成在 Fsys 中的非连续的 cache 块。对于一次读磁盘,磁盘驱动程序从磁盘读到多路非连续的 cache 中。 Fsys 接着调用在内核中的 MX 功能自动地把散开的块聚集和复制到应用程序指定的连续的读缓冲区中。结果是,即使在一个消息传递、网络透明的环境内的文件系统操作,也展示出与在单体内核中实现的高速缓存(cache)的文件系统同样数量的数据复制。 

在一个无盘的网络连接的机器上,Fsys 进程可以用命令行启动。设备驱动程序也动态的挂接在 Fsys 上,在Fsys 将不再使用的情况下,Fsys 和它的设备驱动程序可以从内存中除去。 

注意可得到许多文件系统管理器。例如包括 Dosfsys 来访问 DOS格式化的介质,Iso9660fsys 用于 CDROM,一些嵌入式文件系统用于 Flash-memory 设备,等等。作为运行时应用程序的需要,任何文件系统进程的组合均可以并发的运行。 

Dev - 设备管理
设备管理(Dev) 提供了 POSIX 兼容的设备控制而且还带有一些适于实现通信协议的实时扩展。用与 Fsys 类似的方式,Dev进程可以动态的启动和与设备驱动程序挂接上并且如果不再被使用可以从内存中除去。 

即使在有非智能 UART 设备的现代硬件上,Dev 可以处理的波特率也高达 115 Kbaud,原因是微内核提供了低时延中断。通过增加智能通信板卡,可以轻易的配置一个高带宽的多线路通信服务器。 

有赖于 MX 基本操作,Dev 可以 Receive() 一个应用程序对一个设备作的 write() 直接到一个中断处理程序管理的环状缓冲区中。通过适当的定义 MX 表,接收的数据可以放置在 Dev 管理的环状缓冲区当中。因为写到环状缓冲区可以要求数据被映射到物理上不连贯的(逻辑上连续的)内存区域中,一个有三个表项的 MX 表可以描述环状缓冲区中一个头部和两物理上不连贯的区段。对于 read() 的情况,从设备来的数据流从驱动程序直接进入环状缓冲区,从环状缓冲区直接进入应用程序的 read() 缓冲区,而没用于建立连续的消息的冗余复制。 

设备驱动程序支持 

不要求设备驱动中断处理程序只能存在于内核空间中,QNX 提供了一个系统调用,用来允许用户进程去连接一个在有足够的权限的用户进程内的中断处理程序,此中断处理程序相应于处理内核中的某个中断向量。连接的这个中断处理程序就可以被内核调用来响应物理中断。通过在用户进程中存在,处理程序可以完全的访问这个有响应中断功能的进程的地址空间。一旦中断处理程序开始运行,它要么可以唤醒与它共享代码的进程要么是简单的返回内核。用于 Dev 的设备驱动程序从下面的行为中获利,使用单独的中断在Dev 管理的缓冲区中积累字符,只在事先定义的"重大事件"发生时唤醒 Dev (例如终端字符计数、行结束条件、或超时)。 

通过中断处理程序驻留在内核之外的方式,用户可以在一个运行的系统中动态的增加或删除中断处理程序 (和包含他们的设备驱动程序)。 由内核处理的第一层次的中断处理也照顾了嵌套和共享的中断,而不强加硬件依赖的细节和用户写中断处理程序的复杂性。微内核提供外部的中断处理程序是允许一个资源管理器与单体内核可提供的的性能水平相匹配的基础。 

易于扩展 

因为设备驱动程序在用户级进程中存在,开发者可以从这个基本的优势中获利:开发 OS 的功能的扩展与开发用户级进程相一致。事实上,在 QNX Software Systems 内部使用的开发工具是运行在全屏幕、源代码级的调试器下的实验性的资源管理器,所以调试象一个新的 Fsys 进程这样的 OS 服务可以免去调试内核这样复杂的过程就能完成。并且因为资源管理器和设备驱动程序可以在需要的时候启动或去除,重新连接内核和重新启动来测试新内核的费力的过程就变的不在是必须的了。 

作为 QNX 操作系统易于扩展的例子,象类似于在 [Pike 90]中描述的 /proc 资源管理器这样的服务可以被应用程序级的程序员(而不是内核设计师!)只用几个小时的努力和不到200行的易懂的 C 源程序实现。/proc 有效的把系统资源(一系列的在系统中的活跃的进程)包装起来,并且对于系统把它们表现得就象是在 /proc 的路径名空间中维护的文件和目录。 

一个复杂一些的例子,实现了一个类似于在 [Presotto 91] 中描述的客户端网络文件系统的 cache 管理器。这个 cache 把某节点对网络上的远程 Fsys 最近访问的文件块保存在客户端复本中。在 open() 的时候,cache 验证了远程的文件未被更改(更改将使本地的缓存的数据失效)之后提供本地缓存的数据,这样来增强性能。通过提供一个容纳 cache “溢出”的文件系统,一个以慢速串行线路连网的系统仍可以提供合理的远程网络文件系统性能。这样一个服务器只用了1000 行源代码。再者,这是完全在应用程序员的范围内使用标准系统库实现的。 

最后,客户的文件系统可以作为使用 Fsys 的裸磁盘块服务的资源管理器来实现,此客户的文件系统可表示为在根文件系统上的子树。一个例子是 PC-DOS 的文件系统 Dosfsys, Dosfsys 接受 /dos 路径名作为认证域并提供目录形式如 /dos/a, /dos/b 等等。这些目录映射到相应的 PC-DOS 介质上,并且Dosfsys 维护进入Dosfsys 认证域的 I/O 请求指示出的在此卷上的裸块。文件的维护可以被映射到所支持的下层文件系统上,而尝试其他的比如 link() 的时候则返回适当的出错信息。 

网络服务 - FLEETTM 网络技术
Fault-tolerant 容错 
Load-balancing 平衡负载 
Efficient 高效 
Extensible 可扩展性 
Transparent 透明性 
象前面曾提到的那样,网络管理器 (Net) 被直接连接进了内核。当一个本地进程调用微内核向其他节点上的进程传送消息的时候,微内核通过这个专用接口把一个指向消息的指针加入一个用于 Net 的队列中。 Net 进程也可以从其他微内核接受消息并把这些消息传给本地微内核。实质上,在网络上的网络管理器把所有局域网上的微内核融合成一个单一的逻辑上的微内核。因为所有的系统服务包括进程创建、调试、文件和设备 I/O 都凭借通过微内核消息传送完成,结果是在网络上的多个计算机的行为就象是一个单一计算机。局域网上的任何进程提供的任何服务均可被网络上的任何进程透明的访问。这是与 TCP/IP 的标志性的差异,TCP/IP 只是明显的提供了一系列服务--典型的终端任务和文件 I/O。作为对比,这个连接成的微内核体系结构允许下面的命令: 

ls /usr/danh | grep abc | wc 

以每个进程在网络上不同的处理器上运行的方式执行,而 Proc 提供的网络继承的文件描述符导致管道可以在网络上连接和转送数据。这种环境的透明性也给实现分布式应用提供了方便。一个由一系列的协作进程组成的应用可以在一个单一的 CPU 上开发,并在网络(LAN)上分布而不需要更改源代码或二进制代码。 

就象 Fsys 和 Dev 可以从命令行启动和停止、它们各自都有一族驱动程序一样,Net 也有一族驱动程序并支持连接多种网络驱动程序。如果 Net 发现在一个节点上连接了多于一个网络驱动器,它在将驱动器之间进行平衡流量负载。这里的平衡负载使用基于介质传输速率和队列深度的算法。可得到用于按用户意愿手动强制网络流量的命令行选项。 

在节点间的多条网络路径提供了更好的吞吐量和容错能力。应用程序级的变化不需要用到容错能力,因为容错支持已经存在于本地的网络管理器中了。例如,原子能反应堆监视系统就是用这种技术成功的实现的。 

作为另一种途径,廉价的串行链路可被用于在主局域网出错时的后备网络链路。通过做数据压缩、启用客户方的文件系统高速缓存等方法使串行链路以高波特率运行,串行网络的性能可以很快。 


图 4.多路物理网络通过逻辑网络融洽共存。 

当在局域网上的两个文件服务器进行点到点的高流量传输的时候经常导致局域网的拥塞问题,这样的设施也可以解决这种问题。通过 FLEET 的方式,加入一条专有的链路来连接两个服务器,把流量从主局域网上移到专有链路上。如果两服务器在物理上离的很近,那么象点到点的 SCSI 或总线到总线的 DMA 这样的非常规的局域网技术就成为可行的选择。这种方法可用于实现 CPU/文件服务器组[Presotto 91]。 
通过制造使用 backplane (背板)总线的处理器板, FLEET 方式也允许用一个系统的 backplane 总线把多处理器系统构造为一个 VLAN (超局域网)。每个处理器板运行一个包含微内核、Proc、 Net、和 Net.vlan 驱动程序的 QNX OS,其中某个处理器可以同时使用 Net.vlan 驱动程序和 Net.ethernet 驱动程序,而 Net.ethernet 是用来访问一个外部的以太局域网的。通过为这些处理器增加额外的硬件,和适当的 Dev 或 Fsys 进程,这些处理器能变成分布式 I/O 处理器。每个在以太网上的节点可以有效的包含在一个机架上的增补处理器的 VLAN。这就使在每个以太网节点上的运行的一队处理器在这个节点内重新分布并以一个处理器队伍的方式运行。 Ziatech Inc (http://www.ziatech.com/)完成这种技术的一个实现。[Tanenbaum 89]描述的计算服务器也可以用这种硬件很容易的实现。 

对于嵌入式应用,一个最小化的 QNX 系统可以被放入小于 256K 的 ROM 中(微内核、Proc 和一些应用程序)。增加一个 Net 进程和一个 Net 驱动程序( 大约 70K)之后,嵌入式系统就可以连接到一个大的网络上,变成一个大局域网的一个无缝的的扩展。这就允许嵌入式系统访问数据库、图形用户界面、局域网网关、和其他的服务。不受嵌入式系统有限的功能的限制,网络链路力图要使局域网提供给在嵌式系统上运行的进程的整个局域网资源的访问。嵌入式系统也可以从网络上引导,进一步的减少对 ROM 的要求。因为系统调试服务是通过运行被调试应用程序所在节点上的 Proc 进程的标准消息实现的,所以可以从在局域网上的其他节点上调试嵌入式系统上的应用程序。 

对于主机传输层协议, Net 提供 一个“Clarkson兼容”的原始分组递送服务并可得到网络驱动器。通过以这种方式实现的协议栈,在同一个物理的局域网上的非QNX的机器可以通过协议栈的通信访问多处理器QNX 局域网。在局域网上的 QNX 节点对与外部世界(例如 TCP/IP)表现的就是一个单一的多处理器机器。 

FLEET 协议的实现也支持网络桥接,允许分组在通过中介节点转发来把多个 QNX 局域网结合成一个局域网。因为 QNX 在所有基于 IEEE 802的网络上使用同样的分组格式和协议,你可以生成在以太网,令牌环、FDDI 局域网间的网桥。 

  可维护性 

维护一个单体内核的 OS 的基本问题是所有内核代码在一个公共的、共享的地址空间运行。内核的任何一部分都能破坏其他部分的数据空间的危险是非常现实的和每当连接新驱动程序到内核时必须考虑的。QNX 使用的方式是显式的定义组成 OS 的各部分之间的接口,每个资源管理器,就象每个用户进程一样,在自己的受保护的内存空间运行,所有 OS 模块间的通信通过标准的系统 IPC 服务完成。结果是,任何一个资源管理器产生的错误将被约束在自己的子系统中而不破坏其他的在系统中与其不相关的资源管理器。 

因为新的资源管理器和设备驱动程序可以使用与用户进程同样的工具调试和调整,系统开发与应用开发使用同样的手段。这是非常重要的,因为这样就允许通过新方式用更自由的实验来实现 OS 子系统,而不用招致使用有限的工具调试内核带来的巨大工作量。 

另一个要点是因为组成 OS 的模块在分开的、受 MMU 保护的地址空间运行,并且这些模块在不同的系统上是以"一致的二进制"方式运行。当在一个新系统配置下使用一个模块的时候,就允许直接适用以前的运行经验和对一个 OS 模块(设备驱动程序、文件系统管理器、内部开发的服务器进程等)获得的可靠的质量控制。相比之下,单体内核要重新连接内核来包含一个可选的 OS 模块,结果是对于不同的配置有完全不同二进制形式。这导致了对过去的 OS 服务的相关的运行经验在新的使用当中的作用的相应减少。因为二进制形式的变更,与迷途的指针错误相连在一起的“运气”和其他编码问题也变更了。曾经是一个不产生任何系统错误的和善的内存重写,在重新连接内核之后就可能导致系统崩溃。 

这个问题也适用于嵌入式实时执行者和不实现内核保护的内核中,当增加开发员工的时候,一个开发者的编程错误可以导致系统的行为不容易被作者跟踪,结果是非常费时的调试任务。通过在进程间的内存保护,一个开发者的错误的在 OS 中的直接结果是终止有错误的进程(迷途的指针引用和超出边界的数组访问)。避免了"Finger pointing"并且查找问题的原因可得到立即的回报。当嵌入式系统的开发队伍变得非常大的时候,质量控制与进程模块重用的结合,联合上在调试努力期间增加的生产率,提出一个选择内存保护的微内核操作系统的有说服力的论据。没有进程间的内存保护的大队伍的嵌入式系统开发事实上是难以想象的。 

性能 

QNX 必然要面对的挑战是使用者的实时应用对性能的需求。尽管一个幽雅的 OS 体系结构是很有意趣的,但学术上的优美不一定带来在商业上成功的 OS ,因为它在性能上要超过传统的单体内核的系统。许多微内核系统的一个设计目标就是与单体内核的系统在性能上相匹敌 [Guillemont 91]。但是仅仅在性能水平上可匹敌将不能提供给 OS 使用者以使用基于微内核系统的在技术上的显著利益。 

QNX 把完全的硬件性能提供给应用程序层(超出了单体内核系统的性能),开发出许多体系结构上的变革。这些增强的前提是不能对实时系统的性能进行让步。即使最初的研究指出增加的消息传送的模型的共性是要比单体内核有更大的开销,这里有一些结构上的想法用来更正这些误解。两个对全面的系统性能有显著贡献的概念是在资源管理器内直接支持中断处理,和多部分消息原语。从以性能为目标中解放出来,就可以凭借内核体系结构而致力于有更大的意义的系统健壮性和对管理更大编程队伍的努力。 

附录 B是关于 QNX 4.24 版本的性能的简述。 

  结论 

原创粉丝点击