国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

經典面試題:從輸入 URL 到頁面加載完成的過程中都發生了什么事情?

greatwhole / 2625人閱讀

摘要:第一個問題從輸入到瀏覽器接收的過程中發生了什么事情從觸屏到首先是輸入,大部分人的第一反應會是鍵盤,不過為了與時俱進,這里將介紹觸摸屏設備的交互。

第一個問題:從輸入 URL 到瀏覽器接收的過程中發生了什么事情?
從觸屏到 CPU

首先是「輸入 URL」,大部分人的第一反應會是鍵盤,不過為了與時俱進,這里將介紹觸摸屏設備的交互。

觸摸屏一種傳感器,目前大多是基于電容(Capacitive)來實現的,以前都是直接覆蓋在顯示屏上的,不過最近出現了 3 種嵌入到顯示屏中的技術,第一種是 iPhone 5 的 In-cell,它能減小了 0.5 毫米的厚度,第二種是三星使用的 On-cell 技術,第三種是國內廠商喜歡用的 OGS 全貼合技術,具體細節可以閱讀這篇文章。

當手指在這個傳感器上觸摸時,有些電子會傳遞到手上,從而導致該區域的電壓變化,觸摸屏控制器芯片根據這個變化就能計算出所觸摸的位置,然后通過總線接口將信號傳到 CPU 的引腳上。

以 Nexus 5 為例,它所使用的觸屏控制器是 Synaptics S3350B,總線接口為 I2C,以下是 Synaptics 觸摸屏和處理器連接的示例:


左邊是處理器,右邊是觸摸屏控制器,中間的 SDA 和 SCL 連線就是 I2C 總線接口。
CPU 內部的處理

移動設備中的 CPU 并不是一個多帶帶的芯片,而是和 GPU 等芯片集成在一起,被稱為 SoC(片上系統)。

前面提到了觸屏和 CPU 的連接,這個連接和大部分計算機內部的連接一樣,都是通過電氣信號來進行通信的,也就是電壓高低的變化,如下面的時序圖:


在時鐘的控制下,這些電流會經過 MOSFET 晶體管,晶體管中包含 N 型半導體和 P 型半導體,通過電壓就能控制線路開閉,然后這些 MOSFET 構成了 CMOS,接著再由 CMOS 實現「與」「或」「非」等邏輯電路門,最后由邏輯電路門上就能實現加法、位移等計算,整體如下圖所示(來自《計算機體系結構》):


除了計算,在 CPU 中還需要存儲單元來加載和存儲數據,這個存儲單元一般通過觸發器(Flip-flop)來實現,稱為寄存器。

以上這些概念都比較抽象,推薦閱讀「How to Build an 8-Bit Computer」這篇文章,作者基于晶體管、二極管、電容等原件制作了一個 8 位的計算機,支持簡單匯編指令和結果輸出,雖然現代 CPU 的實現要比這個復雜得多,但基本原理還是一樣的。

另外其實我也是剛開始學習 CPU 芯片的實現,所以就不在這誤人子弟了,感興趣的讀者請閱讀本節后面推薦的書籍。
CPU 到操作系統內核

前面說到觸屏控制器將電氣信號發送到 CPU 對應的引腳上,接著就會觸發 CPU 的中斷機制,以 Linux 為例,每個外部設備都有一標識符,稱為中斷請求(IRQ)號,可以通過 /proc/interrupts 文件來查看系統中所有設備的中斷請求號,以下是 Nexus 7 (2013) 的部分結果:

shell@flo:/ $ cat /proc/interrupts

        CPU0

17: 0 GIC dg_timer
294: 1973609 msmgpio elan-ktf3k
314: 679 msmgpio KEY_POWER

因為 Nexus 7 使用了 ELAN 的觸屏控制器,所以結果中的 elan-ktf3k 就是觸屏的中斷請求信息,其中 294 是中斷號,1973609 是觸發的次數(手指單擊時會產生兩次中斷,但滑動時會產生上百次中斷)。

為了簡化這里不考慮優先級問題,以 ARMv7 架構的處理器為例,當中斷發生時,CPU 會停下當前運行的程序,保存當前執行狀態(如 PC 值),進入 IRQ 狀態),然后跳轉到對應的中斷處理程序執行,這個程序一般由第三方內核驅動來實現,比如前面提到的 Nexus 7 的驅動源碼在這里 touchscreen/ektf3k.c。

