声音识别的原理是什么,可以用简单的语言结构的基本原理描述下吗

  浏览器可以被认为是使用最廣泛的软件本文将介绍浏览器的工作原理,我们将看到从你在地址栏输入google.com到你看到google主页过程中都发生了什么。

  本文将基于一些开源浏览器的例子——Firefox、Chrome及SafariSafari是部分开源的。

  根据W3C(World Wide Web Consortium万维网联盟)的浏览器统计数据当前(2011年5月),Firefox、Safari及Chrome的市场占有率综合已接近60%(原文为2009年10月,数据没有太大变化)因此可以说开源浏览器已经占据了浏览器市场的半壁江山。

  浏览器的主要功能是将用户选择嘚web资源呈现出来它需要从服务器请求资源,并将其显示在浏览器窗口中资源的格式通常是HTML,也包括PDF、image及其他格式用户用URI(Uniform Resource Identifier统一资源標识符)来指定所请求资源的位置,在网络一章有更多讨论

  HTML和CSS规范中规定了浏览器解释html文档的方式,由W3C组织对这些规范进行维护W3C昰负责制定web标准的组织。

  这些年来浏览器厂商纷纷开发自己的扩展,对规范的遵循并不完善这为web开发者带来了严重的兼容性问题。

  但是浏览器的用户界面则差不多,常见的用户界面元素包括:

  • 用来输入URI的地址栏
  • 用于刷新及暂停当前加载文档的刷新、暂停按钮
  • 鼡于到达主页的主页按钮

  奇怪的是并没有哪个正式公布的规范对用户界面做出规定,这些是多年来各浏览器厂商之间相互模仿和不斷改进的结果

  HTML5并没有规定浏览器必须具有的UI元素,但列出了一些常用元素包括地址栏、状态栏及工具栏。还有一些浏览器有自己專有的功能比如Firefox的下载管理。更多相关内容将在后面讨论用户界面时介绍

  浏览器的主要组件包括:

  1. 用户界面 - 包括地址栏、後退/前进按钮、书签目录等,也就是你所看到的除了用来显示你所请求页面的主窗口之外的其他部分

  2. 浏览器引擎 - 用来查询及操作渲染引擎的接口。

  3. 渲染引擎 - 用来显示请求的内容例如,如果请求内容为html它负责解析html及css,并将解析后的结果显示出来

  4. 网络 - 用来完成网络调用,例如http请求它具有平台无关的接口,可以在不同平台上工作

  5. UI后端 - 用来绘制类似组合选择框及对话框等基本組件,具有不特定于某个平台的通用接口底层使用操作系统的用户接口。

  6. JS解释器 - 用来解释执行JS代码

  7. 数据存储 - 属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术

  需要注意的是不同于大部分浏览器,Chrome为每个Tab分配了各自的渲染引擎实例每个Tab就是一个独立的进程。

  对于构成浏览器的这些组件后面会逐一详细讨论。

  渲染引擎的职责就是渲染即在浏览器窗口中显示所请求的内容。

  默认情况下渲染引擎可以显示html、xml文档及图片,它也可以借助插件(一种瀏览器扩展)显示其他类型数据例如使用PDF阅读器插件,可以显示PDF格式将由专门一章讲解插件及扩展,这里只讨论渲染引擎最主要的用途——显示应用了CSS之后的html及图片

  Webkit是一款开源渲染引擎,它本来是为Linux平台研发的后来由Apple移植到Mac及Windows上,相关内容请参考

  渲染引擎首先通过网络获得所请求文档的内容,通常以8K分块的方式完成

  下面是渲染引擎在取得内容之后的基本流程:

图2:渲染引擎基本流程

  渲染引擎开始解析html,并将标签转化为内容树中的dom节点接着,它解析外部CSS文件及style标签中的样式信息这些样式信息以及html中的可见性指令将被用来构建另一棵树——render树。

  Render树由一些包含有颜色和大小等属性的矩形组成它们将被按照正确的顺序显示到屏幕上。

  Render树構建好了之后将会执行布局过程,它将确定每个节点在屏幕上的确切坐标再下一步就是绘制,即遍历render树并使用UI后端层绘制每个节点。

  值得注意的是这个过程是逐步完成的,为了更好的用户体验渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的html嘟解析完成之后再去构建和布局render树它是解析完一部分内容就显示一部分内容,同时可能还在通过网络下载其余内容。

  从图3和4中可鉯看出尽管webkit和Gecko使用的术语稍有不同,他们的主要流程基本相同Gecko称可见的格式化元素组成的树为frame树,每个元素都是一个framewebkit则使用render树这个洺词来命名由渲染对象组成的树。Webkit中元素的定位称为布局而Gecko中称为回流。Webkit称利用dom节点及样式信息去构建render树的过程为attachmentGecko在html和dom树之间附加了┅层,这层称为内容接收器相当制造dom元素的工厂。下面将讨论流程中的各个阶段

  既然解析是渲染引擎中一个非常重要的过程,我們将稍微深入的研究它首先简要介绍一下解析。

  解析一个文档即将其转换为具有一定意义的结构——编码可以理解和使用的东西解析的结果通常是表达文档结构的节点树,称为解析树或语法树

  例如,解析“2+3-1”这个表达式可能返回这样一棵树。

图5:数学表达式树节点

  解析基于文档依据的语法规则——文档的语言结构的基本原理或格式每种可被解析的格式必须具有由词汇及语法规则組成的特定的文法,称为上下文无关文法人类语言结构的基本原理不具有这一特性,因此不能被一般的解析技术所解析

  解析可以汾为两个子过程——语法分析及词法分析

  词法分析就是将输入分解为符号,符号是语言结构的基本原理的词汇表——基本有效单元的集合对于人类语言结构的基本原理来说,它相当于我们字典中出现的所有单词

  语法分析指对语言结构的基本原理应用语法规则。

  解析器一般将工作分配给两个组件——词法分析器(有时也叫分词器)负责将输入分解为合法的符号解析器则根据语言结构的基本原理的语法规则分析文档结构,从而构建解析树词法分析器知道怎么跳过空白和换行之类的无关字符。

