从输入 URL 到页面加载完成的过程中都发生了什么事情? 来源:fexweb前端 http://wuduoyi.com 编辑:Gemini 背景 本文来自于之前我发的一篇微博: 不过写这篇文章并不是为了帮大家准备面试,而是想借这道题来介绍计算机和互联网的基础知识,让读者了解它们之间是如何关联起来的。 为了便于理解,我将整个过程分为了六个问题来展开。 第一个问题:从输入 URL 到浏览器接收的过程中发生了什么事情?从触屏到 CPU首先是「输入 URL」,大部分人的第一反应会是键盘,不过为了与时俱进,这里将介绍触摸屏设备的交互。 触摸屏一种传感器,目前大多是基于电容(Capacitive)来实现的,以前都是直接覆盖在显示屏上的,不过最近出现了 3 种嵌入到显示屏中的技术,第一种是 iPhone 5 的 In-cell,它能减小了 0.5 毫米的厚度,第二种是三星使用的 On-cell 技术,第三种是国内厂商喜欢用的 OGS 全贴合技术,具体细节可以阅读这篇文章http://www.igao7.com/news/201406/in-cell-on-cell-ogs.html。 当手指在这个传感器上触摸时,有些电子会传递到手上,从而导致该区域的电压变化,触摸屏控制器芯片根据这个变化就能计算出所触摸的位置,然后通过总线接口将信号传到 CPU 的引脚上。 以 Nexus 5 为例,它所使用的触屏控制器是Synaptics S3350B,总线接口为IC,以下是 Synaptics 触摸屏和处理器连接的示例: 左边是处理器,右边是触摸屏控制器,中间的 SDA 和 SCL 连线就是 IC 总线接口。 CPU 内部的处理
前面提到了触屏和 CPU 的连接,这个连接和大部分计算机内部的连接一样,都是通过电气信号来进行通信的,也就是电压高低的变化,如下面的时序图: 在时钟的控制下,这些电流会经过MOSFET晶体管,晶体管中包含 N 型半导体和 P 型半导体,通过电压就能控制线路开闭,然后这些 MOSFET 构成了CMOS,接着再由 CMOS 实现「与」「或」「非」等逻辑电路门,最后由逻辑电路门上就能实现加法、位移等计算,整体如下图所示(来自《计算机体系结构》): 除了计算,在 CPU 中还需要存储单元来加载和存储数据,这个存储单元一般通过触发器(Flip-flop)来实现,称为寄存器。 以上这些概念都比较抽象,推荐阅读「How to Build an 8-Bit Computer http://www.instructables.com/id/How-to-Build-an-8-Bit-Computer/」这篇文章,作者基于晶体管、二极管、电容等原件制作了一个 8 位的计算机,支持简单汇编指令和结果输出,虽然现代 CPU 的实现要比这个复杂得多,但基本原理还是一样的。 另外其实我也是刚开始学习 CPU 芯片的实现,所以就不在这误人子弟了,感兴趣的读者请阅读本节后面推荐的书籍。 从 CPU 到操作系统内核前面说到触屏控制器将电气信号发送到 CPU 对应的引脚上,接着就会触发 CPU 的中断机制,以 Linux 为例,每个外部设备都有一标识符,称为中断请求(IRQ)号,可以通过
因为 Nexus 7 使用了 ELAN 的触屏控制器,所以结果中的 elan-ktf3k 就是触屏的中断请求信息,其中 294 是中断号,1973609 是触发的次数(手指单击时会产生两次中断,但滑动时会产生上百次中断)。 为了简化这里不考虑优先级问题,以 ARMv7 架构的处理器为例,当中断发生时,CPU 会停下当前运行的程序,保存当前执行状态(如 PC 值),进入 IRQ 状态),然后跳转到对应的中断处理程序执行,这个程序一般由第三方内核驱动来实现,比如前面提到的 Nexus 7 的驱动源码在这里touchscreen/ektf3k.c https://android.googlesource.com/kernel/tegra/ /android-tegra3-grouper-3.1-kitkat-mr1/drivers/input/touchscreen/ektf3k.c。 这个驱动程序将读取 IC 总线中传来的位置数据,然后通过内核的input_report_abs等方法记录触屏按下坐标等信息,最后由内核中的input 子模块将这些信息都写进
从操作系统 GUI 到浏览器前面提到 Linux 内核已经完成了对硬件的抽象,其它程序只需要通过禁用词语 但 Android 并没有使用 X,而是自己实现了一套 GUI 框架,其中有个EventHub的服务会通过epoll方式禁用词语 就这样,我们解答了第一个问题,不过由于时间有限,这里省略了很多细节,想进一步学习的读者推荐阅读以下书籍。 扩展学习第二个问题:浏览器如何向网卡发送数据?从浏览器到浏览器内核前面提到操作系统 GUI 将输入事件传递到了浏览器中,在这过程中,浏览器可能会做一些预处理,比如 Chrome 会根据历史统计来预估所输入字符对应的网站,比如输入了「ba」,根据之前的历史发现 90% 的概率会访问「www.baidu.com 」,因此就会在输入回车前就马上开始建立 TCP 链接甚至渲染了,这里面还有很多其它策略,感兴趣的读者推荐阅读High Performance Networking in Chrome http://aosabook.org/en/posa/high-performance-networking-in-chrome.html。 接着是输入 URL 后的「回车」,这时浏览器会对 URL 进行检查,首先判断协议,如果是 http 就按照 Web 来处理,另外还会对这个 URL 进行安全检查,然后直接调用浏览器内核中的对应方法,比如WebView中的 loadUrl 方法。 在浏览器内核中会先查看缓存,然后设置 UA 等 HTTP 信息,接着调用不同平台下网络请求的方法。
HTTP 请求的发送因为网络的底层实现是和内核相关的,所以这一部分需要针对不同平台进行处理,从应用层角度看主要做两件事情:通过 DNS 查询 IP、通过 Socket 发送数据,接下来就分别介绍这两方面的内容。 DNS 查询应用程序可以直接调用 Libc 提供的getaddrinfo()方法来实现 DNS 查询。 DNS 查询其实是基于 UDP 来实现的,这里我们通过一个具体例子来了解它的查找过程,以下是使用 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|