這個驅動程序將讀取 I2C 總線中傳來的位置數據,然后通過內核的 input_report_abs 等方法記錄觸屏按下坐標等信息,最后由內核中的 input 子模塊將這些信息都寫進 /dev/input/event0 這個設備文件中,比如下面展示了一次觸摸事件所產生的信息:

130|shell@flo:/ $ getevent -lt /dev/input/event0
[ 414624.658986] EV_ABS ABS_MT_TRACKING_ID 0000835c
[ 414624.659017] EV_ABS ABS_MT_TOUCH_MAJOR 0000000b
[ 414624.659047] EV_ABS ABS_MT_PRESSURE 0000001d
[ 414624.659047] EV_ABS ABS_MT_POSITION_X 000003f0
[ 414624.659078] EV_ABS ABS_MT_POSITION_Y 00000588
[ 414624.659078] EV_SYN SYN_REPORT 00000000
[ 414624.699239] EV_ABS ABS_MT_TRACKING_ID ffffffff
[ 414624.699270] EV_SYN SYN_REPORT 00000000

從操作系統 GUI 到瀏覽器

前面提到 Linux 內核已經完成了對硬件的抽象,其它程序只需要通過監聽 /dev/input/event0 文件的變化就能知道用戶進行了哪些觸摸操作,不過如果每個程序都這么做實在太麻煩了,所以在圖像操作系統中都會包含 GUI 框架來方便應用程序開發,比如 Linux 下著名的 X。

但 Android 并沒有使用 X,而是自己實現了一套 GUI 框架,其中有個 EventHub 的服務會通過 epoll 方式監聽 /dev/input/ 目錄下的文件,然后將這些信息傳遞到 Android 的窗口管理服務(WindowManagerService)中,它會根據位置信息來查找相應的 app,然后調用其中的監聽函數(如 onTouch 等)。

就這樣,我們解答了第一個問題,不過由于時間有限,這里省略了很多細節,想進一步學習的讀者推薦閱讀以下書籍。
擴展學習

《計算機體系結構》
《計算機體系結構:量化研究方法》
《計算機組成與設計:硬件/軟件接口》
《編碼》
《CPU自制入門》
《操作系統概念》
《ARMv7-AR 體系結構參考手冊》
《Linux內核設計與實現》
《精通Linux設備驅動程序開發》
第二個問題:瀏覽器如何向網卡發送數據?
從瀏覽器到瀏覽器內核

前面提到操作系統 GUI 將輸入事件傳遞到了瀏覽器中,在這過程中,瀏覽器可能會做一些預處理,比如 Chrome 會根據歷史統計來預估所輸入字符對應的網站,比如輸入了「ba」,根據之前的歷史發現 90% 的概率會訪問「www.baidu.com 」,因此就會在輸入回車前就馬上開始建立 TCP 鏈接甚至渲染了,這里面還有很多其它策略,感興趣的讀者推薦閱讀 High Performance Networking in Chrome。

接著是輸入 URL 后的「回車」,這時瀏覽器會對 URL 進行檢查,首先判斷協議,如果是 http 就按照 Web 來處理,另外還會對這個 URL 進行安全檢查,然后直接調用瀏覽器內核中的對應方法,比如 WebView 中的 loadUrl 方法。

在瀏覽器內核中會先查看緩存,然后設置 UA 等 HTTP 信息,接著調用不同平臺下網絡請求的方法。

需要注意瀏覽器和瀏覽器內核是不同的概念,瀏覽器指的是 Chrome、Firefox,而瀏覽器內核則是 Blink、Gecko,瀏覽器內核只負責渲染,GUI 及網絡連接等跨平臺工作則是瀏覽器實現的

HTTP 請求的發送

因為網絡的底層實現是和內核相關的,所以這一部分需要針對不同平臺進行處理,從應用層角度看主要做兩件事情:通過 DNS 查詢 IP、通過 Socket 發送數據,接下來就分別介紹這兩方面的內容。
DNS 查詢

應用程序可以直接調用 Libc 提供的 getaddrinfo() 方法來實現 DNS 查詢。