图6:从源文档到解析树

  解析過程是迭代的解析器从词法分析器处取到一个新的符号,并试着用这个符号匹配一条语法规则如果匹配了一条规则,这个符号对应的節点将被添加到解析树上然后解析器请求另一个符号。如果没有匹配到规则解析器将在内部保存该符号,并从词法分析器取下一个符號直到所有内部保存的符号能够匹配一项语法规则。如果最终没有找到匹配的规则解析器将抛出一个异常,这意味着文档无效或是包含语法错误

  很多时候,解析树并不是最终结果解析一般在转换中使用——将输入文档转换为另一种格式。编译就是个例子编译器在将一段源码编译为机器码的时候,先将源码解析为解析树然后将该树转换为一个机器码文档。

  图5中我们从一个数学表达式构建了一个解析树,这里定义一个简单的数学语言结构的基本原理来看下解析过程

  词汇表:我们的语言结构的基本原理包括整数、加號及减号。

  1. 该语言结构的基本原理的语法基本单元包括表达式、term及操作符

  2. 该语言结构的基本原理可以包括多个表达式

  3. 一个表達式定义为两个term通过一个操作符连接

  4. 操作符可以是加号或减号

  5. term可以是一个整数或一个表达式

  现在来分析一下“2+3-1”这个输叺

  第一个匹配规则的子字符串是“2”根据规则5,它是一个term第二个匹配的是“2+3”,它符合第2条规则——一个操作符连接两个term下一佽匹配发生在输入的结束处。“2+3-1”是一个表达式因为我们已经知道“2+3”是一个term,所以我们有了一个term紧跟着一个操作符及另一个term“2++”将鈈会匹配任何规则,因此是一个无效输入

  词汇表及语法的定义

  词汇表通常利用正则表达式来定义。

  例如上面的语言结构的基本原理可以定义为:

  正如看到的这里用正则表达式定义整数。

  语法通常用BNF格式定义我们的语言结构的基本原理可以定义为:

  如果一个语言结构的基本原理的文法是上下文无关的,则它可以用正则解析器来解析对上下文无关文法的一个直观的定义是,该攵法可以用BNF来完整的表达可查看。

  有两种基本的解析器——自顶向下解析及自底向上解析比较直观的解释是,自顶向下解析查看语法的最高层结构并试着匹配其中一个;自底向上解析则从输入开始,逐步将其转换为语法规则从底层规则开始直到匹配高层规则。

  来看一下这两种解析器如何解析上面的例子:

  自顶向下解析器从最高层规则开始——它先识别出“2+3“将其视为一个表达式,然後识别出”2+3-1“为一个表达式(识别表达式的过程中匹配了其他规则但出发点是最高层规则)。

  自底向上解析会扫描输入直到匹配了┅条规则然后用该规则取代匹配的输入,直到解析完所有输入部分匹配的表达式被放置在解析堆栈中。

  自底向上解析器称为shift reduce解析器因为输入向右移动(想象一个指针首先指向输入开始处,并向右移动)并逐渐简化为语法规则。

  解析器生成器这个工具可以自動生成解析器只需要指定语言结构的基本原理的文法——词汇表及语法规则,它就可以生成一个解析器创建一个解析器需要对解析有罙入的理解,而且手动的创建一个由较好性能的解析器并不容易所以解析生成器很有用。Webkit使用两个知名的解析生成器——用于创建语法汾析器的Flex及创建解析器的Bison(你可能接触过Lex和Yacc)Flex的输入是一个包含了符号定义的正则表达式,Bison的输入是用BNF格式表示的语法规则

  HTML解析器的工作是将html标识解析为解析树。

  W3C组织制定规范定义了HTML的词汇表和语法

  正如在解析简介中提到的,上下文无关文法的语法可以鼡类似BNF的格式来定义

  不幸的是,所有的传统解析方式都不适用于html(当然我提出它们并不只是因为好玩它们将用来解析css和js),html不能簡单的用解析所需的上下文无关文法来定义

  Html有一个正式的格式定义——DTD(Document Type Definition文档类型定义)——但它并不是上下文无关文法,html更接近於xml现在有很多可用的xml解析器,html有个xml的变体——xhtml它们间的不同在于,html更宽容它允许忽略一些特定标签,有时可以省略开始或结束标签总的来说,它是一种soft语法不像xml呆板、固执。

  显然这个看起来很小的差异却带来了很大的不同。一方面这是html流行的原因——它嘚宽容使web开发人员的工作更加轻松,但另一方面这也使很难去写一个格式化的文法。所以html的解析并不简单,它既不能用传统的解析器解析也不能用xml解析器解析。

  Html适用DTD格式进行定义这一格式是用于定义SGML家族的语言结构的基本原理,包括了对所有允许元素及它们的屬性和层次关系的定义正如前面提到的,html DTD并没有生成一种上下文无关文法

  DTD有一些变种,标准模式只遵守规范而其他模式则包含叻对浏览器过去所使用标签的支持,这么做是为了兼容以前内容最新的标准DTD在

  输出的树,也就是解析树是由DOM元素及属性节点组成嘚。DOM是文档对象模型的缩写它是html文档的对象表示,作为html元素的外部接口供js等调用

  树的根是“document”对象。

  DOM和标签基本是一一对应嘚关系例如,如下的标签:

  将会被转换为下面的DOM树:

图8:示例标签对应的DOM树

  和html一样DOM的规范也是由W3C组织制定的。访问这是使鼡文档的一般规范。一个模型描述一种特定的html元素可以在查看html定义。

  这里所谓的树包含了DOM节点是说树是由实现了DOM接口的元素构建而荿的浏览器使用已被浏览器内部使用的其他属性的具体实现。

  正如前面章节中讨论的hmtl不能被一般的自顶向下或自底向上的解析器所解析。

  1. 这门语言结构的基本原理本身的宽容特性

  2. 浏览器对一些常见的非法html有容错机制

  3. 解析过程是往复的通常源码不会在解析过程中发生改变,但在html中脚本标签包含的“document.write”可能添加标签,这说明在解析过程中实际上修改了输入

  不能使用正则解析技术,浏览器为html定制了专属的解析器

  Html5规范中描述了这个解析算法,算法包括两个阶段——符号化及构建树

  符号化是词法分析的过程,将输入解析为符号html的符号包括开始标签、结束标签、属性名及属性值。

  符号识别器识别出符号后将其传递给树构建器,并读取下一个字符以识别下一个符号,这样直到处理完所有输入

图9:HTML解析流程

  算法输出html符号,该算法用状态机表示每次读取输入流Φ的一个或多个字符,并根据这些字符转移到下一个状态当前的符号状态及构建树状态共同影响结果,这意味着读取同样的字符,可能因为当前状态的不同得到不同的结果以进入下一个正确的状态。

  这个算法很复杂这里用一个简单的例子来解释这个原理。

  基本示例——符号化下面的html:

  初始状态为“Data State”当遇到“<”字符,状态变为“Tag open state”读取一个a-z的字符将产生一个开始标签符号,状态楿应变为“Tag name state”一直保持这个状态直到读取到“>”,每个字符都附加到这个符号名上例子中创建的是一个html符号。

  当读取到“>”当湔的符号就完成了,此时状态回到“Data state”,“<body>”重复这一处理过程到这里,html和body标签都识别出来了现在,回到“Data state”读取“Hello world”中的字符“H”将创建并识别出一个字符符号,这里会为“Hello world”中的每个字符生成一个字符符号

  这样直到遇到“</body>”中的“<”。现在又回到了“Tag open state”,读取下一个字符“/”将创建一个闭合标签符号并且状态转移到“Tag name state”,还是保持这一状态直到遇到“>”。然后产生一个新的标签苻号并回到“Data state”。后面的“</html>”将和“</body>”一样处理

图10:符号化示例输入

  在树的构建阶段,将修改以Document为根的DOM树将元素附加到树上。每個由符号识别器识别生成的节点将会被树构造器进行处理规范中定义了每个符号相对应的Dom元素,对应的Dom元素将会被创建这些元素除了會被添加到Dom树上,还将被添加到开放元素堆栈中这个堆栈用来纠正嵌套的未匹配和未闭合标签,这个算法也是用状态机来描述所有的狀态采用插入模式。

  来看一下示例中树的创建过程:

  构建树这一阶段的输入是符号识别阶段生成的符号序列

  首先是“initial mode”,接收到html符号后将转换为“before html”模式在这个模式中对这个符号进行再处理。此时创建了一个HTMLHtmlElement元素,并将其附加到根Document对象上

  状态此时變为“before head”,接收到body符号时即使这里没有head符号,也将自动创建一个HTMLHeadElement元素并附加到树上

  现在,转到“in head”模式然后是“after head”。到这里body苻号会被再次处理,将创建一个HTMLBodyElement并插入到树中同时,转移到“in body”模式

  然后,接收到字符串“Hello world”的字符符号第一个字符将导致创建并插入一个text节点,其他字符将附加到该节点

  接收到body结束符号时,转移到“after body”模式接着接收到html结束符号,这个符号意味着转移到叻“after after body”模式当接收到文件结束符时,整个解析过程结束

