原文:http://www.cnblogs.com/duguguiyu/archive/2008/10/04/1303695.html
1. Chrome進(jìn)程通信的基本模式
進(jìn)程間通信,叫做IPC(Inter-Process Communication),在Chrome不多的文檔中,有一篇就是介紹這個的,在 這里 。Chrome最主要有三類進(jìn)程,一類是Browser主進(jìn)程,我們一直尊稱它老人家為老大;還有一類是各個Render進(jìn)程,前面也提過了;另外還有一類一直沒說過,是Plugin進(jìn)程,每一個插件,在Chrome中都是以進(jìn)程的形式呈現(xiàn),等到后面說插件的時候再提罷了。Render進(jìn)程和Plugin進(jìn)程都與老大保持進(jìn)程間的通信,Render進(jìn)程與Plugin進(jìn)程之間也有彼此聯(lián)系的通路,唯獨(dú)是多個Render進(jìn)程或多個Plugin進(jìn)程直接,沒有互相聯(lián)系的途徑,全靠老大協(xié)調(diào)。。。
進(jìn)程與進(jìn)程間通信,需要仰仗操作系統(tǒng)的特性,能玩的花著實(shí)不多,在Chrome中,用到的就是有名管道(Named Pipe),只不過,它用一個IPC::Channel類,封裝了具體的實(shí)現(xiàn)細(xì)節(jié)。Channel可以有兩種工作模式,一種是Client,一種是Server,Server和Client分屬兩個進(jìn)程,維系一個共同的管道名,Server負(fù)責(zé)創(chuàng)建該管道,Client會嘗試連接該管道,然后雙發(fā)往各自管道緩沖區(qū)中讀寫數(shù)據(jù)(在Chrome中,用的是二進(jìn)制流,異步IO...),完成通信。。。
管道名字的協(xié)商
在Socket中,我們會事先約定好通信的端口,如果不按照這個端口進(jìn)行訪問,走錯了門,會被直接亂棍打出門去的。與之類似,有名管道期望在兩個進(jìn)程間游走,就需要拿一個兩個進(jìn)程都能接受的進(jìn)門暗號,這個就是有名管道的名字。在Chrome中(windows下...),有名管道的名字格式都是:\\.\pipe\chrome.ID。其中的ID,自然是要求獨(dú)一無二,比如:進(jìn)程ID.實(shí)例地址.隨機(jī)數(shù)。通常,這個ID是由一個Process生成(往往是Browser Process),然后在創(chuàng)建另一個進(jìn)程的時候,作為命令行參數(shù)傳進(jìn)去,從而完成名字的協(xié)商。。。
如果不了解并期待了解有關(guān)Windows下有名管道和信號量的知識,建議去看一些專業(yè)的書籍,比如圣經(jīng)級別的《Windows核心編程》和《深入解析Windows操作系統(tǒng)》,當(dāng)然也可以去查看SDK,你需要了解的API可能包括:CreateNamedPipe, CreateFile, ConnectNamedPipe, WaitForMultipleObjects, WaitForSingleObject, SetEvent, 等等。。。
Channel中,有三個比較關(guān)鍵的角色,一個是Message::Sender,一個是Channel::Listener,最后一個是MessageLoopForIO::Watcher。Channel本身派生自Sender和Watcher,身兼兩角,而Listener是一個抽象類,具體由Channel的使用者來實(shí)現(xiàn)。顧名思義,Sender就是發(fā)送消息的接口,Listener就是處理接收到消息的具體實(shí)現(xiàn),但這個Watcher是啥?如果你覺得Watcher這東西看上去很眼熟的話,我會激動的熱淚盈眶的,沒錯,在前面(第一部分第一小節(jié)...)說消息循環(huán)的時候,從那個表中可以看到,IO線程(記住,在Chrome中,IO指的是網(wǎng)絡(luò)IO,*_*)的循環(huán)會處理注冊了的Watcher。其實(shí)Watcher很簡單,可以視為一個信號量和一個帶有OnObjectSignaled方法對象的對,當(dāng)消息循環(huán)檢測到信號量開啟,它就會調(diào)用相應(yīng)的OnObjectSignaled方法。。。
圖5 Chrome的IPC處理流程圖
一圖解千語,如上圖所示,整個Chrome最核心的IPC流程都在圖上了,期間,刨去了一些錯誤處理等邏輯,如果想看原汁原味的,可以自查Channel類的實(shí)現(xiàn)。當(dāng)有消息被Send到一個發(fā)送進(jìn)程的Channel的時候,Channel會把它放在發(fā)送消息隊(duì)列中,如果此時還正在發(fā)送以前的消息(發(fā)送端被阻塞...),則看一下阻塞是否解除(用一個等待0秒的信號量等待函數(shù)...),然后將消息隊(duì)列中的內(nèi)容序列化并寫道管道中去。操作系統(tǒng)會維護(hù)異步模式下管道的這一組信號量,當(dāng)消息從發(fā)送進(jìn)程緩沖區(qū)寫到接收進(jìn)程的緩沖區(qū)后,會激活接收端的信號量。當(dāng)接收進(jìn)程的消息循環(huán),循到了檢查Watcher這一步,并發(fā)現(xiàn)有信號量激活了,就會調(diào)用該Watcher相應(yīng)的OnObjectSignaled方法,通知接受進(jìn)程的Channel,有消息來了!Channel會嘗試從管道中收字節(jié),組消息,并調(diào)用Listener來解析該消息。。。
從上面的描述不難看出,Chrome的進(jìn)程通信,最核心的特點(diǎn),就是利用消息循環(huán)來檢查信號量,而不是直接讓管道阻塞在某信號量上。這樣就與其多線程模型緊密聯(lián)系在了一起,用一種統(tǒng)一的模式來解決問題。并且,由于是消息循環(huán)統(tǒng)一檢查,線程不會隨便就被阻塞了,可以更好的處理各種其他工作,從理論上講,這是通過增加CPU工作時間,來換取更好的體驗(yàn),頗有資本家的派頭。。。
溫柔的消息循環(huán)
其實(shí),Chrome的很多消息循環(huán),也不是都那么霸道,也是會被阻塞在某些信號量或者某種場景上的,畢竟客戶端不是它家的服務(wù)器,CPU不能被全部歸在它家名下。。。 比如IO線程,當(dāng)沒有消息來到,又沒有信號量被激活的時候,就會被阻塞,具體實(shí)現(xiàn)可以去看MessagePumpForIO的WaitForWork方法。。。 不過這種阻塞是集中式的,可隨時修改策略的,比起Channel直接阻塞在信號量上,停工的時間更短。。。
出處:Venus神廟
責(zé)任編輯:bluehearts
上一頁 Chrome的多線程模型 下 下一頁 Chrome的多線程模型 中
◎進(jìn)入論壇網(wǎng)絡(luò)編程版塊參加討論
|