ECM
ECM
总版主
总版主
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:1904亚博国际平台老虎机官网:0

开发一款浏览器内核需要学习哪些方面的知识?

楼主#
更多 发布于:2016-05-02 08:43
恭喜你选了一个好题目。你横跨了网页开发,网络,编译原理,图形,网页开发等几个方面。
网页开发:你要知道inline与block有什么不同,什么是box model,ie是怎么实现的,标准的是怎么样的。
网络方面:浏览器会使用URL,表单提交,下载,DNS等一系列知识,深一些的比如说在chrome下面输入chrome://dns,看看什么叫 prefetch DNS,浅一点至少要知道怎么实现表单提交,表单提交分那些格式。在网络那一层要怎么拼。
编译原理:简单的是状态机,具体的是CSS的解析,Javascript的解析。其实光HTML,CSS的解析就够做一个毕设的了,据一个简单的例子,浏览器是边下载边解析,边显示的,这个地方就有不少的坑等着你,光拿一个开源的xml解析器可不行,html的解析中还有图文混排等功能,整个地方又是无数的坑。 就不要说javascript的引擎了,龙书中写的只是一小部分,里面还牵涉到什么JIT等一大堆东西。
图形:硬件加速,你在chrome浏览器中地址栏中输入 chrome://gpu ,里面出现频率最高的就是Hardware accelerated
如果你真要做,准备把所有的时间放在chromium与webkit两个网站上吧,但是就算这样,里面有很多东西也不会说,比如说边下载边解析,这张东西在他们看来太简单了,里面根本就没有文档。URL的转义也是。看标准是一回事,但是有些东西根本在RFC中不会说,比如说URL的长度,整个就没有标准,但是通常浏览器都会是2048以上。
如边疆所说,怎么简化怎么来吧,比如说做个WAP1.0的浏览器,这个木有javascript,木有css,就是URL转义,wap标签显示,表单的提交。



浏览器的两个关键部分,布局引擎和JavaScript解释器。


布局引擎就是我们常说的浏览器的内核,主要处理HTML和CSS。简单的说,就是他决定了什么东西该在什么地方怎么样显示。对于网页这种视觉工程来说,布局引擎的重要程度不言而喻。


对于布局引擎的难点,大概有这些方面。


对标准的支持和扩展: 有一些标准的内容可能会难以实现,或者会带来一些安全的问题,所以各大浏览器对于标准都会有一些的裁剪,而另外又有一些拓展。


布局性能: 布局引擎的性能,包括内存、CPU等指标,能够直接影响用户的体验。简单来说就是显示快不快,占用内存多不多。


其他: 类型稳定性、可拓展性这样的一些其他类型软件共有的特点。


JavaScript解释器本来应该是浏览器内核的一部分,但是现在前端大量对JavaScript的应用,和浏览器厂商对这个部分的重视,开始分离出来了。既然拿出来了,JavaScript解释器的性能,包括时间性能、内存性能这些因素就很重要了,需要各种优化编译过程,优化生成代码,优化指令的工作。


其他的一些难点,就是一些软件上通用的东西,如何挖掘用户需求,如何让用户使用得更满意,比如单窗口向多标签的转变,快速拨号,鼠标手势这些功能。


然后就是一个好看的界面。




找不到资料是因为你不会找,找的方向不对,用的关键字不对,用的搜索引擎不对,以及用的语言不对。下面是我觉得有价值的资料:另外注意现代浏览器渲染引擎结构早就不是为了 HTML 1.0 设计了,支持的语法不是简单的 SGML,还要支持 CSS 和 JavaScript 等许多其他技术。所以你如果只想支持 HTML 1.0 的话现在的渲染引擎结构会过于复杂了,至于怎么做简化得自己摸着石头过河。



首先,毫无疑问,浏览器是个非常复杂的系统。但是任何复杂软件系统都可以通过层层抽象来简化设计,这个也就是我们平常熟悉的自顶向下的设计方式。

那么我们首先就要对浏览器进行拆解。现在的浏览器都有一个叫做浏览器内核的关键部分(也称作排版引擎),而这个部分相对于浏览器本身来说就是一个黑箱,提供接口,给出结果。另外对现代浏览器来说,书签管理等功能则独立于排版引擎而存在。那么你在做的时候,重点也就在排版引擎。

那排版引擎主要做什么功能呢?简单讲就是根据URL获取资源的字节流,然后根据字节流和资源类型交给相关的解析器进行处理。这个时候需要考虑我们到底需要处理几种资源,各种资源如何处理。所谓的资源处理就是将无结构的字节流变成结构化数据。因为计算机能够处理是结构化数据。拿到结构化数据,便可以根据结构化数据继续处理。