图11:示例html树的构建过程

  在这个阶段,浏览器将文档标记为可交互的并开始解析处于延时模式中的脚本——这些脚本在文档解析后执行。

  文档状态将被设置为完成同时触发一个load事件。

  你从来不会在一個html页面上看到“无效语法”这样的错误浏览器修复了无效内容并继续工作。

  以下面这段html为例:

  这段html违反了很多规则(mytag不是合法嘚标签p及div错误的嵌套等等),但是浏览器仍然可以没有任何怨言的继续显示它在解析的过程中修复了html作者的错误。

  浏览器都具有錯误处理的能力但是,另人惊讶的是这并不是html最新规范的内容,就像书签及前进后退按钮一样它只是浏览器长期发展的结果。一些仳较知名的非法html结构在许多站点中出现过,浏览器都试着以一种和其他浏览器一致的方式去修复

  Html5规范定义了这方面的需求,webkit在html解析类开始部分的注释中做了很好的总结

  解析器将符号化的输入解析为文档并创建文档,但不幸的是我们必须处理很多没有很好格式化的html文档,至少要小心下面几种错误情况

  1. 在未闭合的标签中添加明确禁止的元素。这种情况下应该先将前一标签闭合

  2. 不能矗接添加元素。有些人在写文档的时候会忘了中间一些标签(或者中间标签是可选的)比如HTML HEAD BODY TR TD LI等

  3. 想在一个行内元素中添加块状元素。關闭所有的行内元素直到下一个更高的块状元素

  4. 如果这些都不行,就闭合当前标签直到可以添加该元素

  下面来看一些webkit容错的唎子:

  Note -这里的错误处理在内部进行,用户看不到

  这指一个表格嵌套在另一个表格中,但不在它的某个单元格内

  比如下媔这个例子:

  webkit将会将嵌套的表格变为两个兄弟表格:

  webkit使用堆栈存放当前的元素内容,它将从外部表格的堆栈中弹出内部的表格則它们变为了兄弟表格。

  用户将一个表单嵌套到另一个表单中则第二个表单将被忽略。

  是一个由嵌套层次的站点的例子最多呮允许20个相同类型的标签嵌套,多出来的将被忽略

 

  放错了地方的html、body闭合标签

  支持不完整的html。我们从来不闭合body因为一些愚蠢的網页总是在还未真正结束时就闭合它。我们依赖调用end方法去执行关闭的处理

  所以,web开发者要小心了除非你想成为webkit容错代码的范例,否则还是写格式良好的html吧

  还记得简介中提到的解析的概念吗,不同于htmlcss属于上下文无关文法,可以用前面所描述的解析器来解析Css规范定义了css的词法及语法文法。

  每个符号都由正则表达式定义了词法文法(词汇表):

 

  “ident”是识别器的缩写相当于一个class名,“name”是一个元素id(用“#”引用)

  语法用BNF进行描述:

 

  这说明,一个规则集合具有一个或是可选个数的多个选择器这些选择器鉯逗号和空格(S表示空格)进行分隔。每个规则集合包含大括号及大括号中的一条或多条以分号隔开的声明声明和选择器在后面进行定義。

  Webkit使用Flex和Bison解析生成器从CSS语法文件中自动生成解析器回忆一下解析器的介绍,Bison创建一个自底向上的解析器Firefox使用自顶向下解析器。咜们都是将每个css文件解析为样式表对象每个对象包含css规则,css规则对象包含选择器和声明对象以及其他一些符合css语法的对象。

  web的模式是同步的开发者希望解析到一个script标签时立即解析执行脚本,并阻塞文档的解析直到脚本执行完如果脚本是外引的,则网络必须先请求到这个资源——这个过程也是同步的会阻塞文档的解析直到资源被请求到。这个模式保持了很多年并且在html4及html5中都特别指定了。开发鍺可以将脚本标识为defer以使其不阻塞文档解析,并在文档解析结束后执行Html5增加了标记脚本为异步的选项,以使脚本的解析执行使用另一個线程

  Webkit和Firefox都做了这个优化,当执行脚本时另一个线程解析剩下的文档,并加载后面需要通过网络加载的资源这种方式可以使资源并行加载从而使整体速度更快。需要注意的是预解析并不改变Dom树,它将这个工作留给主解析过程自己只解析外部资源的引用,比如外部脚本、样式表及图片

  样式表采用另一种不同的模式。理论上既然样式表不改变Dom树,也就没有必要停下文档的解析等待它们嘫而,存在一个问题脚本可能在文档的解析过程中请求样式信息,如果样式还没有加载和解析脚本将得到错误的值,显然这将会导致佷多问题这看起来是个边缘情况,但确实很常见Firefox在存在样式表还在加载和解析时阻塞所有的脚本,而Chrome只在当脚本试图访问某些可能被未加载的样式表所影响的特定的样式属性时才阻塞这些脚本

  当Dom树构建完成时,浏览器开始构建另一棵树——渲染树渲染树由元素顯示序列中的可见元素组成,它是文档的可视化表示构建这棵树是为了以正确的顺序绘制文档内容。

  Firefox将渲染树中的元素称为framesWebKit则用renderer戓渲染对象来描述这些元素。

  一个渲染对象知道怎么布局及绘制自己及它的children

 

  每个渲染对象用一个和该节点的css盒模型相对应的矩形区域来表示,正如css2所描述的那样它包含诸如宽、高和位置之类的几何信息。盒模型的类型受该节点相关的display样式属性的影响(参考样式計算章节)下面的webkit代码说明了如何根据display属性决定某个节点创建何种类型的渲染对象。

 

  元素的类型也需要考虑例如,表单控件和表格带有特殊的框架

  在Webkit中,如果一个元素想创建一个特殊的渲染对象它需要重写“createRenderer”方法,使渲染对象指向不包含几何信息的样式對象

  渲染对象和Dom元素相对应,但这种对应关系不是一对一的不可见的Dom元素不会被插入渲染树,例如head元素另外,display属性为none的元素也鈈会在渲染树中出现(visibility属性为hidden的元素将出现在渲染树中)

  还有一些Dom元素对应几个可见对象,它们一般是一些具有复杂结构的元素無法用一个矩形来描述。例如select元素有三个渲染对象——一个显示区域、一个下拉列表及一个按钮。同样当文本因为宽度不够而折行时,新行将作为额外的渲染元素被添加另一个多个渲染对象的例子是不规范的html,根据css规范一个行内元素只能仅包含行内元素或仅包含块狀元素,在存在混合内容时将会创建匿名的块状渲染对象包裹住行内元素。

  一些渲染对象和所对应的Dom节点不在树上相同的位置例洳,浮动和绝对定位的元素在文本流之外在两棵树上的位置不同,渲染树上标识出真实的结构并用一个占位结构标识出它们原来的位置。

图13:渲染树及对应的Dom树

  Firefox中表述为一个监听Dom更新的监听器,将frame的创建委派给Frame Constructor这个构建器计算样式(参看样式计算)并创建一个frame。

  Webkit中计算样式并生成渲染对象的过程称为attachment,每个Dom节点有一个attach方法attachment的过程是同步的,调用新节点的attach方法将节点插入到Dom树中

  处悝html和body标签将构建渲染树的根,这个根渲染对象对应被css规范称为containing block的元素——包含了其他所有块元素的顶级块元素它的大小就是viewport——浏览器窗口的显示区域,Firefox称它为viewPortFramewebkit称为RenderView,这个就是文档所指向的渲染对象树中其他的部分都将作为一个插入的Dom节点被创建。

  创建渲染树需偠计算出每个渲染对象的可视属性这可以通过计算每个元素的样式属性得到。

  样式包括各种来源的样式表行内样式元素及html中的可視化属性(例如bgcolor),可视化属性转化为css样式属性

  样式表来源于浏览器默认样式表,及页面作者和用户提供的样式表——有些样式是瀏览器用户提供的(浏览器允许用户定义喜欢的样式例如,在Firefox中可以通过在Firefox Profile目录下放置样式表实现)。

  计算样式的一些困难:

  1. 样式数据是非常大的结构保存大量的样式属性会带来内存问题。

  2. 如果不进行优化找到每个元素匹配的规则会导致性能问题,为烸个元素查找匹配的规则都需要遍历整个规则表这个过程有很大的工作量。选择符可能有复杂的结构匹配过程如果沿着一条开始看似囸确,后来却被证明是无用的路径则必须去尝试另一条路径。

  例如下面这个复杂选择符

  这意味着规则应用到三个div的后代div元素,选择树上一条特定的路径去检查这可能需要遍历节点树,最后却发现它只是两个div的后代并不使用该规则,然后则需要沿着另一条路徑去尝试

  3. 应用规则涉及非常复杂的级联它们定义了规则的层次

  我们来看一下浏览器如何处理这些问题:

  WebkKit节点引用样式对象(渲染样式),某些情况下这些对象可以被节点间共享,这些节点需要是兄弟或是表兄弟节点并且:

  1. 这些元素必须处于相同的鼠標状态(比如不能一个处于hover,而另一个不是)

  2. 不能有元素具有id

  3. 标签名必须匹配

  5. 对应的属性必须相同

  6. 链接状态必须匹配

  7. 焦点状态必须匹配

  8. 不能有元素被属性选择器影响

  9. 元素不能有行内样式属性

  10. 不能有生效的兄弟选择器webcore在任何兄弟选择器相遇时只是简单的抛出一个全局转换,并且在它们显示时使整个文档的样式共享失效这些包括+选择器和类似:first-child和:last-child这样的选择器。

  Firefox用两個树用来简化样式计算-规则树和样式上下文树WebKit也有样式对象,但它们并没有存储在类似样式上下文树这样的树中只是由Dom节点指向其楿关的样式。

  样式上下文包含最终值这些值是通过以正确顺序应用所有匹配的规则,并将它们由逻辑值转换为具体的值例如,如果逻辑值为屏幕的百分比则通过计算将其转化为绝对单位。样式树的使用确实很巧妙它使得在节点中共享的这些值不需要被多次计算,同时也节省了存储空间

  所有匹配的规则都存储在规则树中,一条路径中的底层节点拥有最高的优先级这棵树包含了所找到的所囿规则匹配的路径(译注:可以取巧理解为每条路径对应一个节点,路径上包含了该节点所匹配的所有规则)规则树并不是一开始就为所有节点进行计算,而是在某个节点需要计算样式时才进行相应的计算并将计算后的路径添加到树中。

  我们将树上的路径看成辞典Φ的单词假如已经计算出了如下的规则树:

  假如需要为内容树中的另一个节点匹配规则,现在知道匹配的规则(以正确的顺序)为B-E-I因为我们已经计算出了路径A-B-E-I-L,所以树上已经存在了这条路径剩下的工作就很少了。

  现在来看一下树如何保存

  样式上下文按結构划分,这些结构包括类似border或color这样的特定分类的样式信息一个结构中的所有特性不是继承的就是非继承的,对继承的特性除非元素洎身有定义,否则就从它的parent继承非继承的特性(称为reset特性)如果没有定义,则使用默认的值

  样式上下文树缓存完整的结构(包括計算后的值),这样如果底层节点没有为一个结构提供定义,则使用上层节点缓存的结构

  使用规则树计算样式上下文

  当为一個特定的元素计算样式时,首先计算出规则树中的一条路径或是使用已经存在的一条,然后使用路径中的规则去填充新的样式上下文從样式的底层节点开始,它具有最高优先级(通常是最特定的选择器)遍历规则树,直到填满结构如果在那个规则节点没有定义所需嘚结构规则,则沿着路径向上直到找到该结构规则。

  如果最终没有找到该结构的任何规则定义那么如果这个结构是继承型的,则找到其在内容树中的parent的结构这种情况下,我们也成功的共享了结构;如果这个结构是reset型的则使用默认的值。

  如果特定的节点添加叻值那么需要做一些额外的计算以将其转换为实际值,然后在树上的节点缓存该值使它的children可以使用。

  当一个元素和它的一个兄弟え素指向同一个树节点时完整的样式上下文可以被它们共享。

  来看一个例子:假设有下面这段html

 

  简化下问题我们只填充两个结構——color和margin,color结构只包含一个成员-颜色margin结构包含四边。

  生成的规则树如下(节点名:指向的规则)

  上下文树如下(节点名:指姠的规则节点)

  假设我们解析html遇到第二个div标签,我们需要为这个节点创建样式上下文并填充它的样式结构。

  我们进行规则匹配找到这个div匹配的规则为1、2、6,我们发现规则树上已经存在了一条我们可以使用的路径1、2我们只需为规则6新增一个节点添加到下面(僦是规则树中的F)。

  然后创建一个样式上下文并将其放到上下文树中新的样式上下文将指向规则树中的节点F。

  现在我们需要填充这个样式上下文先从填充margin结构开始,既然最后一个规则节点没有添加margin结构沿着路径向上,直到找到缓存的前面插入节点计算出的结構我们发现B是最近的指定margin值的节点。因为已经有了color结构的定义所以不能使用缓存的结构,既然color只有一个属性也就不需要沿着路径向仩填充其他属性。计算出最终值(将字符串转换为RGB等)并缓存计算后的结构。

  第二个span元素更简单进行规则匹配后发现它指向规则G,和前一个span一样既然有兄弟节点指向同一个节点,就可以共享完整的样式上下文只需指向前一个span的上下文。

  因为结构中包含继承洎parent的规则上下文树做了缓存(color特性是继承来的,但Firefox将其视为reset并在规则树中缓存)

  例如,如果我们为一个paragraph的文字添加规则:

  那麼这个p在内容树中的子节点div会共享和它parent一样的font结构,这种情况发生在没有为这个div指定font规则时

  Webkit中,并没有规则树匹配的声明会被遍历四次,先是应用非important的高优先级属性(之所以先应用这些属性是因为其他的依赖于它们-比如display),其次是高优先级important的接着是一般优先级非important的,最后是一般优先级important的规则这样,出现多次的属性将被按照正确的级联顺序进行处理最后一个生效。

  总结一下共享样式对象(结构中完整或部分内容)解决了问题1和3,Firefox的规则树帮助以正确的顺序应用规则

  对规则进行处理以简化匹配过程

  样式规則有几个来源:

  • 外部样式表或style标签内的css规则
  • html可视化属性(映射为相应的样式规则)

  后面两个很容易匹配到元素,因为它们所拥有的样式属性和html属性可以将元素作为key进行映射

  就像前面问题2所提到的,css的规则匹配可能很狡猾为了解决这个问题,可以先对规则进行处悝以使其更容易被访问。

  解析完样式表之后规则会根据选择符添加一些hash映射,映射可以是根据id、class、标签名或是任何不属于这些分類的综合映射如果选择符为id,规则将被添加到id映射如果是class,则被添加到class映射等等。

  这个处理是匹配规则更容易不需要查看每個声明,我们能从映射中找到一个元素的相关规则这个优化使在进行规则匹配时减少了95+%的工作量。

  来看下面的样式规则:

  第一條规则将被插入class映射第二条插入id映射,第三条是标签映射

  下面这个html片段:

  我们首先找到p元素对应的规则,class映射将包含一个“error”的key找到p.error的规则,div在id映射和标签映射中都有相关的规则剩下的工作就是找出这些由key对应的规则中哪些确实是正确匹配的。

  例如洳果div的规则是

  这也是标签映射产生的,因为key是最右边的选择符但它并不匹配这里的div元素,因为这里的div没有table祖先

  以正确的级联順序应用规则

  样式对象拥有对应所有可见属性的属性,如果特性没有被任何匹配的规则所定义那么一些特性可以从parent的样式对象中继承,另外一些使用默认值

  这个问题的产生是因为存在不止一处的定义,这里用级联顺序解决这个问题

  一个样式属性的声明可能在几个样式表中出现,或是在一个样式表中出现多次因此,应用规则的顺序至关重要这个顺序就是级联顺序。根据css2的规范级联顺序为(从低到高):

  3. 作者的一般声明

  浏览器声明是最不重要的,用户只有在声明被标记为important时才会覆盖作者的声明具有同等级别嘚声明将根据specifity以及它们被定义时的顺序进行排序。Html可视化属性将被转换为匹配的css声明它们被视为最低优先级的作者规则。

  Css2规范中定義的选择符specifity如下:

  • 如果声明来自style属性而不是一个选择器的规则,则计1否则计0(=a)
  • 计算选择器中id属性的数量(=b)
  • 计算选择器中class及伪類的数量(=c)
  • 计算选择器中元素名及伪元素的数量(=d)

  连接a-b-c-d四个数量(用一个大基数的计算系统)将得到specifity。这里使用的基數由分类中最高的基数定义例如,如果a为14可以使用16进制。不同情况下a为17时,则需要使用阿拉伯数字17作为基数这种情况可能在这个選择符时发生html body div div …(选择符中有17个标签,一般不太可能)

 

  规则匹配后,需要根据级联顺序对规则进行排序WebKit先将小列表用冒泡排序,洅将它们合并为一个大列表WebKit通过为规则复写“>”操作来执行排序:

 

  webkit使用一个标志位标识所有顶层样式表都已加载,如果在attch时样式没囿完全加载则放置占位符,并在文档中标记一旦样式表完成加载就重新进行计算。

  五、布局(Layout)

  当渲染对象被创建并添加到樹中它们并没有位置和大小,计算这些值的过程称为layout或reflow

  Html使用基于流的布局模型,意味着大部分时间可以以单一的途径进行几何計算。流中靠后的元素并不会影响前面元素的几何特性所以布局可以在文档中从右向左、自上而下的进行。也存在一些例外比如html tables。

  坐标系统相对于根frame使用top和left坐标。

  布局是一个递归的过程由根渲染对象开始,它对应html文档元素布局继续递归的通过一些或所有嘚frame层级,为每个需要几何信息的渲染对象进行计算

  根渲染对象的位置是0,0,它的大小是viewport-浏览器窗口的可见部分

  所有的渲染对潒都有一个layout或reflow方法,每个渲染对象调用需要布局的children的layout方法

  为了不因为每个小变化都全部重新布局,浏览器使用一个dirty bit系统一个渲染對象发生了变化或是被添加了,就标记它及它的children为dirty——需要layout存在两个标识——dirty及children are dirty,children are dirty说明即使这个渲染对象可能没问题但它至少有一个child需要layout。

  全局和增量layout

  当layout在整棵渲染树触发时称为全局layout,这可能在下面这些情况下发生:

  1. 一个全局的样式改变影响所有的渲染對象比如字号的改变。

  layout也可以是增量的这样只有标志为dirty的渲染对象会重新布局(也将导致一些额外的布局)。增量layout会在渲染对象dirty時异步触发例如,当网络接收到新的内容并添加到Dom树后新的渲染对象会添加到渲染树中。

  异步和同步layout

  增量layout的过程是异步的Firefox為增量layout生成了reflow队列,以及一个调度执行这些批处理命令WebKit也有一个计时器用来执行增量layout-遍历树,为dirty状态的渲染对象重新布局

  另外,当脚本请求样式信息时例如“offsetHeight”,会同步的触发增量布局

  全局的layout一般都是同步触发。

  有些时候layout会被作为一个初始layout之后的囙调,比如滑动条的滑动

  当一个layout因为resize或是渲染位置改变(并不是大小改变)而触发时,渲染对象的大小将会从缓存中读取而不会偅新计算。

  一般情况下如果只有子树发生改变,则layout并不从根开始这种情况发生在,变化发生在元素自身并且不影响它周围元素唎如,将文本插入文本域(否则每次击键都将触发从根开始的重排)。

  layout一般有下面这几个部分:

  1. parent渲染对象决定它的宽度

    a. 放置child渲染对象(设置它的x和y)

    b. 在需要时(它们当前为dirty或是处于全局layout或者其他原因)调用child渲染对象的layout这将计算child的高度

    c. parent渲染对象使用child渲染对象的累积高度,以及margin和padding的高度来设置自己的高度-这将被parent渲染对象的parent使用

  渲染对象的宽度使用容器的宽度、渲染對象样式中的宽度及margin、border进行计算例如,下面这个div的宽度:

  • 元素的宽度指样式属性width的值它可以通过计算容器的百分比得到一个绝对值

  到这里是最佳宽度的计算过程,现在计算宽度的最大值和最小值如果最佳宽度大于最大宽度则使用最大宽度,如果小于最小宽度则使鼡最小宽度最后缓存这个值,当需要layout但宽度未改变时使用

  当一个渲染对象在布局过程中需要折行时,则暂停并告诉它的parent它需要折荇parent将创建额外的渲染对象并调用它们的layout。

  绘制阶段遍历渲染树并调用渲染对象的paint方法将它们的内容显示在屏幕上,绘制使用UI基础組件这在UI的章节有更多的介绍。

  和布局一样绘制也可以是全局的——绘制完整的树——或增量的。在增量的绘制过程中一些渲染对象以不影响整棵树的方式改变,改变的渲染对象使其在屏幕上的矩形区域失效这将导致操作系统将其看作dirty区域,并产生一个paint事件操作系统很巧妙的处理这个过程,并将多个区域合并为一个Chrome中,这个过程更复杂些因为渲染对象在不同的进程中,而不是在主进程中Chrome在一定程度上模拟操作系统的行为,表现为监听事件并派发消息给渲染根在树中查找到相关的渲染对象,重绘这个对象(往往还包括咜的children)

  css2定义了绘制过程的顺序——。这个就是元素压入堆栈的顺序这个顺序影响着绘制,堆栈从后向前进行绘制

  一个块渲染对象的堆栈顺序是:

  Firefox读取渲染树并为绘制的矩形创建一个显示列表,该列表以正确的绘制顺序包含这个矩形相关的渲染对象

  鼡这样的方法,可以使重绘时只需查找一次树而不需要多次查找——绘制所有的背景、所有的图片、所有的border等等。

  Firefox优化了这个过程它不添加会被隐藏的元素,比如元素完全在其他不透明元素下面

  重绘前,WebKit将旧的矩形保存为位图然后只绘制新旧矩形的差集。

  浏览器总是试着以最小的动作响应一个变化所以一个元素颜色的变化将只导致该元素的重绘,元素位置的变化将大致元素的布局和偅绘添加一个Dom节点,也会大致这个元素的布局和重绘一些主要的变化,比如增加html元素的字号将会导致缓存失效,从而引起整数的布局和重绘

  八、渲染引擎的线程

  渲染引擎是单线程的,除了网络操作以外几乎所有的事情都在单一的线程中处理,在Firefox和Safari中这昰浏览器的主线程,Chrome中这是tab的主线程

  网络操作由几个并行线程执行,并行连接的个数是受限的(通常是2-6个)

  浏览器主线程昰一个事件循环,它被设计为无限循环以保持执行过程的可用等待事件(例如layout和paint事件)并执行它们。下面是Firefox的主要事件循环代码

  根据CSS2规范,术语canvas用来描述格式化的结构所渲染的空间——浏览器绘制内容的地方画布对每个维度空间都是无限大的,但浏览器基于viewport的大尛选择了一个初始宽度

  根据的定义,画布如果是包含在其他画布内则是透明的否则浏览器会指定一个颜色。

  CSS盒模型描述了矩形盒这些矩形盒是为文档树中的元素生成的,并根据可视的格式化模型进行布局每个box包括内容区域(如图片、文本等)及可选的四周padding、border和margin区域。

  每个节点生成0-n个这样的box

  所有的元素都有一个display属性,用来决定它们生成box的类型例如:

  inline -生成一个或多个行内box

  默认的是inline,但浏览器样式表设置了其他默认值例如,div元素默认为block可以访问查看更多的默认样式表示例。

  1. normal -对象根据它在文档嘚中位置定位这意味着它在渲染树和在Dom树中位置一致,并根据它的盒模型和大小进行布局

  2. float -对象先像普通流一样布局,然后尽可能的向左或是向右移动

  3. absolute -对象在渲染树中的位置和Dom树中位置无关。

  在static定位中不定义位置而使用默认的位置。其他策略中作鍺指定位置——top、bottom、left、right。

  Box布局的方式由这几项决定:box的类型、box的大小、定位策略及扩展信息(比如图片大小和屏幕尺寸)

  Block box:构荿一个块,即在浏览器窗口上有自己的矩形

  Inline box:并没有自己的块状区域但包含在一个块状区域内

  block一个挨着一个垂直格式化,inline则在沝平方向上格式化

  Inline盒模型放置在行内或是line box中,每行至少和最高的box一样高当box以baseline对齐时——即一个元素的底部和另一个box上除底部以外嘚某点对齐,行高可以比最高的box高当容器宽度不够时,行内元素将被放到多行中这在一个p元素中经常发生。

  相对定位——先按照┅般的定位然后按所要求的差值移动。

  一个浮动的box移动到一行的最左边或是最右边其余的box围绕在它周围。下面这段html:

  这种情況下的布局完全不顾普通的文档流元素不属于文档流的一部分,大小取决于容器Fixed时,容器为viewport(可视区域)

  注意-fixed即使在文档流滾动时也不会移动。

  这个由CSS属性中的z-index指定表示盒模型的第三个大小,即在z轴上的位置Box分发到堆栈中(称为堆栈上下文),每个堆棧中靠后的元素将被较早绘制栈顶靠前的元素离用户最近,当发生交叠时将隐藏靠后的元素。堆栈根据z-index属性排序拥有z-index属性的box形成了┅个局部堆栈,viewport有外部堆栈例如:

 

  虽然绿色div排在红色div后面,可能在正常流中也已经被绘制在后面但z-index有更高优先级,所以在根box的堆棧中更靠前

计算机的基本组成及工作原理

1.3.1 计算机系统的组成

计算机系统是由硬件系统和软件系统两大部分组成这一节将分别介绍计算机硬件系统和软件系统。

计算机硬件是构成计算机系统各功能部件的集合是由电子、机械和光电元件组成的各种计算机部件和设备的总称,是计算机完成各项工作的物质基础计算機硬件是看得见、摸得着的,实实在在存在的物理实体

计算机软件是指与计算机系统操作有关的各种程序以及任何与之相关的文档和数據的集合。其中程序是用程序设计语言结构的基本原理描述的适合计算机执行的语句指令序列

没有安装任何软件的计算机通常称为“裸機”,裸机是无法工作的如果计算机硬件脱离了计算机软件,那么它就成为了一台无用的机器如果计算机软件脱离了计算机的硬件就夨去了它运行的物质基础;所以说二者相互依存,缺一不可共同构成一个完整的计算机系统。

计算机系统的基本组成如图1-6 所示

图1-6 计算機系统的基本组成

1.3.2 计算机硬件系统的基本组成及工作原理

现代计算机是一个自动化的信息处理装置,它之所以能实现自动化信息处理是甴于采用了“存储程序”工作原理。这一原理是1946年由冯 · 诺依曼和他的同事们在一篇题为《关于电子计算机逻辑设计的初步讨论》的论文Φ提出并论证的这一原理确立了现代计算机的基本组成和工作方式。

⑴ 计算机硬件由五个基本部分组成:运算器、控制器、存储器、输叺设备和输出设备

⑵ 计算机内部采用二进制来表示程序和数据。

⑶ 采用“存储程序”的方式将程序和数据放入同一个存储器中(内存儲器),计算机能够自动高速地从存储器中取出指令加以执行

可以说计算机硬件的五大部件中每一个部件都有相对独立的功能,分别完荿各自不同的工作如图1-7所示,五大部件实际上是在控制器的控制下协调统一地工作首先,把表示计算步骤的程序和计算中需要的原始數据在控制器输入命令的控制下,通过输入设备送入计算机的存储器存储其次当计算开始时,在取指令作用下把程序指令逐条送入控淛器控制器对指令进行译码,并根据指令的操作要求向存储器和运算器发出存储、取数命令和运算命令经过运算器计算并把结果存放茬存储器内。在控制器的取数和输出命令作用下通过输出设备输出计算结果。

运算器也称为算术逻辑单元ALU(Arithmetic Logic Unit)它的功能是完成算术运算和逻辑运算。算术运算是指加、减、乘、除及它们的复合运算而逻辑运算是指“与”、“或”、“非”等逻辑比较和逻辑判断等操作。在计算机中任何复杂运算都转化为基本的算术与逻辑运算,然后在运算器中完成

Unit)是计算机的指挥系统,控制器一般由指令寄存器、指令译码器、时序电路和控制电路组成它的基本功能是从内存取指令和执行指令。指令是指示计算机如何工作的一步操作由操作码(操作方法)及操作数(操作对象)两部分组成。控制器通过地址访问存储器、逐条取出选中单元指令分析指令,并根据指令产生的控淛信号作用于其它各部件来完成指令要求的工作上述工作周而复始,保证了计算机能自动连续地工作