DNS 查詢其實是基于 UDP 來實現的,這里我們通過一個具體例子來了解它的查找過程,以下是使用 dig +trace fex.baidu.com 命令得到的結果(省略了一些):
可以看到這是一個逐步縮小范圍的查找過程,首先由本機所設置的 DNS 服務器(8.8.8.8)向 DNS 根節點查詢負責 .com 區域的域務器,然后通過其中一個負責 .com 的服務器查詢負責 baidu.com 的服務器,最后由其中一個 baidu.com 的域名服務器查詢 fex.baidu.com 域名的地址。

可能你在查詢某些域名的時會發現和上面不一樣,最底將看到有個奇怪的服務器搶先返回結果。。。

這里為了方便描述,忽略了很多不同的情況,比如 127.0.0.1 其實走的是 loopback,和網卡設備沒關系;比如 Chrome 會在瀏覽器啟動的時預先查詢 10 個你有可能訪問的域名;還有 Hosts 文件、緩存時間 TTL(Time to live)的影響等。

通過 Socket 發送數據

有了 IP 地址,就可以通過 Socket API 來發送數據了,這時可以選擇 TCP 或 UDP 協議,具體使用方法這里就不介紹了,推薦閱讀 Beej’s Guide to Network Programming。

HTTP 常用的是 TCP 協議,由于 TCP 協議的具體細節到處都能看到,所以本文就不介紹了,這里談一下 TCP 的 Head-of-line blocking 問題:假設客戶端的發送了 3 個 TCP 片段(segments),編號分別是 1、2、3,如果編號為 1 的包傳輸時丟了,即便編號 2 和 3 已經到達也只能等待,因為 TCP 協議需要保證順序,這個問題在 HTTP pipelining 下更嚴重,因為 HTTP pipelining 可以讓多個 HTTP 請求通過一個 TCP 發送,比如發送兩張圖片,可能第二張圖片的數據已經全收到了,但還得等第一張圖片的數據傳到。

為了解決 TCP 協議的性能問題,Chrome 團隊去年提出了 QUIC 協議,它是基于 UDP 實現的可靠傳輸,比起 TCP,它能減少很多來回(round trip)時間,還有前向糾錯碼(Forward Error Correction)等功能。目前 Google Plus、 Gmail、Google Search、blogspot、Youtube 等幾乎大部分 Google 產品都在使用 QUIC,可以通過 chrome://net-internals/#spdy 頁面來發現。

雖然目前除了 Google 還沒人用 QUIC,但我覺得挺有前景的,因為優化 TCP 需要升級系統內核(比如 Fast Open)。

瀏覽器對同一個域名有連接數限制,大部分是 6,我以前認為將這個連接數改大后會提升性能,但實際上并不是這樣的,Chrome 團隊有做過實驗,發現從 6 改成 10 后性能反而下降了,造成這個現象的因素有很多,如建立連接的開銷、擁塞控制等問題,而像 SPDY、HTTP 2.0 協議盡管只使用一個 TCP 連接來傳輸數據,但性能反而更好,而且還能實現請求優先級。

另外,因為 HTTP 請求是純文本格式的,所以在 TCP 的數據段中可以直接分析 HTTP 的文本,如果發現。。。
Socket 在內核中的實現

前面說到瀏覽器的跨平臺庫通過調用 Socket API 來發送數據,那么 Socket API 是如何實現的呢?

以 Linux 為例,它的實現在這里 socket.c,目前我還不太了解,推薦讀者看看 Linux kernel map,它標注出了關鍵路徑的函數,方便學習從協議棧到網卡驅動的實現。
底層網絡協議的具體例子

接下來如果繼續介紹 IP 協議和 MAC 協議可能很多讀者會暈,所以本節將使用 Wireshark 來通過具體例子講解,以下是我請求百度首頁時抓取到的網絡數據:

最底下是實際的二進制數據,中間是解析出來的各個字段值,可以看到其中最底部為 HTTP 協議(Hypertext Transfer Protocol),在 HTTP 之前有 54 字節(0x36),這就是底層網絡協議所帶來的開銷,我們接下來對這些協議進行分析。

在 HTTP 之上是 TCP 協議(Transmission Control Protocol),它的具體內容如下圖所示:


不多細說了
第三個問題:數據如何從本機網卡發送到服務器?
從內核到網絡適配器(Network Interface Card)

前面說到調用 Socket API 后內核會對數據進行底層協議棧的封裝,接下來啟動 DMA 控制器,它將從內存中讀取數據寫入網卡。

以 Nexus 5 為例,它使用的是博通 BCM4339 芯片通信,接口采用了 SD 卡一樣的 SDIO,但這個芯片的細節并沒有公開資料,所以這里就不討論了。
連接 Wi-Fi 路由

Wi-Fi 網卡需要通過 Wi-Fi 路由來與外部通信,原理是基于無線電,通過電流變化來產生無線電,這個過程也叫「調制」,而反過來無線電可以引起電磁場變化,從而產生電流變化,利用這個原理就能將無線電中的信息解讀出來就叫「解調」,其中單位時間內變化的次數就稱為頻率,目前在 Wi-Fi 中所采用的頻率分為 2.4 GHz 和 5 GHz 兩種。

在同一個 Wi-Fi 路由下,因為采用的頻率相同,同時使用時會發生沖突,為了解決這個問題,Wi-Fi 采用了被稱為 CSMA/CA 的方法,簡單來說就是在傳輸前先確認信道是否已被使用,沒有才發送數據。

而同樣基于無線電原理的 2G/3G/LTE 也會遇到類似的問題,但它并沒有采用 Wi-Fi 那樣的獨占方案,而是通過頻分(FDMA)、時分(TDMA)和碼分(CDMA)來進行復用,具體細節這里就不展開了。

以小米路由為例,它使用的芯片是 BCM 4709,這個芯片由 ARM Cortex-A9 處理器及流量(Flow)硬件加速組成,使用硬件芯片可以避免經過操作系統中斷、上下文切換等操作,從而提升了性能。

路由器中的操作系統可以基于 OpenWrt 或 DD-WRT 來開發的,具體細節我不太了解,所以就不展開了。

因為內網設備的 IP 都是類似 192.168.1.x 這樣的內網地址,外網無法直接向這個地址發送數據,所以網絡數據在經過路由時,路由會修改相關地址和端口,這個操作稱為 NAT 映射。

最后家庭路由一般會通過雙絞線連接到運營商網絡的。
運營商網絡內的路由

數據過雙絞線發送到運營商網絡后,還會經過很多個中間路由轉發,讀者可以通過 traceroute 命令或者在線可視化工具來查看這些路由的 ip 和位置。

當數據傳遞到這些路由器后,路由器會取出包中目的地址的前綴,通過內部的轉發表查找對應的輸出鏈路,而這個轉發表是如何得到的呢?這就是路由器中最重要的選路算法了,可選的有很多,我對這方面并不太了解,看起來維基百科上的詞條列得很全。
主干網間的傳輸

對于長線的數據傳輸,通常使用光纖作為介質,光纖是基于光的全反射來實現的,使用光纖需要專門的發射器通過電致發光(比如 LED)將電信號轉成光,比起前面介紹的無線電和雙絞線,光纖信號的抗干擾性要強得多,而且能耗也小很多。

既然是基于光來傳輸數據,數據傳輸速度也就取決于光的速度,在真空中的光速接近于 30 萬千米/秒,由于光纖包層(cladding)中的折射率(refractive index)為 1.52,所以實際光速是 20 萬千米/秒左右,從首都機場飛往廣州白云機場的距離是 1967 千米,按照這個距離來算需要花費 10 毫秒才能抵達。這意味著如果你在北京,服務器在廣州,等你發出數據到服務器返回數據至少得等 20 毫秒,實際情況預計是 2- 3 倍,因為這其中還有各個節點路由處理的耗時,比如我測試了一個廣州的 IP 發現平均延遲為 60 毫秒。

這個延遲是現有科技無法解決的(除非找到超過光速的方法),只能通過 CDN 來讓傳輸距離變短,或盡量減少串行的來回請求(比如 TCP 建立連接所需的 3 次握手)。
IDC 內網

數據通過光纖最終會來到服務器所在的 IDC 機房,進入 IDC 內網,這時可以先通過分光器將流量鏡像一份出來方便進行安全檢查等分析,還能用來進行。。。