那我们先看URL获取的这个部分。你可以通过给内核模块封装一个调用接口,从浏览外壳传递URL字符串到内核接口,然后根据URI的相关标准(http://www.ietf.org/rfc/rfc3986.txt)来处理就好了。因为这里面涉及各种协议,比如file协议,比如http/https协议,你可能还需要封装一个自己的协议,用来获取内核自带的一些资源路径,比如默认的404页面。

处理好URI之后,你就可以根据URI的结构,交给相关网络模块来处理。我在做的时候,直接扔给了libcurl。但是libcurl在iOS上面,不是最好的实现方法,这个时候你可以继续抽象,提供统一的网络接口,对接操作系统提供的网络相关API。

网络模块的主要任务就是抓取字节流,抓取回来字节流之后,这个时候你可以直接处理,但是很容易阻塞。所以你可以去实现一个缓存机制,把抓取到的字节流缓存在本地,形成一个资源池。这个地方的实现我没有具体研究过,原谅我直接使用了静态变量来做……

你把资源抓回来了,你就需要看这个这个资源的类型,是图像的,你可以放在那里等着回头用的之后直接调取,是HTML、CSS或者脚本文件,你可以首先判断文件类型,这个一般根据网络请求的Header中的content-type来决定。
<img src="https://pic3.zhimg.com/0153daf9b648c3b6161356b1b5413ff6_b.jpg" data-rawwidth="1332" data-rawheight="476" class="origin_image zh-lightbox-thumb" width="1332" data-original="https://pic3.zhimg.com/0153daf9b648c3b6161356b1b5413ff6_r.jpg">

图片:0153daf9b648c3b6161356b1b5413ff6_b.jpg


除了判定资源的类型以外,你还需要判断文件的编码格式,是UTF-8呢,还是GB2312呢?这个有多种方法,包括解析Meta标签,或者采取《HTML5规范》中给出的算法来进行判定。参考:
2 Common infrastructure
8 The HTML syntax

那么你现在拿到HTML的源代码了,又知道源代码的编码格式了,那就处理呗。不过为了更好的开发,一般会将HTML的编码转换成UTF-8,反正《HTML5规范》中是这么写的(我只是粗略的读了,可能是我理解错了?)。正如前面的答案给出的,HTML解析就是一个自动机模型,虽然是这么说,但是写起来还是很不容易的。《HTML5规范》中有详细的算法:8 The HTML syntax
<img src="https://pic4.zhimg.com/02a1b6bef739543aa4f4792c698595c7_b.jpg" data-rawwidth="766" data-rawheight="862" class="origin_image zh-lightbox-thumb" width="766" data-original="https://pic4.zhimg.com/02a1b6bef739543aa4f4792c698595c7_r.jpg">

图片:02a1b6bef739543aa4f4792c698595c7_b.jpg


貌似总共有大概232个判断条件?反正我尝试写了一个之后,果断放弃了,而是采用了 google/gumbo-parser · GitHub 。所以如果你感兴趣HTML的解析,可以参考Google的实现,自己写一个也是可以的,只不过要耐心点。Google Gumbo本身给你实现一个类似DOM Tree的数据结构,但是如果自己调用的话貌似有些问题,因为你需要首先清楚他们的数据结构。

补充点不相关的内容:如果你想看Google Gumbo的代码,别去直接看代码了,用doxygen,顺便打开自动生成UML的功能,写论文都靠它了。

DOM Tree是HTML的结构化依托的数据结构,HTML其实可以表示成多种数据结构,但是《HTML 5规范》中直接采用了DOM Tree,或许由于已经成为事实上的标准了。但是,我们都知道《HTML 5规范》并非W3C嫡出……(扯远了)

生成DOM Tree,其实规范中也是有详细算法描述的,参见 8 The HTML syntax 。简单描述就是采用一个栈结构。HTML的解析需要考虑各种不规范的情况……什么嵌套结构有错,标签没有正确闭合等等。好在规范都给出了算法。

DOM Tree也是网页的对外接口。CSS的样式化,JavaScript对于HTML文件的操作都是操作DOM Tree。

至于CSS,看标准呗。Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification 标准中直接给出了CSS的语言描述,可以采用YACC/LEX直接生成。但是我卡在这里了,后面的也就都没有做,只是看了下如何实现的。

至于JavaScript,我都还不会写JavaScript,就不涉及了。不过你可以调用V8嘛!

你获取了DOM结构和CSS的结构,就可以根据CSS的规则,按照CSS的选择器遍历DOM Tree找到相关节点,然后把样式信息写过去。这个时候,CSS是有三层的,一层是浏览器给各类标签定义的默认样式,一般也是用CSS来描述的,一种是网页作者提供的CSS样式,一种是用户定义的样式。这个时候根据优先级,融合这三种CSS,然后对DOM Tree进行样式化。样式话无非就是一个遍历的过程而已。

经过样式化之后,你会得到一个经过样式话的DOM Tree,也就是各个DOM节点带了这个节点的样式信息。这个时候就开始进行布局计算了。布局计算,说白了就是从DOM Tree构建一个子树,我们称为Rendering Tree。Rendering Tree的各个节点都是将来要在屏幕上画出来的,因此一般只涉及里面的内容。这个就是渲染过程的开始部分了,所有隐藏的元素其实都是不会进入到Rendering Tree的,例如具有CSS的display:none属性的,都是不会显示的,自然也就无法进入Rendering Tree。对于渲染,可以去读如下的五篇文章,讲的非常好:
Rendering:
Very useful series of posts by Dave Hyatt:
WebCore Rendering I – The Basics
WebCore Rendering II – Blocks and Inlines
WebCore Rendering III – Layout Basics
WebCore Rendering IV – Absolute/Fixed and Relative Positioning
WebCore Rendering V – Floats
Render Layers and The Rendering paths – “WebKit Rendering Basics” section explains it very well.

拿到Rendering Tree之后,就是渲染了,这个时候就可以调用操作系统提供的各种API绘制文字、图片和视频等。各种Form空间就可以绑定到原生控件。然后显示出来。还记得刚开始翻WebKit代码时,就看到貌似采用了一个NSScorllView作为画布,进行绘制。

整个浏览器内核的工作原理也就是这些,说起来容易,写起来,则需要各种考量。自己写一个,不一定能写出多少东西,但是整个研究过程,会学习到很多设计模式的精髓什么的。虽然我的毕设混过去了,但是我准备再好好重构重写这个内核,真的很有趣。(自立Flag)

你做的是浏览器内核,那么最好的参考材料其实是W3C出的各种规范,各种RFC以及现有的浏览器内核的开源实现。印象最深的一句话就是RFC和具体实现其实是相辅相成,互相描述的。

另外,排版引擎的功能不止在这里,写iOS的时候,意识到其实窗口管理器喝各种UI本质上和HTML的排版是类似的,其本质也是利用各种数据结构来记录处理各UI控件之间的关系。

总之,计算机的各层抽象隐藏了很多细节,但是往往这些细节都是优美的,我们看到的往往是水面上的冰山。附上一些做毕设的时候的研究资料,供参考(原谅我直接从论文文献拷贝出来了):

  1. Let's build a browser engine! Part 1: Getting started.
  2. 朱永盛. WebKit 技术内幕 [M]. 北京 : 电子工业出版社, 2014.
  3. GARSIEL T, IRISH P. How Browsers Work: Behind the scenes of modern webbrowsers[EB/OL]. [2014-08-28].How Browsers Work: Behind the scenes of modern web browsers.



做一个毕业设计的话, 推荐看一下j2me lwuit 的html component. ?代码实现比较简单, 符合你只想实现html 1.0 的要求。 你想用c/c++ 重新实现一遍也比较简单, javascript 你想要实现一个效率不高的解释器,不整JIT 什么的没那么复杂。要知道有人在j2me 平台也实现了一个javascript 解释器的,

Links:
Lwuit: Subversion
HTMLComponent
minijoe -
?
?
?Minimal Javascript Object Environement for J2ME


不要嫌这个实现太简单,太小儿科。 也是支持html4.0 和css 1.0的。 正因为简单才比较好理解。 j2me 平台基本上没什么前途了, 但是因为它的memory 限制, 有些idea 和implementation 对其他平台还是有借鉴价值的。

学习编程最好的方法是Read the fxxking code。 但我的建议要从简单直接的code 读起, 一上来就整webkit, gecko, V8, TraceMonkey, 很难找到对自己直接有用的代码, 对培养自信也没好处。






简介一下,浏览器内核
Firefox -- Gecko
Opera -- Presto
IE -- Trident
Safari等一大波 -- webkit
chromium,新Opera -- Blink

?

?

?

?

?

?

?

异常中心网是一家专门收集整理程序员编程过程中遇到的常见异常(exception)以及各种异常问答中心的网站。异常中心网旨在,减少程序员在编码遇到异常,处理各种异常时间和痛苦,让程序员能更愉快的、快速的定位异常并查找对应的异常解决方案。异常中心网诚心打造最完美的编程社区为程序员用户服务,努力成为最好的程序员乐园程序员社区程序异常中心程序bug中心异常问答中心

?

喜欢0 评分0
游客

返回顶部