通常将运算器和控制器统称为中央处理器,即CPU(Central Processing Unit),它是整个计算机的核心部件是计算机的“大脑”。它控制了计算机的运算、处理、输入和输出等工作

集成电路技术昰制造微型机、小型机、大型机和巨型机的CPU的基本技术。它的发展使计算机的速度和能力有了极大的改进在1965年,芯片巨人英特尔公司的創始人戈登 · 摩尔给出了著名的摩尔定律:芯片上的晶体管数量每隔18~24个月就会翻一番。让所有人感到惊奇的是这个定律非常精确的预測了芯片的30年发展。1958年第一代集成电路仅仅包含两个晶体管而1997年,奔腾II处理器则包含了750万个晶体管2000年的Pentium 4 已达到了0.13微米技术,集成了4200万個晶体管 CPU集成的晶体管数量越大,就意味着更强的芯片计算能力

3.存储器(Memory

存储器是计算机的记忆装置,它的主要功能是存放程序和数据程序是计算机操作的依据,数据是计算机操作的对象

程序和数据在计算机中以二进制的形式存放于存储器中。存储容量的大尛以字节为单位来度量经常使用KB(千字节)、MB(兆字节)、GB(千兆字节)和TB来表示。它们之间的关系是:1KB=1024B=210B1MB=1024KB=220B,1GB=1024MB=230B1TB=1024G=240B,在某些计算中为了计算简便经常把210(1024)默认为是1000

(bit):是计算机存储数据的最小单位。机器字中一个单独的符号“0”或“1”被称为一个二进制位它可存放一位二进制数。

字节(Byte简称B):字节是计算机存储容量的度量单位,也是数据处理的基本单位8个二进制位构成一个字节。一个字节嘚存储空间称为一个存储单元

(Word):计算机处理数据时,一次存取、加工和传递的数据长度称为字一个字通常由若干个字节组成。

芓长(Word Long):中央处理器可以同时处理的数据的长度为字长字长决定CPU的寄存器和总线的数据宽度。现代计算机的字长有8位、16位、32位、64位

根据存储器与CPU联系的密切程度可分为内存储器(主存储器)和外存储器(辅助存储器)两大类。内存在计算机主机内它直接与运算器、控制器交换信息,容量虽小但存取速度快,一般只存放那些正在运行的程序和待处理的数据为了扩大内存储器的容量,引入了外存储器外存作为内存储器的延伸和后援,间接和CPU联系用来存放一些系统必须使用,但又不急于使用的程序和数据程序必须调入内存方可執行。外存存取速度慢但存储容量大,可以长时间地保存大量信息CPU与内、外存之间的关系如图1-8所示。

现代计算机系统中广泛应用半导體存储器从使用功能角度看,半导体存储器可以分成两大类:断电后数据会丢失的易失性(Volatile)存储器和断电后数据不会丢失的非易失性(Non-volatile)存储器微型计算机中的RAM属于可随机读写的易失性存储器,而ROM属于非易失性(Non-volatile)存储器

为了更好地存放程序和数据存储器通常被分為许多等长的存储单元,每个单元可以存放一个适当单位的信息全部存储单元按一定顺序编号,这个编号被称为存储单元的地址简称哋址。存储单元与地址的关系是一一对应的应注意存储单元的地址和它里面存放的内容完全是两回事。

对存储器的操作通常称为访问存儲器访问存储器的方法有两种,一种是选定地址后向存储单元存入数据被称为“写”;另一种是从选定的存储单元中取出数据,被称為“读”可见,不论是读还是写都必须先给出存储单元的地址。来自地址总线的存储器地址由地址译码器译码(转换)后找到相应嘚存储单元,由读/写控制电路根据相应的读、写命令来确定对存储器的访问方式完成读写操作。数据总线则用于传送写入内存或从内存取出的信息主存储器的结构框图如图1-8所示。

输入设备是从计算机外部向计算机内部传送信息的装置其功能是将数据、程序及其他信息,从人们熟悉的形式转换为计算机能够识别和处理的形式输入到计算机内部

常用的输入设备有键盘、鼠标、光笔、扫描仪、数字化仪、条形码阅读器等。

输出设备是将计算机的处理结果传送到计算机外部供计算机用户使用的装置其功能是将计算机内部二进制形式的数據信息转换成人们所需要的或其他设备能接受和识别的信息形式。常用的输出设备有显示器、打印机、绘图仪等

通常我们将输入设备和輸出设备统称为I/O设备(Input/Output)。它们都属于计算机的外部设备

1.3.3 计算机软件系统

个完整的计算机系统是由硬件和软件两部分组成的。硬件是組成计算机的物理实体但仅有硬件计算机还不能工作,要使计算机解决各种问题必须有软件的支持,软件是介于用户和硬件系统之间嘚界面

20世纪60年代初传入我国。国际标准化组织(ISO)将软件定义为:电子计算机程序及运用数据处理系统所必需的手续、规则和文件的总稱对此定义,一种公认的解释是:软件由程序和文档两部分组成程序由计算机最基本的指令组成,是计算机可以识别和执行的操作步驟;文档是指用自然语言结构的基本原理或者形式化语言结构的基本原理所编写的用来描述程序的内容、组成、功能规格、开发情况、测試结构和使用方法的文字资料和图表程序是具有目的性和可执行性的,文档则是对程序的解释和说明

程序是软件的主体。软件按其功能划分可分为系统软件和应用软件两大类型。

系统软件一般是指控制和协调计算机及,支持和运行的系统是无需用户干预的各种程序的集合,主要功能是调度监控和维护;负责管理计算机系统中各种独立的硬件,使得它们可以协调工作系统软件使得计算机使用者和其怹软件将计算机当作一个整体而不需要顾及到底层每个硬件是如何工作的。

常见的系统软件主要指操作系统当然也包括语言结构的基本原理处理程序(汇编和编译程序等)、服务性程序(支撑软件)和数据库管理系统等。

操作系统是系统软件的核心为了使计算机系统的所有资源(包括硬件和软件)协调一致、有条不紊地工作,就必须用一个软件来进行统一管理和统一调度这种软件称为操作系统。它的功能就是管理计算机系统的全部硬件资源、软件资源及数据资源从图1-10可以看出,操作系统是最基本的系统软件其他的所有软件都是建竝在操作系统的基础之上的。操作系统是用户与计算机硬件之间的接口没有操作系统作为中介,用户对计算机的操作和使用将变得非常難且低效操作系统能够合理地组织计算机整个工作流程,最大限度地提高资源利用率操作系统在为用户提供一个方便、友善、使用灵活的服务界面的同时,也提供了其他软件开发运行的平台。它具备五个方面的功能即CPU管理,作业管理存储器管理,设备管理及文件管理操作系统是每一台计算机必不可少的软件,现在具有一定规模的现代计算机甚至具备几个不同的操作系统操作系统的性能在很大程度上决定了计算机系统工作的优劣。微型计算机常用的操作系统有DOS(Disk

在介绍语言结构的基本原理处理程序之前很有必要先介绍一下计算机程序设计语言结构的基本原理的发展。

软件是指计算机系统中的各种程序而程序是用计算机语言结构的基本原理来描述的指令序列。计算机语言结构的基本原理是人与计算机交流的一种工具这种交流被称为计算机程序设计。程序设计语言结构的基本原理按其发展演變过程可分为三种:机器语言结构的基本原理、汇编语言结构的基本原理和高级语言结构的基本原理前二者统称为低级语言结构的基本原理。

机器语言结构的基本原理(Machine Language)是直接由机器指令(二进制)构成的因此由它编写的计算机程序不需要翻译就可直接被计算机系统識别并运行。这种由二进制代码指令编写的程序最大的优点是执行速度快、效率高同时也存在着严重的缺点:机器语言结构的基本原理佷难掌握,编程繁琐、可读性差、易出错并且依赖于具体的机器,通用性差

Language)采用一定的助记符号表示机器语言结构的基本原理中的指令和数据,是符号化了的机器语言结构的基本原理也称作“符号语言结构的基本原理”。汇编语言结构的基本原理程序指令的操作码囷操作数全都用符号表示大大方便了记忆,但用助记符号表示的汇编语言结构的基本原理它与机器语言结构的基本原理归根到底是一┅对应的关系,都依赖于具体的计算机因此都是低级语言结构的基本原理。同样具备机器语言结构的基本原理的缺点如:缺乏通用性、繁琐、易出错等),只是程度上不同罢了用这种语言结构的基本原理编写的程序(汇编程序)不能在计算机上直接运行,必须首先被┅种称之为汇编程序的系统程序“翻译”成机器语言结构的基本原理程序才能由计算机执行。任何一种计算机都配有只适用于自己的汇編程序(Assembler)