這里的帶寬成本很高,是按照峰值來結算的,以每月每 Gbps(注意這里指的是 bit,而不是 Byte)為單位,北京這邊價格在十萬人民幣以上,一般網站使用 1G 到 10G 不等。

接下來光纖中的數據將進入集群(Cluster)交換機,然后再轉發到機架(Rack)頂部的交換機,最后通過這個交換機的端口將數據發往機架中的服務器,可以參考下圖(來自 Open Compute):


上圖左邊是正面,右邊是側面,可以看到頂部為交換機所留的位置。

以前這些交換機的內部實現是封閉的,相關廠商(如思科、Juniper 等)會使用特定的處理器和操作系統,外界難以進行靈活控制,甚至有時候需要手工配置,但這幾年隨著 OpenFlow 技術的流行,也出現了開放交換機硬件(Open Switch Hardware),比如 Intel 的網絡平臺,推薦感興趣的讀者建議看看它的視頻,比文字描述清晰多了。

需要注意的是,一般網絡書中提到的交換機都只具備二層(MAC 協議)的功能,但在 IDC 中的交換器基本上都具備三層(IP 協議)的功能,所以不需要有專門的路由了。

最后,因為 CPU 處理的是電氣信號,所以光纖中的光線需要先使用相關設備通過光電效應將光信號轉成電信號,然后進入服務器網卡。
服務器 CPU

前面說到數據已經到達服務器網卡了,接著網卡會將數據拷貝到內存中(DMA),然后通過中斷來通知 CPU,目前服務器端的 CPU 基本上都是 Intel Xeon,不過這幾年出現了一些新的架構,比如在存儲領域,百度使用 ARM 架構來提升存儲密度,因為 ARM 的功耗比 Xeon 低得多。而在高性能領域,Google 最近在嘗試基于 POWER 架構的 CPU 來開發的服務器,最新的 POWER8 處理器可以并行執行 96 個線程,所以對高并發的應用應該很有幫助。
擴展學習

The Datacenter as a Computer
Open Computer
《軟件定義網絡》
《大話無線通信》

第四個問題:服務器接收到數據后會進行哪些處理?
為了避免重復,這里將不再介紹操作系統,而是直接進入后端服務進程,由于這方面有太多技術選型,所以我只挑幾個常見的公共部分來介紹。
負載均衡

請求在進入到真正的應用服務器前,可能還會先經過負責負載均衡的機器,它的作用是將請求合理地分配到多個服務器上,同時具備具備防攻擊等功能。

負載均衡具體實現有很多種,有直接基于硬件的 F5,有操作系統傳輸層(TCP)上的 LVS,也有在應用層(HTTP)實現的反向代理(也叫七層代理),接下來將介紹 LVS 及反向代理。

負載均衡的策略也有很多,如果后面的多個服務器性能均衡,最簡單的方法就是挨個循環一遍(Round-Robin),其它策略就不一一介紹了,可以參考 LVS 中的算法。

LVS

LVS 的作用是從對外看來只有一個 IP,而實際上這個 IP 后面對應是多臺機器,因此也被成為 Virtual IP。

前面提到的 NAT 也是一種 LVS 中的工作模式,除此之外還有 DR 和 TUNNEL,具體細節這里就不展開了,它們的缺點是無法跨網段,所以百度自己開發了 BVS 系統。

反向代理

反向代理是工作在 HTTP 上的,具體實現可以基于 HAProxy 或 Nginx,因為反向代理能理解 HTTP 協議,所以能做非常多的事情,比如:

進行很多統一處理,比如防攻擊策略、防抓取、SSL、gzip、自動性能優化等
應用層的分流策略都能在這里做,比如對 /xx 路徑的請求分到 a 服務器,對 /yy 路徑的請求分到 b 服務器,或者按照 cookie 進行小流量測試等
緩存,并在后端服務掛掉的時候顯示友好的 404 頁面
監控后端服務是否異常
??

Nginx 的代碼寫得非常優秀,從中能學到很多,對高性能服務端開發感興趣的讀者一定要看看。
Web Server 中的處理

請求經過前面的負載均衡后,將進入到對應服務器上的 Web Server,比如 Apache、Tomcat、Node.JS 等。

