0%

当在浏览器中输入www.baidu.com并按下回车后,都发生了什么

让我们从零开始,从回车键按下到页面渲染完毕,从计算机和计算机网络角度(数据通信部分就不分析了,越弄越复杂)详细分析这个看似简单实则极度复杂的过程,争取考虑到每一个细节。欢迎补充。

0x01 回车键按下(物理级/硬件级)


一个专用于回车键的电流回路被直接或者通过电容器闭合了,使得少量的电流进入了键盘的逻辑电路系统。这个系统会扫描每个键的状态,对于按键开关的电位弹跳变化进行噪音消除,并将按键开关的电位弹跳变化转化为键盘码值。回车的码值是13。键盘控制器在得到码值之后,将其编码,用于之后的传输。(现在这个传输过程几乎都是通过通用串行总线(USB)或者蓝牙(Bluetooth)来进行的,以前是通过PS/2或者ADB连接进行。)

USB键盘
键盘的USB元件通过计算机上的USB接口与USB控制器相连接,USB接口中的第一号针为它提供了5V的电压
键码值存储在键盘内部电路一个叫做”endpoint”的寄存器内
USB控制器大概每隔10ms便查询一次”endpoint”以得到存储的键码值数据
键值码值通过USB串行接口引擎被转换成一个或者多个遵循低层USB协议的USB数据包
这些数据包通过D+针或者D-针(中间的两个针),以最高1.5Mb/s的速度从键盘传输至计算机
这个串行信号在计算机的USB控制器处被解码,然后被人机交互设备通用键盘驱动进行进一步解释,之后按键的码值被传输到操作系统的硬件抽象层

虚拟键盘(触屏设备)
在现代电容屏上,当用户把手指放在屏幕上时,一小部分电流从传导层的静电域经过手指传导,形成了一个回路,使得屏幕上触控的那一点电压下降,屏幕控制器产生一个中断,报告这次“点击”的坐标
然后移动操作系统通知当前活跃的应用,有一个点击事件发生在它的某个GUI部件上了,现在这个部件是虚拟键盘的按钮
虚拟键盘引发一个软中断,返回给OS一个“按键按下”消息
这个消息又返回来向当前活跃的应用通知一个“按键按下”事件

非USB键盘:产生中断信号
键盘在它的中断请求线(IRQ)上发送信号,信号会被中断控制器映射到一个中断向量。CPU使用中断描述符表(IDT)把中断向量映射到对应函数,这些函数被称为中断处理器,它们由操作系统内核提供。当一个中断到达时,CPU根据IDT和中断向量索引到对应的中断处理器,然后操作系统内核出场了。
(当中断发生时,CPU 会停下当前运行的程序,保存当前执行状态(如 PC 值( PC是一个16位的计数器。用于存放和指示下一条要执行的指令的地址)),进入 IRQ 状态(中断处理线状态),然后跳转到对应的中断处理程序执行)

0x02 操作系统级响应


[Windows系统]一个WM_KEYDOWN消息被发往应用程序

人体学接口设备(HID)把键盘按下的事件传送给 KBDHID.sys 驱动,把HID的信号转换成一个扫描码,这里回车的扫描码是 VK_RETURN(0x0d)。 KBDHID.sys 驱动和 KBDCLASS.sys (键盘类驱动)进行交互,之后它又去调用 Win32K.sys 。这些都是发生在内核模式(对比操作系统的用户模式)。

Win32K.sys 通过 GetForegroundWindow() API函数(该函数获取用户当前工作窗口的句柄)找到当前哪个窗口是活跃的。这个API函数提供了当前浏览器的地址栏的句柄。Windows系统的”message pump”机制(该机制在Window的主线程上做一个死循环,不断地去消息泵里去检查是否有消息到达,如果有消息抵达该窗口对象,则取出该消息,交付窗口过程去做处理。)调用 SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, lParam) 函数, lParam 是一个用来指示这个按键的更多信息的掩码,这些信息包括按键重复次数(这里是0),实际扫描码(可能依赖于OEM厂商,不过通常不会是 VK_RETURN ),功能键(alt, shift, ctrl)是否被按下(在这里没有),以及一些其他状态。