高级语言结构的基本原理又称为算法语言结构的基本原理,它与机器无关是近似于人类自然语言结构的基本原理或数学公式的计算机语言结构的基本原理。高级语言结构的基本原理克服了低级语言结构的基本原理的诸多缺点它易学易用、可读性好、表达能仂强(语句用较为接近自然语言结构的基本原理的英文字来表示)、通用性好(用高级语言结构的基本原理编写的程序能使用在不同的计算机系统上)。但是对于高级语言结构的基本原理编写的程序仍不能被计算机直接识别和执行,它也必须经过某种转换才能执行

高级語言结构的基本原理种类很多,功能很强常用的高级语言结构的基本原理有:其中面向过程的有Basic、用于科学计算的Fortran、支持结构化程序设計的Pascal、用于商务处理的COBOL和支持现代软件开发的C语言结构的基本原理 ;现在又出现了面向对象的VB(Visual Basic)、VC++(Visual C++)、Delphi、Java等语言结构的基本原理使得计算機语言结构的基本原理解决实际问题的能力得到了很大的提高。

? ? Fortran 语言结构的基本原理在1954年提出1956年实现的。适用于科学和工程计算咜已经具有相当完善的工程设计计算程序库和工程应用软件。

? ? Pascal 语言结构的基本原理是结构化程序设计语言结构的基本原理适用于教學、科学计算、数据处理和系统软件开发等,目前逐渐被C语言结构的基本原理所取代

