前幾天看到一個(gè)題目,問(wèn)在瀏覽器中輸入一個(gè)URL會(huì)發(fā)生神馬,這好像是網(wǎng)上比較流行的面試題,而且也被回答爛了,仔細(xì)想下來(lái),要是自己遇到這個(gè)題目能不能答上來(lái),后來(lái)一想, 這個(gè)題目要完全答出來(lái)可以把大學(xué)開(kāi)始的幾乎所有知識(shí)都用上。 呵呵,為了模擬面試,所以都憑印象說(shuō)的,沒(méi)有查網(wǎng)絡(luò)資料,所以估計(jì)很多地方都不對(duì),歡迎來(lái)拍。[]()后續(xù)可以總結(jié)一個(gè)非常非常詳細(xì)的版本,個(gè)人感覺(jué)真的可以把大學(xué)開(kāi)始的所有的東西都用上,包括連數(shù)電模電(全部流程都跑不掉),信息論(gzip壓縮),密碼學(xué)(HTTPS),通訊原理(網(wǎng)絡(luò)基帶傳輸)這種都可以,本文還是以軟件處理過(guò)程為主。[]()
硬件層---鍵盤(pán)到CPU
[]()輸入網(wǎng)址嘛,那就是鍵盤(pán)輸入了,鍵盤(pán)一般用usb或者PS/2口連接電腦,現(xiàn)在見(jiàn)過(guò)PS/2口的人不多了吧,我們就看看usb吧,usb分為主從模式,一般的鍵盤(pán)本身的usb是一個(gè)從設(shè)備,相應(yīng)的還有u盤(pán)啊,鼠標(biāo)啊都是從設(shè)備,對(duì)應(yīng)的主機(jī)端的USBcontroller是一個(gè)主設(shè)備,這個(gè)主設(shè)備掛在CPU上,在X86結(jié)構(gòu)的機(jī)器上是掛在主板的南橋(好像是的,反正是低速的那個(gè))芯片上,如果是ARM這類(lèi)嵌入式設(shè)備的話(huà),那么就是掛在APB總線(xiàn)上,對(duì)這個(gè)我熟悉一些,就按ARM這種SoC來(lái)說(shuō)吧,當(dāng)是在手機(jī)上輸入U(xiǎn)RL吧,呵呵。[]()
鍵盤(pán)輸入字符以后,通過(guò)USB協(xié)議(USB協(xié)議簡(jiǎn)單的來(lái)說(shuō)就是一個(gè)串行協(xié)議,靠一個(gè)時(shí)鐘電信號(hào)和一個(gè)數(shù)據(jù)電信號(hào)傳輸數(shù)據(jù))將數(shù)據(jù)傳輸?shù)紸PB總線(xiàn)上的USB控制器上。然后這個(gè)控制器開(kāi)始搶總線(xiàn),總線(xiàn)的APB橋
接收到信號(hào)以后也開(kāi)始通過(guò)APB總線(xiàn)上的時(shí)鐘和數(shù)據(jù)線(xiàn)發(fā)送一個(gè)中斷信號(hào)
到APB橋
中,APB橋
同時(shí)連接在AHP
高速總線(xiàn)上,接收完數(shù)據(jù)以后,它開(kāi)始搶高速總線(xiàn),高速總線(xiàn)上有個(gè)Arbiter(總線(xiàn)仲裁器)
,因?yàn)楦咚倏偩€(xiàn)上接的都是內(nèi)存啊這種家伙,你一個(gè)小小的USB不見(jiàn)得搶得過(guò)他們,等仲裁器給你時(shí)間以后,APB橋
開(kāi)始把中斷信號(hào)發(fā)給CPU。[]()
CPU接收到這個(gè)中斷以后,要是沒(méi)有其他更高級(jí)的中斷需要處理的話(huà)就會(huì)調(diào)用內(nèi)核中的中斷處理函數(shù)開(kāi)始處理中斷,中斷處理函數(shù)又分為底半部和頂半部,首先會(huì)是底半部處理,把中斷放到處理隊(duì)列中就返回了,然后頂半部從隊(duì)列根據(jù)注冊(cè)的的中斷號(hào)拿到自己對(duì)應(yīng)的中斷號(hào)進(jìn)行處理,這時(shí)候中斷處理函數(shù)就算收到這個(gè)信號(hào)了,相當(dāng)于硬件的電信號(hào)已經(jīng)傳遞到軟件層了,中斷處理函數(shù)會(huì)調(diào)用USB的驅(qū)動(dòng)程序去USB控制器上讀取這個(gè)輸入的字符,這個(gè)字符還是通過(guò)兩條總線(xiàn)(APB和AHB)以獨(dú)占的方式傳遞到軟件層上,其實(shí)呢,是軟件控制這個(gè)信號(hào)寫(xiě)到了內(nèi)存的某個(gè)空間上。[]()
整個(gè)流程是這樣的[]()
發(fā)出中斷 :鍵盤(pán)--->usb控制器 ---> APB橋 ---> CPU硬件中斷 ---> 中斷處理底部 ---> 中斷處理函數(shù)頂部 ---> 驅(qū)動(dòng)程序 ---> 讀取數(shù)據(jù) ---> CPU尋址 ---> 寫(xiě)入內(nèi)存[]()
內(nèi)核層到應(yīng)用層
[]()假設(shè)我們輸入的url以C語(yǔ)言的scanf
函數(shù)為例,scanf函數(shù)會(huì)一直在內(nèi)核態(tài)阻塞著,直到中斷處理函數(shù)接收到了所有的字符并且接受到了一個(gè)回車(chē)符,這時(shí)scanf語(yǔ)句會(huì)通過(guò)操作系統(tǒng)的read調(diào)用把緩沖區(qū)的所有字符從內(nèi)核態(tài)拷貝到用戶(hù)態(tài),這時(shí)這些個(gè)字符就從電信號(hào)傳遞到了應(yīng)用程序(瀏覽器)的軟件層了。[]()
整個(gè)流程是[]()
scanf ---> 系統(tǒng)調(diào)用read ---> 內(nèi)核態(tài)阻塞等待 ---> 讀取拷貝數(shù)據(jù) ---> 用戶(hù)態(tài)接收數(shù)據(jù)[]()
因?yàn)檐浖右膊皇且粋€(gè)實(shí)體層次,其實(shí)所有的操作最后都變成了硬件的電信號(hào),所有沒(méi)辦法把流程寫(xiě)得很明白,大概就是這么個(gè)意思吧。[]()
網(wǎng)絡(luò)請(qǐng)求
[]()應(yīng)用程序(瀏覽器)接收到這個(gè)URL以后,就開(kāi)始走網(wǎng)絡(luò)層來(lái)獲取數(shù)據(jù)了,這里我們就不深入到底層的電信號(hào)了,就按網(wǎng)絡(luò)這一套來(lái)說(shuō)吧。[]()
DNS解析
[]()首先就要解析域名了,瀏覽器會(huì)先看一下本地的host文件,看有沒(méi)有url域名對(duì)應(yīng)的ip地址,如果沒(méi)有的話(huà),會(huì)通過(guò)DNS協(xié)議發(fā)送數(shù)據(jù)包給DNS服務(wù)器詢(xún)問(wèn)域名的ip地址,DNS服務(wù)自己沒(méi)有對(duì)應(yīng)的ip的話(huà)會(huì)繼續(xù)往上尋找,然后把ip地址發(fā)回給瀏覽器。DNS協(xié)議是UDP的,但好像有特殊情況是TCP連接,好像是各個(gè)DNS服務(wù)器之間傳輸用的TCP吧,不管了,反正通過(guò)UDP這個(gè)傳輸層協(xié)議之上的DNS應(yīng)用層協(xié)議把url對(duì)應(yīng)的ip地址得到了。[]()
傳輸數(shù)據(jù)準(zhǔn)備
[]()拿到ip地址以后,假設(shè)我們輸入的網(wǎng)址是https://www.baidu.com/
,百度的服務(wù)器在北京,而我們?cè)谏虾#瑸g覽器就通過(guò)connect開(kāi)始連接這個(gè)這個(gè)北京的ip地址了,連接跑到tcp/ip協(xié)議棧以后,協(xié)議棧一看這個(gè)IP和本地IP根本就不在一個(gè)段上啊,那ARP也不發(fā)了,直接把數(shù)據(jù)包轉(zhuǎn)發(fā)到網(wǎng)關(guān)上,也就是家里的路由器上了,路由器拿到地址,查一下本地的路由表,呀,我這小路由表上沒(méi)這個(gè)網(wǎng)段的啊,那我不管了,給我的上級(jí)路由吧(也許是小區(qū)的大路由器了),小區(qū)路由一看,我這也沒(méi)有啊,這樣一級(jí)一級(jí)傳遞到了上海的城際路由上,然后到了北京的城際路由,這么一層一層下來(lái)終于傳到了百度的服務(wù)器上。[]()
在這里看上去簡(jiǎn)單,但是路由的算法是很復(fù)雜的,這一塊我也不太懂沒(méi)弄過(guò),但是Dijkstra
選路算法還是明白的,別問(wèn)我為什么記得這個(gè)單詞,大學(xué)計(jì)算機(jī)網(wǎng)絡(luò)課的課程作業(yè)啊,就是實(shí)現(xiàn)這個(gè)Dijkstra
啊,通過(guò)路由算法,終于把第一個(gè)數(shù)據(jù)包發(fā)送給百度的服務(wù)器了。[]()
建立連接
[]()這個(gè)數(shù)據(jù)包是神馬呢,就是我們熟悉的TCP三次握手的第一握了,SYN=1的那個(gè)數(shù)據(jù)包,關(guān)于三次握手就不多說(shuō)了,大家都知道,關(guān)鍵是我不記得細(xì)節(jié)了,反正就是大家都懂的,握手完了連接就建立完了。為什么建立連接需要三次握手,關(guān)閉連接需要四次握手,呵呵,寫(xiě)不動(dòng)了。[]()
同時(shí),在百度服務(wù)器這邊,有個(gè)web服務(wù)器的應(yīng)用程序(比如Nginx),一直在監(jiān)聽(tīng)著80端口,收到這個(gè)數(shù)據(jù)包以后也同時(shí)和客戶(hù)端建立起了連接了。[]()
傳輸數(shù)據(jù)
[]()連接建立好以后,是TCP連接建立了,這時(shí)通過(guò)更上層的HTTP協(xié)議開(kāi)始傳輸數(shù)據(jù),HTTP協(xié)議本身很復(fù)雜,這里我們簡(jiǎn)單的來(lái)說(shuō),就是瀏覽器發(fā)送了一個(gè)GET / HTTP/1.1 \\n\\r
字符串給了服務(wù)器,服務(wù)器接受到這個(gè)字符串以后,通過(guò)協(xié)議棧傳遞給了上層的Nginx應(yīng)用程序。[]()
應(yīng)用程序一看這個(gè)地址是/
,然后對(duì)照一下自己的配置文件nginx.conf
,有個(gè)配置告訴他碰到這種請(qǐng)求,直接把本地的index.html
吐出去,于是Nginx讀取index.html
并把數(shù)據(jù)通過(guò)這條TCP連接回復(fù)給了客戶(hù)端。[]()
由于http協(xié)議是無(wú)狀態(tài)的,所以本次傳輸完數(shù)據(jù)以后,這個(gè)鏈接就關(guān)閉了。[]()
完成顯示
[]()好了,后面的就是接受到數(shù)據(jù)的顯示了,關(guān)于webkit內(nèi)核的細(xì)節(jié)就真不清楚了,就是解DOM樹(shù),執(zhí)行JS代碼,重新請(qǐng)求CSS和圖片,然后把頁(yè)面畫(huà)出來(lái)吧。[]()
哦了,題目做完了,其實(shí)還有很多細(xì)節(jié)沒(méi)有說(shuō)的,比如網(wǎng)絡(luò)尋址的時(shí)候的ARP協(xié)議啊,路由器尋路的其他很多算法啊,Nginx處理請(qǐng)求的時(shí)候的幾個(gè)階段解讀啊,是否需要反向代理到后端的服務(wù)器上啊,最后顯示的時(shí)候還需要操作顯卡進(jìn)行顯存的操作,如果頁(yè)面中有復(fù)雜的圖形效果還需要GPU參與運(yùn)算之類(lèi)的,要寫(xiě)就寫(xiě)不完了。
-
USB接口
+關(guān)注
關(guān)注
9文章
702瀏覽量
55758 -
USB控制器
+關(guān)注
關(guān)注
1文章
35瀏覽量
11906 -
SoC設(shè)計(jì)
+關(guān)注
關(guān)注
1文章
148瀏覽量
18805 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7614瀏覽量
137457 -
URL
+關(guān)注
關(guān)注
0文章
139瀏覽量
15426
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論