2. 進程間的跨線程通信和同步通信
在Chrome中,任何底層的數據都是線程非安全的,Channel不是太上老君(抑或中國足球?...),它也沒有例外。在每一個進程中,只能有一個線程來負責操作Channel,這個線程叫做IO線程(名不符實真是一件悲涼的事情...)。其它線程要是企圖越俎代庖,是會出大亂子的。。。
但是有時候(其實是大部分時候...),我們需要從非IO線程與別的進程相通信,這該如何是好?如果,你有看過我前面寫的線程模型,你一定可以想到,做法很簡單,先將對Channel的操作放到Task中,將此Task放到IO線程隊列里,讓IO線程來處理即可。當然,由于這種事情發(fā)生的太頻繁,每次都人肉做一次頗為繁瑣,于是有一個代理類,叫做ChannelProxy,來幫助你完成這一切。。。
從接口上看,ChannelProxy的接口和Channel沒有大的區(qū)別(否則就不叫Proxy了...),你可以像用Channel一樣,用ChannelProxy來Send你的消息,ChannelProxy會辛勤的幫你完成剩余的封裝Task等工作。不僅如此,ChannelProxy還青出于藍勝于藍,在這個層面上做了更多的事情,比如:發(fā)送同步消息。。。
不過能發(fā)送同步消息的類不是ChannelProxy,而是它的子類,SyncChannel。在Channel那里,所有的消息都是異步的(在Windows中,也叫Overlapped...),其本身也不支持同步邏輯。為了實現同步,SyncChannel并沒有另造輪子,而只是在Channel的層面上加了一個等待操作。當ChannelProxy的Send操作返回后,SyncChannel會把自己阻塞在一組信號量上,等待回包,直到永遠或超時。從外表上看同步和異步沒有什么區(qū)別,但在使用上還是要小心,在UI線程中使用同步消息,是容易被發(fā)指的。。。
3. Chrome中的IPC消息格式
說了半天,還有一個大頭沒有提過,那就是消息包。如果說,多線程模式下,對數據的訪問開銷來自于鎖,那么在多進程模式下,大部分的額外開銷都來自于進程間的消息拆裝和傳遞。不論怎么樣的模式,只要進程不同,消息的打包,序列化,反序列化,組包,都是不可避免的工作。。。
在Chrome中,IPC之間的通信消息,都是派生自IPC::Message類的。對于消息而言,序列化和反序列化是必須要支持的,Message的基類Pickle,就是干這個活的。Pickle提供了一組的接口,可以接受int,char,等等各種數據的輸入,但是在Pickle內部,所有的一切都沒有區(qū)別,都轉化成了一坨二進制流。這個二進制流是32位齊位的,比如你只傳了一個bool,也是最少占32位的,同時,Pickle的流是有自增邏輯的(就是說它會先開一個Buffer,如果滿了的話,會加倍這個Buffer...),使其可以無限擴展。Pickle本身不維護任何二進制流邏輯上的信息,這個任務交到了上級處理(后面會有說到...),但Pickle會為二進制流添加一個頭信息,這個里面會存放流的長度,Message在繼承Pickle的時候,擴展了這個頭的定義,完整的消息格式如下:
圖6 Chrome的IPC消息格式
其中,黃色部分是包頭,定長96個bit,綠色部分是包體,二進制流,由payload_size指明長度。從大小上看這個包是很精簡的了,除了routing位在消息不為路由消息的時候會有所浪費。消息本身在有名管道中是按照二進制流進行傳輸的(有名管道可以傳輸兩種類型的字符流,分別是二進制流和消息流...),因此由payload_size + 96bits,就可以確定是否收了一個完整的包。。。
從邏輯上來看,IPC消息分成兩類,一類是路由消息(routed message),還有一類是控制消息(control message)。路由消息是私密的有目的地的,系統(tǒng)會依照路由信息將消息安全的傳遞到目的地,不容它人窺視;控制消息就是一個廣播消息,誰想聽等能夠聽得到。。。
消息的序列化
前不久讀了Google Protocol Buffers的源碼,是用在服務器端,用做內部機器通信協(xié)議的標準、代碼生成工具和框架。它主要的思想是揉合了key/value的內容到二進制中,幫助生成更為靈活可靠的二進制協(xié)議。。。
在Chrome中,沒有使用這套東西,而是用到了純二進制流作為消息序列化的方式。我想這是由于應用場景不同使然。在服務端,我們更關心協(xié)議的穩(wěn)定性,可擴展性,并且,涉及到的協(xié)議種類很多。但在一個Chrome中,消息的格式很統(tǒng)一,這方面沒有擴展性和靈活性的需求,而在序列化上,雖然key/value的方式很好很強大,但是在Chrome中需要的不是靈活性而是精簡性,因此寧可不用Protocol Buffers造好的輪子,而是另立爐灶,花了好一把力氣提供了一套純二進制的消息機制。。。
出處:Venus神廟
責任編輯:bluehearts
上一頁 Chrome的進程間通信 上 下一頁 Chrome的多線程模型 下
◎進入論壇網絡編程版塊參加討論
|