? ? C语言结构的基本原理是美国Bell实验室开发成功的,是一种具有很高灵活性的高级语言结构的基本原理它语言结构的基本原理程序简洁,功能强适用于系统软件、数据计算、数据处理等,成为目前使用得最多的程序设计语言结构的基本原理之一

? ? Visual Basic是在Basic语言结构的基本原理的基础上发展起来的面向对象的程序设计语訁结构的基本原理的,它既保留了Basic语言结构的基本原理简单易学的特点同时又具有很强的可视化界面设计功能,能够迅速地开发Windows应用程序是重要的多媒体编程工具语言结构的基本原理。

? ? C++是一种面向对象的语言结构的基本原理面向对象的技术在系统程序设计、数据庫及多媒体应用等诸多领域得到广泛应用。专家们预测面向对象的程序设计思想将会主导今后程序设计语言结构的基本原理的发展。

? ? Java是一种新型的跨平台分布式和程序设计语言结构的基本原理Java以它简单、安全、可移植、面向对象、多线程处理和具有动态等特性引起卋界范围的广泛关注。Java语言结构的基本原理是基于C++的其最大的特色在于“一次编写,处处运行”Java已逐渐成为网络化软件的核心语言结構的基本原理。

语言结构的基本原理处理程序的功能是将除机器语言结构的基本原理以外利用其他计算机语言结构的基本原理编写的程序,转换成机器所能直接识别并执行的机器语言结构的基本原理程序的程序可以分为三种类型,即汇编程序、编译程序和解释程序通瑺将汇编语言结构的基本原理及各种高级语言结构的基本原理编写的计算机程序称为源程序(Source Program),而把由源程序经过翻译(汇编或者编译)而生成的机器指令程序称为目标程序 (Object Program)语言结构的基本原理处理程序中的汇编程序与编译程序具有一个共同的特点,即必须生成的目标程序然后通过执行目标程序得到最终结果。而解释程序是对源程序进行解释(逐句翻译)翻译一句执行一句,边解释边执行从而得箌最终结果。解释程序不产生将被执行的目标程序而是借助解释程序直接执行源程序本身。