Windows的 SendMessage API直接将消息添加到特定窗口句柄 hWnd 的消息队列中,之后赋给 hWnd 的主要消息处理函数 WindowProc 将会被调用,用于处理队列中的消息。

当前活跃的句柄hWnd是一个edit control控件,这种情况下,WindowProc有一个用于处理 WM_KEYDOWN 消息的处理器,这段代码会查看 SendMessage 传入的第三个参数 wParam ,因为这个参数是 VK_RETURN ,于是它知道用户按下了回车键。

(Mac OS X)一个 KeyDown NSEvent被发往应用程序

  中断信号引发了I/O Kit Kext键盘驱动的中断处理事件,驱动把信号翻译成键码值,然后传给OS X的 WindowServer 进程。然后, WindowServer 将这个事件通过Mach端口分发给合适的(活跃的,或者正在监听的)应用程序,这个信号会被放到应用程序的消息队列里。队列中的消息可以被拥有足够高权限的线程使用 mach_ipc_dispatch 函数读取到。这个过程通常是由 NSApplication 主事件循环产生并且处理的,通过 NSEventType 为 KeyDown 的 NSEvent 。

(GNU/Linux)Xorg 服务器监听键码值

  当使用图形化的 X Server 时,X Server会按照特定的规则把键码值再一次映射,映射成扫描码。当这个映射过程完成之后, X Server 把这个按键字符发送给窗口管理器(DWM,metacity, i3等等),窗口管理器再把字符发送给当前窗口。

0x03 解析URL


浏览器通过URL能够知道下面的信息:
Protocol “http”:使用HTTP协议
Resource “/“:请求的资源是主页(index)

输入的是URL还是搜索的关键字?

  当协议或主机名不合法时,浏览器会将地址栏中输入的文字传给默认的搜索引擎。大部分情况下,在把文字传递给搜索引擎的时候,URL会带有特定的一串字符,用来告诉搜索引擎这次搜索来自这个特定浏览器。

检查HSTS列表

浏览器检查自带的“预加载HSTS(HTTP严格传输安全)”列表,这个列表里包含了那些请求浏览器只使用HTTPS进行连接的网站。
如果网站在这个列表里,浏览器会使用HTTPS而不是HTTP协议,否则,最初的请求会使用HTTP协议发送
注意,一个网站哪怕不在HSTS列表里,也可以要求浏览器对自己使用HSTS政策进行访问。浏览器向网站发出第一个HTTP请求之后,网站会返回浏览器一个响应,请求浏览器只使用HTTPS发送请求。然而,就是这第一个HTTP请求,却可能会使用户收到 downgrade attack 的威胁,这也是为什么现代浏览器都预置了HSTS列表。

转换非ASCII的Unicode字符

浏览器检查输入是否含有不是 a-z,A-Z,0-9,-或者.的字符
这里主机名是 google.com ,所以没有非ASCII的字符,如果有的话,浏览器会对主机名部分使用 Punycode 编码

HTTP与HTTPS

超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。
为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS,为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。

HTTP和HTTPS的基本概念

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