以 Apache 為例,在接收到請求后會交給一個獨立的進程來處理,我們可以通過編寫 Apache 擴展來處理,但這樣開發起來太麻煩了,所以一般會調用 PHP 等腳本語言來進行處理,比如在 CGI 下就是將 HTTP 中的參數放到環境變量中,然后啟動 PHP 進程來執行,或者使用 FastCGI 來預先啟動進程。

(等后續有空再多帶帶介紹 Node.JS 中的處理)
進入后端語言

前面說到 Web Server 會調用后端語言進程來處理 HTTP 請求(這個說法不完全正確,有很多其它可能),那么接下來就是后端語言的處理了,目前大部分后端語言都是基于虛擬機的,如 PHP、Java、JavaScript、Python 等,但這個領域的話題非常大,難以講清楚,對 PHP 感興趣的讀者可以閱讀我之前寫的 HHVM 介紹文章,其中提到了很多虛擬機的基礎知識。
Web 框架(Framework)

如果你的 PHP 只是用來做簡單的個人主頁「Personal Home Page」,倒沒必要使用 Web 框架,但如果隨著代碼的增加會變得越來越難以管理,所以一般網站都會會基于某個 Web 框架來開發,因此在后端語言執行時首先進入 Web 框架的代碼,然后由框架再去調用應用的實現代碼。

可選的 Web 框架非常多,這里就不一一介紹了。
讀取數據

這部分不展開了,從簡單的讀寫文件到數據中間層,這里面可選的方案實在太多。
擴展學習

《深入理解Nginx》
《Python源碼剖析》
《深入理解Java虛擬機》
《數據庫系統實現》

第五個問題:服務器返回數據后瀏覽器如何處理?
前面說到服務端處理完請求后,結果將通過網絡發回客戶端的瀏覽器,從本節開始將介紹瀏覽器接收到數據后的處理,值得一提的是這方面之前有一篇不錯的文章 How Browsers Work,所以很多內容我不想再重復介紹,因此將重點放在那篇文章所忽略的部分。
從 01 到字符

HTTP 請求返回的 HTML 傳遞到瀏覽器后,如果有 gzip 會先解壓,然后接下來最重要的問題是要知道它的編碼是什么,比如同樣一個「中」字,在 UTF-8 編碼下它的內容其實是「11100100 10111000 10101101」也就是「E4 B8 AD」,而在 GBK 下則是「11010110 11010000」,也就是「D6 D0」,如何才能知道文件的編碼?可以有很多判斷方法:

用戶設置,在瀏覽器中可以指定頁面編碼
HTTP 協議中
 中的 charset 屬性值
對于 JS 和 CSS
對于 iframe

如果在這些地方都沒指明,瀏覽器就很難處理,在它看來就是一堆「0」和「1」,比如「中文」,它在 UTF-8 下有 6 個字節,如果按照 GBK 可以當成「涓枃」這 3 個漢字來解釋,瀏覽器怎么知道到底是「中文」還是「涓枃」呢?

不過正常人一眼就能認出「涓枃」是錯的,因為這 3 個字太不常見了,所以有人就想到通過判斷常見字的方法來檢測編碼,典型的比如 Mozilla 的 UniversalCharsetDetection,不過這東東誤判率也很高,所以還是指明編碼的好。

這樣后續對文本的操作就是基于「字符」(Character)的了,一個漢字就是一個字符,不用再關心它究竟是 2 個字節還是 3 個字節。
外鏈資源的加載

(待補充,這里有調度策略)
JavaScript 的執行

(后續再多帶帶介紹,推薦大家看 R 大去年整理的這個帖子,里面有非常多相關資料,另外我兩年前曾講過 JavaScript 引擎中的性能優化,雖然有些內容不太正確了,但也可以看看)
從字符到圖片

二維渲染中最復雜的要數文字顯示了,雖然想想似乎很簡單,不就是將某個文字對應的字形(glyph)找出來么?在中文和英文中這樣做是沒問題的,因為一個字符就對應一個字形(glyph),在字體文件中找到字形,然后畫上去就可以了,但在阿拉伯語中是不行的,因為它有有連體形式。

(以后續再多帶帶介紹,這里非常復雜)
跨平臺 2D 繪制庫