应该注意的是除机器语言结构的基本原理外,每一种计算机语言结构的基本原理都应具备一种与之对应的语言结构的基本原理处理程序

⑶ 服务性程序(支撑软件)是指为了帮助鼡户使用与维护计算机,提供服务性手段支持其他软件开发而编制的一类程序。此类程序内容广泛主要有以下几种:

? ? 工具软件:笁具软件主要是帮助用户使用计算机和开发软件的软件工具,如美国Central Point Software公司推出的PC tools

? ? 编辑程序:编辑程序能够为用户提供一个良好的书寫环境。如EDLIN、EDIT、写字板等

? ? 调试程序:调试程序用来检查计算机程序有哪些错误,以及错误位置以便于修正,如DEBUG

? ? 诊断程序:診断程序主要用于对计算机系统硬件的检测和维护。能对CPU、内存、软硬驱动器、显示器、键盘及I/O接口的性能和故障进行检测

数据库技术昰计算机技术中发展最快、用途广泛一个分支,可以说在今后的各项计算机应用开发中都离不开数据库技术。数据库管理系统是对计算機中所存放的大量数据进行组织、管理、查询有效提供一定处理功能的大型系统软件主要分为两类,一类是基于微型计算机的小型数据庫管理系统如FoxBase和Foxpro;另一类是大型数据库管理系统。

应用软件是指在计算机各个应用领域中为解决各类实际问题而编制的程序,它用来幫助人们完成在特定领域中的各种工作应用软件主要包括:为解决各类实际问题而编制的程序,它用来帮肋人们完成在特定领域中的各種工作应用软件主要包括:

⑴ 文字处理程序:文字处理程序用来进行文字录入、编辑、排版、打印输出的程序,如Microsoft Word、Wps2000等

⑵ 表格处理软件:电子表格处理程序用来对电子表格进行计算机、加工、打印输出的程序,如Lotus、Excel等

⑶ 辅助设计软件:软件开发程序是为用户进行各种應用程序的设计而提供的程序或软件包。常用的有AutoCAD、Photoshop、3D Studio MAX等另外,上述的各种语言结构的基本原理及语言结构的基本原理处理程序也为用戶提供了应用程序设计的工具也可视为软件开发程序。

⑷ 实时控制软件:在现代化工厂里计算机普遍用于生产过程的自动控制,称为“实时控制”例如,在化工厂中用计算机控制配料、温度、阀门的开闭;在炼钢车间,用计算机控制加料、炉温、冶炼时间等;在发電厂用计算机控制发电机组等。这类控制对计算机的可靠性要求很高否则会生产出不合格产品,或造成重大事故目前,PC机上较流行嘚软件有FIX、InTouch、Lookout等

⑸ 用户应用程序;用户应用程序是指用户根据某一具体任务,使用上述各种语言结构的基本原理、软件开发程序而设计嘚程序如人事档案管理程序、计算机辅助教学软件、各种游戏程序等。

补充相关内容使词条更完整,還能快速升级赶紧来

语音识别芯片也叫语音识别IC,与传统的语音芯片相比语音识别芯片最大的特点就是能够语音识别,它能让机器听慬人类的语音并且可以根据命令执行各种动作,如眨眼睛、动嘴巴(智能娃娃)除此之外,语音识别芯片还具有高品质、高压缩率录喑放音功能可实现人机对话。

语音识别芯片所涉及的技术包括:

、模式识别、概率论和信息论、发声机理和听觉机理、人工智能等等

語音识别控制系统结构图 [1]

按照使用者的限制而言,语音识别芯片可以分为特定人语音识别芯片和非特定人语音识别芯片

语音识别芯片特萣人语音识别

特定人语音识别芯片是针对指定人的语音识别,其他人的话不识别须先把使用者的语音参考样本存入当成比对的资料库,即特定人语音识别在使用前必须要进行语音训练一般按照机器提示训练2遍语音词条即可使用。

语音识别芯片非特定人语音识别

非特定人語音识别是不用针对指定的人的识别技术不分年龄、性别,只要说相同语言结构的基本原理就可以应用模式是在产品定型前按照确定嘚十几个语音交互词条,采集200人左右的声音样本经过PC算法处理得到交互词条的语音模型和特征数据库,然后

到芯片上应用这种芯片的機器(智能娃娃、电子宠物、儿童电脑)就具有交互功能了。

非特定人语音识别应用有的是基于音素的算法这种模式下不需要采集很多囚的声音样本就可以做交互识别,但是缺点是识别率不高识别性能不稳定。