HTTP与HTTPS有什么区别?

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTPS的工作原理

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤:
(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
(5)Web服务器利用自己的私钥解密出会话密钥。
(6)Web服务器利用会话密钥加密与客户端之间的通信。

0x04 DNS查询


浏览器检查域名是否在缓存当中

如果缓存中没有,就去调用 gethostbyname 库函数(该函数返回一个指针,该指针对应于给定主机名,并包含主机名字和地址信息等主机信息)(操作系统不同 函数也不同)进行查询
gethostbyname 函数在试图进行DNS解析之前首先检查域名是否在本地Hosts里,对于Hosts的位置,不同的操作系统有所不同
如果 gethostbyname 没有这个域名的缓存记录,也没有在 hosts 里找到,它将会向DNS 服务器发送一条DNS查询请求。DNS服务器是由网络通信栈提供的,通常是本地路由器或者ISP的缓存DNS服务器。

查询本地 DNS 服务器

如果DNS服务器和我们的主机在同一个子网内,系统会按照下面的 ARP 过程对 DNS 服务器进行 ARP查询
如果DNS服务器和我们的主机在不同的子网,系统会按照下面的 ARP 过程对默认网关进行查询

ARP(根据IP地址获取物理地址,TCP/IP协议簇)

要想发送ARP广播,我们需要有一个目标IP地址,同时还需要知道用于发送ARP广播的接口的Mac地址。
首先查询ARP缓存(IP-MAC对照表的临时条目即ARP缓存)

如果缓存命中

返回结果:目标IP = MAC

如果缓存没有命中

1查看路由表(路由选择),看看目标IP地址是不是在本地路由表中的某个子网内。是的话,使用跟那个子网相连的接口,否则使用与默认网关相连的接口。
2查询选择的网络接口的MAC地址
3我们发送一个二层ARP请求:
ARP Request:
Sender MAC: interface:mac:address:here
Sender IP: interface.ip.goes.here
Target MAC: FF:FF:FF:FF:FF:FF (Broadcast)
Target IP: target.ip.goes.here
根据连接主机和路由器的硬件类型不同,可以分为以下几种情况:

1直连:

如果我们和路由器是直接连接的,路由器会返回一个 ARP Reply (见下面)。

2集线器:

如果我们连接到一个集线器,集线器会把ARP请求向所有其它端口广播,如果路由器也“连接”在其中,它会返回一个 ARP Reply 。

3交换机:

如果我们连接到了一个交换机,交换机会检查本地 CAM/MAC 表,看看哪个端口有我们要找的那个MAC地址,如果没有找到,交换机会向所有其它端口广播这个ARP请求。
如果交换机的MAC/CAM表中有对应的条目,交换机会向有我们想要查询的MAC地址的那个端口发送ARP请求
ARP Reply:
Sender MAC: target:mac:address:here
Sender IP: target.ip.goes.here
Target MAC: interface:mac:address:here
Target IP: interface.ip.goes.here
如果路由器也“连接”在其中,它会返回一个 ARP Reply
现在我们有了DNS服务器或者默认网关的IP地址,我们可以继续DNS请求了:
使用53端口向DNS服务器发送UDP请求包,如果响应包太大,会使用TCP
如果本地/ISP DNS服务器没有找到结果,它会发送一个递归查询请求,一层一层向高层DNS服务器做查询,直到查询到起始授权机构,如果找到会把结果返回

0x05 使用套接字(传输层)


当浏览器得到了目标服务器的IP地址,以及URL中给出来端口号(http协议默认端口号80,https默认端口号443),它会调用系统库函数 socket ,请求一个TCP流套接字(传输层实现端到端的通信,通信节点叫做套接字,表示方法,IP:端口号),对应参数是AF_INET(PF_INET也可以,ipv4用这个) 和 SOCK_STREAM(提供面向连接的稳定数据传输,即TCP)(这两个参数均应用在C语言socket编程中,函数原型:int socket(int domain,int type,int protocol);其中domain指定何种地址类型,如AF_INET,type设置通信协议类型,如SOCK_STREAM。)
这个请求首先被交给传输层,在传输层请求被封装成TCP segment(TCP包)。目标端口会被加入头部,源端口会在系统内核的动态端口范围内选取。
TCP segment被送往网络层,网络层会在其中再加入一个IP头部,里面包含了目标服务器的IP地址以及本机的IP地址,把它封装成一个TCP packet。
这个TCP packet接下来会进入链路层,链路层会在封包中加入frame头部,里面包含了本地内置网卡的MAC地址以及网关(本地路由器)的MAC地址。像前面说的一样,如果内核不知道网关的MAC地址,它必须进行ARP广播来查询其地址。
到了现在,TCP封包已经准备好了,可是使用下面的方式进行传输:
1以太网
2WiFi
3蜂窝数据网络

于大部分家庭网络和小型企业网络来说,封包会从本地计算机出发,经过本地网络,再通过调制解调器把数字信号转换成模拟信号,使其适于在电话线路,有线电视光缆和无线电话线路上传输。在传输线路的另一端,是另外一个调制解调器,它把模拟信号转换回数字信号,交由下一个 网络节点 处理。
大型企业和比较新的住宅通常使用光纤或直接以太网连接,这种情况下信号一直是数字的,会被直接传到下一个 网络节点 进行处理。
最终封包会到达管理本地子网的路由器。在那里出发,它会继续经过自治区域的边界路由器,其他自治区域(BGP协议),最终到达目标服务器。一路上经过的这些路由器会从IP数据报头部里提取出目标地址,并将封包正确地路由到下一个目的地。IP数据报头部TTL域的值每经过一个路由器就减1,如果封包的TTL变为0,或者路由器由于网络拥堵等原因封包队列满了,那么这个包会被路由器丢弃。

上面的发送和接受过程在TCP连接期间会发生很多次

0x06 TCP连接的建立(三次握手)


第一次握手

请求端(客户端)会向服务端(被请求端)发送一个tcp报文,申请打开某一个端口。因为没有数据,所以这个报文仅包含一个tcp头。
其中:
SYN=1;当建立一个新的连接时, SYN标志变1。
序号;序号用来标识从客户端向服务端发送的数据字节流。
此时客户端进入SYN_SENT状态。

第二次握手

服务端收到客户端的SYN包,也会发一个只包含tcp头的报文给客户端。
ACK=1;服务端确认收到信息
确认序号;客户端序号+1,作为应答
SYN=1;因为tcp的连接是双向的,服务端作为应答的同时请求建立连接。
此时服务端进入SYN_RECV状态

第三次握手

ACK=1;客户端确认收到信息
确认序号;服务端序号+1,作为应答
此时客户端进入ESTABLISHED状态,服务端收到ACK后也会进入此状态

可见,客户端和服务端都保留了对方的序号,这三次握手缺少任何一步都无法实现这一目标。在三次握手过程中,出现了一些中间状态。

这个问题的本质是, 信道不可靠, 但是通信双方需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足”在不可靠信道上可靠地传输信息”这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.

0x07 TLS 握手


客户端发送一个 ClientHello 消息到服务器端,消息中同时包含了它的 Transport Layer Security (TLS) 版本,可用的加密算法和压缩算法。

服务器端向客户端返回一个 ServerHello 消息,消息中包含了服务器端的TLS版本,服务器所选择的加密和压缩算法,以及数字证书认证机构(Certificate Authority,缩写 CA)签发的服务器公开证书,证书中包含了公钥。客户端会使用这个公钥加密接下来的握手过程,直到协商生成一个新的对称密钥。

客户端根据自己的信任CA列表,验证服务器端的证书是否可信。如果认为可信,客户端会生成一串伪随机数,使用服务器的公钥加密它。这串随机数会被用于生成新的对称密钥。
服务器端使用自己的私钥解密上面提到的随机数,然后使用这串随机数生成自己的对称主密钥。
客户端发送一个 Finished 消息给服务器端,使用对称密钥加密这次通讯的一个散列值。
服务器端生成自己的 hash 值,然后解密客户端发送来的信息,检查这两个值是否对应。如果对应,就向客户端发送一个Finished 消息,也使用协商好的对称密钥加密。
从现在开始,接下来整个 TLS 会话都使用对称秘钥进行加密,传输应用层(HTTP)内容。

0x08 HTTP服务器请求处理


HTTPD(HTTP Daemon)在服务器端处理请求/相应。最常见的 HTTPD 有 Linux 上常用的 Apache 和 nginx,与 Windows 上的 IIS。

HTTPD接收请求

服务器把请求拆分为以下几个参数:
HTTP请求方法(GET, POST, HEAD, PUT 和 DELETE )。在访问baidu这种情况下,使用的是GET方法
域名:baidu.com
请求路径/页面:/ (我们没有请求baidu.com下的指定的页面,因此 / 是默认的路径)
服务器验证其上已经配置了baidu.com的虚拟主机
服务器验证baidu.com接受GET方法
服务器验证该用户可以使用GET方法(根据IP地址,身份信息等)
如果服务器安装了 URL 重写模块(例如 Apache 的 mod_rewrite 和 IIS 的 URL Rewrite),服务器会尝试匹配重写规则,如果匹配上的话,服务器会按照规则重写这个请求
服务器根据请求信息获取相应的响应内容,这种情况下由于访问路径是 “/“ ,会访问首页文件。(你可以重写这个规则,但是这个是最常用的)
服务器会使用指定的处理程序分析处理这个文件,比如假设baidu使用PHP,服务器会使用PHP解析index文件,并捕获输出,把PHP的输出结果给请求者

0x09 浏览器


当服务器提供了资源之后(HTML,CSS,JS,图片等),浏览器会执行下面的操作:
解析 —— HTML,CSS,JS
渲染 —— 构建 DOM 树 -> 渲染 -> 布局 -> 绘制

浏览器的功能是从服务器上取回你想要的资源,然后展示在浏览器窗口当中。资源通常是 HTML 文件,也可能是 PDF,图片,或者其他类型的内容。资源的位置通过用户提供的 URI(Uniform Resource Identifier) 来确定。
浏览器解释和展示 HTML 文件的方法,在 HTML 和 CSS 的标准中有详细介绍。这些标准由 Web 标准组织 W3C(World Wide Web Consortium) 维护。
不同浏览器的用户界面大都十分接近,有很多共同的 UI 元素:
一个地址栏
后退和前进按
书签选项
刷新和停止按钮
主页按钮

浏览器高层架构

组成浏览器的组件有:

用户界面

用户界面包含了地址栏,前进后退按钮,书签菜单等等,除了请求页面之外所有你看到的内容都是用户界面的一部分

浏览器引擎

浏览器引擎负责让 UI 和渲染引擎协调工作

渲染引擎

渲染引擎负责展示请求内容。如果请求的内容是 HTML,渲染引擎会解析 HTML 和 CSS,然后将内容展示在屏幕上

网络组件

网络组件负责网络调用,例如 HTTP 请求等,使用一个平台无关接口,下层是针对不同平台的具体实现

UI后端

UI后端用于绘制基本 UI 组件,例如下拉列表框和窗口。UI 后端暴露一个统一的平台无关的接口,下层使用操作系统的 UI 方法实现

Javascript引擎

Javascript引擎用于解析和执行 Javascript 代码

数据存储

数据存储组件是一个持久层。浏览器可能需要在本地存储各种各样的数据,例如 Cookie 等。浏览器也需要支持诸如 localStorage,IndexedDB,WebSQL 和 FileSystem 之类的存储机制

HTML 解析

浏览器渲染引擎从网络层取得请求的文档,一般情况下文档会分成8kB大小的分块传输。
HTML 解析器的主要工作是对 HTML 文档进行解析,生成解析树。
解析树是以 DOM 元素以及属性为节点的树。DOM是文档对象模型(Document Object Model)的缩写,它是 HTML 文档的对象表示,同时也是 HTML 元素面向外部(如Javascript)的接口。树的根部是”Document”对象。整个 DOM 和 HTML 文档几乎是一对一的关系。

解析算法

HTML不能使用常见的自顶向下或自底向上方法来进行分析。主要原因有以下几点:
语言本身的“宽容”特性
HTML 本身可能是残缺的,对于常见的残缺,浏览器需要有传统的容错机制来支持它们
解析过程需要反复。对于其他语言来说,源码不会在解析过程中发生变化,但是对于 HTML 来说,动态代码,例如脚本元素中包含的 document.write() 方法会在源码中添加内容,也就是说,解析过程实际上会改变输入的内容
由于不能使用常用的解析技术,浏览器创造了专门用于解析 HTML 的解析器。解析算法在 HTML5 标准规范中有详细介绍,算法主要包含了两个阶段:标记化(tokenization)和树的构建。

解析结束之后

浏览器开始加载网页的外部资源(CSS,图像,Javascript 文件等)。
此时浏览器把文档标记为可交互的(interactive),浏览器开始解析处于“推迟(deferred)”模式的脚本,也就是那些需要在文档解析完毕之后再执行的脚本。之后文档的状态会变为“完成(complete)”,浏览器会触发“加载(load)”事件。
注意解析 HTML 网页时永远不会出现“无效语法(Invalid Syntax)”错误,浏览器会修复所有错误内容,然后继续解析。

CSS 解析

根据 CSS词法和句法 分析CSS文件,以及style标签包含的内容以及 style 属性的值
每个CSS文件都被解析成一个样式表对象(StyleSheet object),这个对象里包含了带有选择器的CSS规则,和对应CSS语法的对象
CSS解析器可能是自顶向下的,也可能是使用解析器生成器生成的自底向上的解析器

页面渲染

通过遍历DOM节点树创建一个“Frame 树”或“渲染树”,并计算每个节点的各个CSS样式值
通过累加子节点的宽度,该节点的水平内边距(padding)、边框(border)和外边距(margin),自底向上的计算”Frame 树”中每个节点的首选(preferred)宽度
通过自顶向下的给每个节点的子节点分配可行宽度,计算每个节点的实际宽度
通过应用文字折行、累加子节点的高度和此节点的内边距(padding)、边框(border)和外边距(margin),自底向上的计算每个节点的高度
使用上面的计算结果构建每个节点的坐标
当存在元素使用 floated,位置有 absolutely 或 relatively 属性的时候,会有更多复杂的计算
创建layer(层)来表示页面中的哪些部分可以成组的被绘制,而不用被重新栅格化处理。每个帧对象都被分配给一个层
每个层的帧对象都会被遍历,计算机执行绘图命令绘制各个层,此过程可能由CPU执行栅格化处理,或者直接通过D2D/SkiaGL在GPU上绘制
上面所有步骤都可能利用到最近一次页面渲染时计算出来的各个值,这样可以减少不少计算量
计算出各个层的最终位置,一组命令由 Direct3D/OpenGL发出,GPU命令缓冲区清空,命令传至GPU并异步渲染,帧被送到Window Server。

GPU 渲染
在渲染过程中,图形处理层可能使用通用用途的 CPU,也可能使用图形处理器 GPU
当使用 GPU 用于图形渲染时,图形驱动软件会把任务分成多个部分,这样可以充分利用 GPU 强大的并行计算能力,用于在渲染过程中进行大量的浮点计算。

Window Server 后期渲染与用户引发的处理

渲染结束后,浏览器根据某些时间机制运行JavaScript代码(比如Google Doodle动画)或与用户交互(在搜索栏输入关键字获得搜索建议)。类似Flash和Java的插件也会运行,尽管Baidu主页里没有。这些脚本可以触发网络请求,也可能改变网页的内容和布局,产生又一轮渲染与绘制。

0x0A 总结


总的来讲,当我们在浏览器地址栏输入 http://www.baidu.com 并按下回车后,一共发生了以下八项内容:

[1]硬件/操作系统级,处理用户按下回车键
[2]解析URL
[3]DNS查询,解析域名,将域名解析为IP地址
[4]ARP广播,根据IP地址来解析MAC地址
[5]分别从应用层到传输层、网络层和数据链路层分别加入各个层的头部封装为包
[6]进行三次握手后,客户端与服务器建立连接
[7]客服务器向客户端返回数据,浏览器接收到数据
[8]浏览器开始渲染页面