在不同操作系統中都提供了自己的圖形繪制 API,比如 Mac OS X 下的 Quartz,Windows 下的 GDI 以及 Linux 下的 Xlib,但它們相互不兼容,所以為了方便支持跨平臺繪圖,在 Chrome 中使用了 Skia 庫。

(以后再多帶帶介紹,Skia 內部實現調用層級太多,直接講代碼可能不適合初學者)
GPU 合成

(以后續再多帶帶介紹,雖然簡單來說就是靠貼圖,但還得介紹 OpenGL 以及 GPU 芯片,內容太長)
擴展學習

這節內容是我最熟悉,結果反而因為這樣才想花更多時間寫好,所以等到以后再發出來好了,大家先可以先看看以下幾個站點:

Chromium
Mozilla Hacks
Surfin’ Safari

第六個問題:瀏覽器如何將頁面展現出來?
前面提到瀏覽器已經將頁面渲染成一張圖片了,接下來的問題就是如何將這張圖片展示在屏幕上。
Framebuffer

以 Linux 為例,在應用中控制屏幕最直接的方法是將圖像的 bitmap 寫入 /dev/fb0 文件中,這個文件實際上一個內存區域的映射,這段內存區域稱為 Framebuffer。

需要注意的是在硬件加速下,如 OpenGL 是不經過 Framebuffer 的。
從內存到 LCD

在手機的 SoC 中通常都會有一個 LCD 控制器,當 Framebuffer 準備好后,CPU 會通過 AMBA 內部總線通知 LCD 控制器,然后這個控制器讀取 Framebuffer 中的數據,進行格式轉換、伽馬校正等操作,最終通過 DSI、HDMI 等接口發往 LCD 顯示器。
本文所忽略的內容

為了編寫方便,前面的介紹中將很多底層細節實現忽略了,比如:

內存相關
    堆,這里的分配策略有很多,比如 malloc 的實現
    棧,函數調用,已經有很多優秀的文章或書籍介紹了
    內存映射,動態庫加載等
    隊列幾乎無處不在,但這些細節和原理沒太大關系
各種緩存
    CPU 的緩存、操作系統的緩存、HTTP 緩存、后端緩存等等
各種監控
    很多日志會保存下來以便后續分析

大綱:

瀏覽器查詢緩存,如果緩存存在跳到第9步

瀏覽器詢問操作系統服務器的IP地址

操作系統做DNS查詢,返回IP地址給瀏覽器

瀏覽器打開對服務器的TCP連接

瀏覽器通過TCP連接發送HTTP請求

瀏覽器接收HTTP響應并且可能關掉TCP連接,或者是重新使用連接處理新請求(也就是keepalive)

瀏覽器檢查HTTP響應是否為一個重定向(3xx 結果狀態碼 ),一個驗證請求(401),錯誤(4xx 5xx)等等,這些都是不同響應的正常處理(2xx)

如果響應可緩存,將存入緩存

瀏覽器解碼響應(例如:如果它是gziped壓縮)

瀏覽器決定如何處理這些響應(例如,它是HTML頁面,一張圖片,一段音樂)

瀏覽器展現響應,對未知類型還會彈出下載對話框(現在一般不會彈出了,用戶對瀏覽器設置而定)

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22849.html

相關文章

  • 前端面試url頁面展現,這之中發生什么

    摘要:比如對于的,瀏覽器實際上不知道到底是什么東西,需要查找網站所在服務器的地址,才能找到目標,這就是下文要說的域名解析。二域名解析當用戶在瀏覽器中輸入后你使用的電腦會發出一個請求到本地服務器。 showImg(https://segmentfault.com/img/remote/1460000009317499?w=700&h=466); 這里markdown格式跟簡書不太一樣,排版可能...

    wdzgege 評論0 收藏0
  • 輸入`URL`頁面加載完成過程中都發生什么事情

    摘要:但收到此失效的連接請求報文段后,就誤認為是再次發出的一個新的連接請求。采用三次握手的辦法可以防止上述現象發生。 概覽 日期:2018-4-26目標:了解從輸入URL到頁面加載完成的過程中都發生了什么事情總用時:一天完成情況:達成 基本過程 為什么會想要了解從輸入URL到頁面加載完成的過程中都發生了什么事情這個問題呢,因為課程參考資料的Web 建站技術中HTML、HTML5、XHTML、...

    cuieney 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<