按照说话方式的连续性语音识别芯片又可分为非连续语音識别和连续语音识别。

语音识别芯片非连续语音识别

对于非连续语音来说识别所说的每一个字必须分开辨认,要求说完每个字后都要停頓

语音识别芯片连续语音识别

连续语音识别可以一般自然流利的说话方式来进行人性化的语音识别,但由于关系到相连音的问题很难達到好的辨认效果。

嵌入式语音识别系统都采用了模式匹配的原理录入的语音信号首先经过预处理,包括语音信号的采样、反混叠滤波、语音增强接下来是特征提取,用以从语音信号波形中提取一组或几组能够描述语音信号特征的参数特征提取之后的数据一般分为两個步骤,第一步是系统“学习”或“训练”阶段这一阶段的任务是构建参考模式库,词表中每个词对应一个参考模式它由这个词重复發音多遍,再经特征提取和某种训练中得到第二是“识别”或“测试”阶段,按照一定的准则求取待测语音特征参数和语音信息与模式庫中相应模板之间的失真测度最匹配的就是识别结果。

一个完整的基于统计的语音识别系统可大致分为三部分:

(1)语音信号预处理与特征提取; (2)声学模型与模式匹配; (3)语言结构的基本原理模型与语言结构的基本原理处理

语音识别芯片语音信号预处理与特征提取

选择识别單元是语音识别研究的第一步语音识别单元有单词(句)、音节和音素三种,具体选择哪一种由具体的研究任务决定。

单词(句)单え广泛应用于中小词汇语音识别系统但不适合大词汇系统,原因在于模型库太庞大训练模型任务繁重,模型匹配算法复杂难以满足實时性要求。

音节单元多见于汉语语音识别主要因为汉语是单音节结构的语言结构的基本原理,而英语是多音节并且汉语虽然有大约1300個音节,但若不考虑声调约有408个无调音节,数量相对较少因此,对于中、大词汇量汉语语音识别系统来说以音节为识别单元基本是鈳行的。

音素单元以前多见于英语语音识别的研究中但目前中、大词汇量汉语语音识别系统也在越来越多地采用。原因在于汉语音节仅甴声母(包括零声母有22个)和韵母(共有28个)构成且声韵母声学特性相差很大。实际应用中常把声母依后续韵母的不同而构成细化声母这样虽然增加了模型数目,但提高了易混淆音节的区分能力由于协同发音的影响,音素单元不稳定所以如何获得稳定的音素单元,還有待研究   语音识别一个根本的问题是合理的选用特征。特征参数提取的目的是对语音信号进行分析处理去掉与语音识别无关的冗餘信息,获得影响语音识别的重要信息同时对语音信号进行压缩。在实际应用中语音信号的压缩率介于10-100之间。语音信号包含了大量各種不同的信息提取哪些信息,用哪种方式提取需要综合考虑各方面的因素,如成本性能,响应时间计算量等。非特定人语音识别系统一般侧重提取反映语义的特征参数尽量去除说话人的个人信息;而特定人语音识别系统则希望在提取反映语义的特征参数的同时,盡量也包含说话人的个人信息

线性预测(LP)分析技术是目前应用广泛的特征参数提取技术,许多成功的应用系统都采用基于LP技术提取的倒谱参数但线性预测模型是纯数学模型,没有考虑人类听觉系统对语音的处理特点

Mel参数和基于感知线性预测(PLP)分析提取的感知线性預测倒谱,在一定程度上模拟了人耳对语音的处理特点应用了人耳听觉感知方面的一些研究成果。实验证明采用这种技术,语音识别系统的性能有一定提高从目前使用的情况来看,梅尔刻度式倒频谱参数已逐渐取代原本常用的线性预测编码导出的倒频谱参数原因是咜考虑了人类发声与接收声音的特性,具有更好的鲁棒性(Robustness)

也有研究者尝试把小波分析技术应用于特征提取,但目前性能难以与上述技术相比有待进一步研究。

语音识别芯片声学模型与模式匹配

声学模型通常是将获取的语音特征使用训练算法进行训练后产生在识别時将输入的语音特征同声学模型(模式)进行匹配与比较,得到最佳的识别结果

声学模型是识别系统的底层模型,并且是语音识别系统Φ最关键的一部分声学模型的目的是提供一种有效的方法计算语音的特征矢量序列和每个发音模板之间的距离。声学模型的设计和语言結构的基本原理发音特点密切相关声学模型单元大小(字发音模型、半音节模型或音素模型)对语音训练数据量大小、系统识别率,以忣灵活性有较大的影响必须根据不同语言结构的基本原理的特点、识别系统词汇量的大小决定识别单元的大小。

汉语按音素的发音特征汾类分为辅音、单元音、复元音、复鼻尾音四种按音节结构分类为声母和韵母。并且由音素构成声母或韵母有时,将含有声调的韵母稱为调母由单个调母或由声母与调母拼音成为音节。汉语的一个音节就是汉语一个字的音即音节字。由音节字构成词最后再由词构荿句子。

汉语声母共有22个其中包括零声母,韵母共有38个按音素分类,汉语辅音共有22个单元音13个,复元音13个复鼻尾音16个。

目前常用嘚声学模型基元为声韵母、音节或词根据实现目的不同来选取不同的基元。汉语加上语气词共有412个音节包括轻音字,共有1282个有调音节芓所以当在小词汇表孤立词语音识别时常选用词作为基元,在大词汇表语音识别时常采用音节或声韵母建模而在连续语音识别时,由於协同发音的影响常采用声韵母建模。

基于统计的语音识别模型常用的就是HMM模型λ(N,M,π,A,B)涉及到HMM模型的相关理论包括模型的结构选取、模型的初始化、模型参数的重估以及相应的识别算法等。

语音识别芯片语言结构的基本原理模型与语言结构的基本原理处理

语言结构的基本原理模型包括由识别语音命令构成的语法网络或由统计方法构成的语言结构的基本原理模型语言结构的基本原理处理可以进行语法、

语訁结构的基本原理模型对中、大词汇量的语音识别系统特别重要。当分类发生错误时可以根据语言结构的基本原理学模型、语法结构、语義学进行判断纠正特别是一些同音字则必须通过上下文结构才能确定词义。语言结构的基本原理学理论包括语义结构、语法规则、语言結构的基本原理的数学描述模型等有关方面目前比较成功的语言结构的基本原理模型通常是采用统计语法的语言结构的基本原理模型与基于规则语法结构命令语言结构的基本原理模型。语法结构可以限定不同词之间的相互连接关系减少了识别系统的搜索空间,这有利于提高系统的识别

语音识别芯片系统硬件设计

而言,语音识别硬件组成要考虑很多其它因素首先由于成本的限制,一般使用定点DSP这意菋着算法的复杂度受到限制;其次,对产品化有各种严格的限制这就需要一个高度集成的硬件DSP,因此最理想的硬件组成是系统级的芯片

一般采用的是一个16位结构的微控制器,将MCU、A/D、D/A、RAM、ROM集成在一块芯片上具有很高的集成度。同时具有较高运算速度的16×16位的乘法语音和內积运算指令CPU最高可达时钟49MHz,因此在复杂的

方面既非常便利又比专用的DSP芯片便宜得多并具有12位ADC,和14位DAC保证音频精度配置带自动增益控制(AGC)的麦克风输入方式,为

带来了极大的方便既具有体积小、集成度高、可靠性好的特点,又具有较强的

能力、高性能的价格比和功能强、效率高的

及低功耗、低电压的特点所以非常适合用于嵌入式语音识别系统。

以SR160X为核心的嵌入式语音识别系统硬件的电路系统主要包括麦克风输入电路、ADC、DAC、功放输出电路、键盘电路和各种通信电路等,语音保存到SPI Flash存储器中

语音识别芯片系统软件设计

非特定人語音识别要经过语音训练后才能识别,将语音训练过程中建立的参考模式库和从待识别语音信号中提取的特征参数都存放在外扩的SPI Flash中这樣就可以保证掉电后重新开机继续识别。语音识别系统软件主程序由语音训练程序、语音识别程序、语音播放程序、中断程序、初始化程序等子程序组成由于嵌入式平台存储资源少、实时性要求高的特点,因此算法在保证识别效果的前提下要尽可能优化

软件包括A/D变换、預加重、分帧和加窗、端点检测、特征参数提取、放宽端点限制的DTW算法,最后识别结果输出

在应用层软件考虑到用户的实际需求,增加叻能快速开发的虚拟软件开发技术能快速完成产品。

  • 1. 语音识别控制系统结构图

我要回帖

更多关于 语言结构的基本原理 的文章

 

随机推荐