從IPC到分布式軟總線的隨筆
在Linux 系統(tǒng)中, 客觀來(lái)說,缺乏相對(duì)開發(fā)者比較友好的進(jìn)程間通信框架。談到Linux上進(jìn)程間通信,一般都會(huì)想起管道(匿名、有名)、信號(hào)/信號(hào)燈、共享內(nèi)存、消息隊(duì)列和socket。這些都是偏低層的技術(shù),有沒有方便開發(fā)者使用的技術(shù)或者框架呢?軟件總線以及分布式軟總線或許是一種不錯(cuò)的候選。
Linux 中的進(jìn)程間通信一瞥
Linux環(huán)境下通信機(jī)制眾多,各種通信方式都有其適用的場(chǎng)合。
管道是Linux支持的最初Unix IPC機(jī)制之一,是實(shí)現(xiàn)方法最簡(jiǎn)單的一種通信機(jī)制。但是,只能以半雙工的形式在進(jìn)程間進(jìn)行通信。
信號(hào)是多種通信機(jī)制中唯一一種異步方式進(jìn)行通信的機(jī)制。信號(hào)方式通信傳輸?shù)臄?shù)據(jù)量較少,側(cè)重于控制進(jìn)程根據(jù)不同的信號(hào)觸發(fā)不同的行為。
消息隊(duì)列是在內(nèi)核中開辟的一組鏈表,以隊(duì)列的形式接收和發(fā)送信息,適用于傳輸數(shù)據(jù)量較少的場(chǎng)合。消息隊(duì)列與管道通信相比,其優(yōu)勢(shì)是對(duì)每一個(gè)消息可以指定特定消息類型,接收的時(shí)候不需要按隊(duì)列次序,而是可以根據(jù)自定義條件接收特定類型的消息。但在消息信息的發(fā)送進(jìn)程—操作系統(tǒng)內(nèi)核和內(nèi)核—接收進(jìn)程間復(fù)制時(shí)需要額外占用CPU的時(shí)間。
共享內(nèi)存通信機(jī)制在進(jìn)程間可以傳送大量的數(shù)據(jù),并且由于讀寫進(jìn)程均將共享內(nèi)存塊視為本進(jìn)程所有,可直接讀寫,因此傳輸速度最快。但由于多個(gè)進(jìn)程對(duì)共享內(nèi)存塊的訪問必須以互斥形式進(jìn)行,因此還需要信號(hào)量機(jī)制予以配合。
信號(hào)量機(jī)制通過信號(hào)量值的變化來(lái)控制多進(jìn)程互斥的訪問共享資源,或者協(xié)調(diào)多個(gè)進(jìn)程并發(fā)執(zhí)行的節(jié)奏,并未在進(jìn)程之間實(shí)際的傳輸數(shù)據(jù)。
基于 Socket 的進(jìn)程間通信機(jī)制是現(xiàn)在所有網(wǎng)絡(luò)操作系統(tǒng)必不可少的基礎(chǔ)功能,大多數(shù)現(xiàn)代進(jìn)程間通信框架都是基于Socket 完成的。
久遠(yuǎn)一點(diǎn)的DCOP
大約從KDE2.0 開始,都包含了非常強(qiáng)大的部件,叫做“Desktop COmmunication Protocol”,簡(jiǎn)稱為 DCOP,從開發(fā)者的角度來(lái)看,利用 DCOP 可以很方便地將強(qiáng)大的腳本功能添加到應(yīng)用程序中。從用戶的角度來(lái)看,利用 DCOP 可以容易地控制 KDE 應(yīng)用程序,并可以將它們以強(qiáng)大而有趣方式組合起來(lái)。
就其本質(zhì)而言,DCOP 是一個(gè)操作于socket之上的輕量級(jí)進(jìn)程間通信機(jī)制,由一個(gè)服務(wù)器(即 dcopserver,它在 KDE 啟動(dòng)時(shí)會(huì)自動(dòng)啟動(dòng))和任意多個(gè)客戶端(支持 DCOP 的應(yīng)用程序)構(gòu)成。DCOP客戶段之間可以通過服務(wù)器互相發(fā)送消息,要求執(zhí)行函數(shù),等等。
kdebindings 軟件包中含對(duì) Java 的 Qt/KDE 綁定,可以在 Java 中使用 Qt/KDE 類,還包括對(duì) C、Perl、Python 的綁定,也可以在這些語(yǔ)言中使用 DCOP,還包括了 XParts,將非 KDE 應(yīng)用程序作為一個(gè) KPart 嵌入使用。
DCOP 一般用于動(dòng)態(tài)管理Linux運(yùn)行時(shí)軟件配置框架,一般的Linux軟件在運(yùn)行時(shí)讀取配置文件后,所有的參數(shù)不可再次調(diào)整,而Dcop能夠在啟動(dòng)軟件后,再次根據(jù)需求去配置軟件各項(xiàng)參數(shù)。
普遍使用的D-Bus
現(xiàn)如今,在Linux 中使用廣泛的D-Bus 又是什么呢?
D-Bus是一個(gè)有面向?qū)ο蠼涌诘膮f(xié)議框架,以及應(yīng)用程序用戶互相發(fā)現(xiàn)和監(jiān)視的守護(hù)進(jìn)程。也就是說,這是一個(gè)進(jìn)程間的通訊系統(tǒng),是由兩個(gè)守護(hù)進(jìn)程,一個(gè)是系統(tǒng)范圍,一個(gè)是用戶會(huì)話范圍,提供了生命周期內(nèi)的跟蹤、服務(wù)激活、安全檢查等高級(jí)功能。這樣的守護(hù)進(jìn)程可以啟動(dòng)服務(wù)以便給其它程序提供某些功能。D-Bus 可以看作DCOP的升級(jí)版,比DCOP要復(fù)雜一些,而且DCOP主要用作桌面應(yīng)用之間的通信。
但是,D-bus 也不是一個(gè)普遍適用的通訊系統(tǒng),這一點(diǎn)和Corba等明顯不同。在設(shè)計(jì)之初,D-Bus 設(shè)計(jì)被用來(lái)作為用戶交互接口與系統(tǒng)服務(wù)之間的解耦和通信,以及系統(tǒng)服務(wù)之間的通信。對(duì)于 D-Bus而言,由于不信任對(duì)端發(fā)來(lái)的數(shù)據(jù),一定要做復(fù)雜的校驗(yàn),導(dǎo)致比直接使用socket讀寫數(shù)據(jù)慢2.5倍,甚至比DCOP乃至Corba等通訊機(jī)制都要慢一些。
Corba,又是一個(gè)久遠(yuǎn)的存在,20多年前的Corba 實(shí)現(xiàn)Orbit都要比D-Bus快,Corba和D-Bus都使用了二機(jī)制的通訊協(xié)議,但Corba 更通用和開放。然而,D-Bus很多地方都是硬編碼,所以D-Bus要比Corba簡(jiǎn)單得多。
DCOM 是Windows 下的IPC系統(tǒng),類似于Corba,由于老碼農(nóng)已經(jīng)多年不涉及Windows 平臺(tái)的軟件開發(fā)了,也不知道現(xiàn)在發(fā)展到怎樣的程度了。
面向嵌入式的ubus
OpenWrt 提供的ubus,類似于Linux桌面系統(tǒng)的D-Bus,目標(biāo)也是提供系統(tǒng)級(jí)的進(jìn)程間通信功能。在設(shè)計(jì)理念上基本一致,但與D-Bus相比減少了內(nèi)存空間的占用,可以更適合嵌入式Linux低內(nèi)存和低CPU性能的特殊環(huán)境。
ubus是OpenWrt的RPC工具大約是在2011年加入OpenWrt中的。為了提供各種后臺(tái)進(jìn)程和應(yīng)用程序之間的通信機(jī)制,ubus模塊由3部分組成:
- ubusd精靈進(jìn)程。
- ubus接口庫(kù)
- ubus命令行工具
ubus模塊的核心是ubusd精靈進(jìn)程,在系統(tǒng)啟動(dòng)時(shí)運(yùn)行,負(fù)責(zé)進(jìn)程間的消息路由和傳遞。其他進(jìn)程注冊(cè)到 ubusd進(jìn)程進(jìn)行消息的發(fā)送和接收,這個(gè)接口是用L文件socket和TLV收發(fā)消息來(lái)實(shí)現(xiàn)的。每一個(gè)進(jìn)程在指定命名空間下注冊(cè)自己的路徑。每一個(gè)路徑都可以提供帶有各種參數(shù)的多個(gè)函數(shù)處理過程,函數(shù)處理程序可以在完成處理后返回消息。
ubus提供的功能主要有以下4個(gè)方面:
- 提供注冊(cè)對(duì)象和方法供其他實(shí)體調(diào)用。
- 調(diào)用其他應(yīng)用程序提供的注冊(cè)對(duì)象的控制接口。
- 在特定對(duì)象上注冊(cè)監(jiān)聽事件。
- 向特定對(duì)象發(fā)送事件消息。
ubus主要用于兩個(gè)進(jìn)程之間的通信,能夠以JSON格式和用戶進(jìn)行數(shù)據(jù)交換,不用關(guān)心消息的實(shí)際傳輸格式。ubus代碼基于LGPL2.1發(fā)布,在OpenWrt 12.09版開始正式使用。
面向內(nèi)核環(huán)境的KDBUS
kdbus是在內(nèi)核里實(shí)現(xiàn)的D-Bus,可傳輸大數(shù)據(jù)塊乃至GB級(jí)的消息流,可做到消息傳遞的零拷貝,在最壞情況下,一條消息及其回復(fù)過程不超過2次拷貝,2次驗(yàn)證和2次上下文切換。全部的憑據(jù)信息(用戶ID,進(jìn)程ID,cgroup信息,權(quán)限等)隨每個(gè)消息傳遞,而且所有消息都有時(shí)間戳。
kdbus在內(nèi)核中作為一個(gè)字符設(shè)備,先要open設(shè)備,再調(diào)用mmap()將一個(gè)消息傳遞區(qū)域映射到自己的地址空間。消息在這個(gè)區(qū)域組裝后交給內(nèi)核傳輸,內(nèi)核簡(jiǎn)單地將消息從一個(gè)進(jìn)程映射的區(qū)域拷貝到另一個(gè)進(jìn)程的區(qū)域。一般地,kdbus通過memfd機(jī)制實(shí)現(xiàn)消息傳遞的零拷貝。memfd是一塊帶有文件描述符的內(nèi)存區(qū)域,可以被“密封”,即擁有它的進(jìn)程不能再改變其內(nèi)容。要傳遞一條消息,進(jìn)程先在memfd區(qū)域構(gòu)造消息,密封,然后交給kdbus傳輸。內(nèi)核可以把相應(yīng)的內(nèi)存頁(yè)面映射到接收進(jìn)程的地址空間,從而避免拷貝數(shù)據(jù),這取決于消息的大小。消息比較小時(shí)內(nèi)存映射的開銷比較大,這時(shí)是直接拷貝數(shù)據(jù)。消息還可以攜帶對(duì)收到回復(fù)的時(shí)間限制(“方法調(diào)用窗口”)。
由于處于內(nèi)核中,kdbus隨時(shí)可用,不需要類似D-Bus那樣的守護(hù)進(jìn)程啟動(dòng),Linux安全模塊可以直接與其掛鉤,可避免競(jìng)態(tài)條件,API也得到了簡(jiǎn)化。另外,kdbus信號(hào)廣播機(jī)制采用布隆過濾器來(lái)選擇接受者,也提高了廣播的效率。
遺憾的是, kdbus 曾經(jīng)試圖合入到主流發(fā)行版的內(nèi)核中,但好像沒有成功,前景又讓人有點(diǎn)捉摸不透了。
面向分布式系統(tǒng)的FDBUS
FDBus提供了分布式的進(jìn)程間通信機(jī)制,支持跨主機(jī)的C/S通信,使用服務(wù)名而非物理地址作為尋址方式,通過各種服務(wù)和心跳重連機(jī)制確保連接的動(dòng)態(tài)性和可靠性,進(jìn)而保證系統(tǒng)內(nèi)的節(jié)點(diǎn)可以動(dòng)態(tài)增刪與部署,可以任意重啟,無(wú)需管理啟動(dòng)順序和依賴,通信各方都能保持連接,從而把各個(gè)分立的模塊組成一個(gè)牢固的整體。
從進(jìn)程間通信視角來(lái)看,F(xiàn)DBus和的D-Bus類似,但功能更齊全,性能更高,使用更便利,除了支持主機(jī)內(nèi)的IPC,還能在多個(gè)主機(jī)之間組網(wǎng)。FDBus構(gòu)建于socket(Unix和TCP)之上,采用protocol buffer來(lái)支持各種復(fù)雜的數(shù)據(jù)類型,也支持raw data格式,便于大量數(shù)據(jù)傳輸。FDBus 采用IDL來(lái)定義接口并支持自動(dòng)代碼生成,大大降低序列化和反序列化工作,而且支持安全策略,對(duì)訪問區(qū)劃分了安全等級(jí),確保整個(gè)系統(tǒng)的安全性。
FDBus支持字符串形式的名字作為server地址,通過類似DNS作用的name server自動(dòng)為server分配Unix domain地址和TCP端口號(hào),實(shí)現(xiàn)client和server之間以服務(wù)名稱進(jìn)行尋址。其高性能主要體現(xiàn)在點(diǎn)對(duì)點(diǎn)直接通信,不通過中央Hub或Broker進(jìn)行轉(zhuǎn)發(fā),目前已經(jīng)在Windows,Linux和QNX上得到了驗(yàn)證。作為C/S模式,支持如下通信模式:
- 帶超時(shí)的同步請(qǐng)求/應(yīng)答
- 帶超時(shí)的異步請(qǐng)求/應(yīng)答
- 無(wú)應(yīng)答的命令請(qǐng)求
- 訂閱模式,實(shí)現(xiàn)多點(diǎn)廣播
FDBus不僅僅是IPC機(jī)制,也是一個(gè)中間件開發(fā)框架,包含開發(fā)中間件過程中經(jīng)常用到的公共組件和基礎(chǔ)模型,提供了跨平臺(tái)且功能強(qiáng)大的支持。源碼開放之后,F(xiàn)DBus經(jīng)過更多開發(fā)者的使用、測(cè)試和改進(jìn),逐漸成為眾多中間件開發(fā)框架的候選之一。
xBus 與軟件總線
除了早期的DCOP,上面的幾種進(jìn)程間通信機(jī)制都命名為xBus,為啥呢?在計(jì)算機(jī)領(lǐng)域,Bus 一詞最早出現(xiàn)在硬件架構(gòu)中, 代表總線,是一組能為多個(gè)部件分時(shí)共享的公共信息傳送線路。
從總線所處的位置來(lái)看,分為片內(nèi)總線和片外總線。片內(nèi)總線是CPU內(nèi)部的寄存器、算術(shù)邏輯部件、控制部件以及總線接口部件之間的公共信息通道,片外總線則泛指CPU與外部器件之間的公共信息通道,我們談到的總線一般指的是片外總線。
從總線傳輸方式的設(shè)計(jì)視角來(lái)看,計(jì)算機(jī)總線有串行總線和并行總線,可以由一個(gè)或多個(gè)通道組成,每個(gè)通道是單線連接,數(shù)據(jù)的傳輸方式將根據(jù)通道的數(shù)量而有所不同。
從通信用途的視角來(lái)看,總線又可以分為3種:地址總線、數(shù)據(jù)總線、控制總線。地址總線用于指定CPU將要操作的內(nèi)存地址;數(shù)據(jù)總線用于讀寫內(nèi)存的數(shù)據(jù),控制總線用于發(fā)送和接受信號(hào),比如中斷、設(shè)備復(fù)位等信號(hào),CPU收到信號(hào)后進(jìn)行響應(yīng),這時(shí)則需要控制總線。
在CPU、內(nèi)存與外設(shè)確定的情況下,計(jì)算機(jī)的總線速度是制約計(jì)算機(jī)整體性能的關(guān)鍵。
計(jì)算機(jī)的軟件總線是一種虛擬的存在,它是在計(jì)算機(jī)硬件總線的功能含義類比的基礎(chǔ)上得到的定義。軟件總線是軟件工程人員為了進(jìn)一步保證軟件系統(tǒng)建設(shè)的規(guī)范性,以及提高計(jì)算機(jī)系統(tǒng)的應(yīng)用價(jià)值而提出的一種設(shè)計(jì)理念。軟件總線可以將各種軟件進(jìn)行相互連接,組成一個(gè)通用的操作平臺(tái),通常表現(xiàn)為一個(gè)接口界面。作為一種軟件模塊,軟件總線為各個(gè)軟件組成部分進(jìn)行準(zhǔn)確的數(shù)據(jù)傳輸,同時(shí)為各種軟件提供虛擬共享的通道和接口。
軟件總線源于分布式異構(gòu)環(huán)境的搭建所提出的,軟件復(fù)用、構(gòu)件化以及面向?qū)ο蠹夹g(shù)的發(fā)展促進(jìn)了它的形成。軟件總線只是對(duì)軟件的構(gòu)件進(jìn)行組裝而不是更改,這不僅有效的提高了軟件開發(fā)的工作效率,縮短了軟件開發(fā)的周期。前面提到的各種xBus,都可以看作軟件總線的一種實(shí)現(xiàn)。
HarmonyOS的分布式軟總線
鴻蒙的分布式軟總線是為了解決所有1+8+N設(shè)備之間的互聯(lián)互通問題,在華為提出的1+8+N中:1指的是手機(jī),8指的是車機(jī)、音箱、耳機(jī)、手表/手環(huán)、平板、大屏、PC、AR/VR,N指的是其他IOT設(shè)備。一般情況下,用戶都是通過手動(dòng)操作的方式進(jìn)行設(shè)備之間的連接,隨著外圍設(shè)備越來(lái)越多,手動(dòng)操作的方式不方便,甚至?xí)绊懹脩舻捏w驗(yàn)。HarmonyOS的分布式總線技術(shù)是為了能夠讓所有的設(shè)備之間能夠方便、高效的互聯(lián)。
HarmonyOS分布式軟總線最主要的功能包括:發(fā)現(xiàn)、連接、組網(wǎng)/拓?fù)涔芾?、任?wù)總線、數(shù)據(jù)總線。其中,”發(fā)現(xiàn)”指的是搜索周圍是否有相關(guān)設(shè)備;”連接”指的是與所發(fā)現(xiàn)的設(shè)備建立連接;”組網(wǎng)/拓?fù)涔芾怼敝傅氖菍?duì)所有發(fā)現(xiàn)的設(shè)備進(jìn)行網(wǎng)絡(luò)拓?fù)涔芾?,比如組成星狀網(wǎng)絡(luò)拓?fù)洌蛘呤墙M成Mesh網(wǎng)絡(luò)拓?fù)??!比蝿?wù)總線”指的是在所建立的網(wǎng)絡(luò)拓?fù)浠A(chǔ)上,用于傳輸小數(shù)據(jù)量信息的通路?!睌?shù)據(jù)總線”指的是用于傳輸較大數(shù)據(jù)量信息的通路。發(fā)現(xiàn)與組網(wǎng)是分布式軟總線的核心術(shù),目前沒有開到公開的細(xì)節(jié)信息。
把眾多外圍設(shè)備連接形成網(wǎng)絡(luò)后,需要保證各個(gè)設(shè)備在時(shí)間上的同步。尤其是IoT設(shè)備,由于成本方面的原因,晶振的質(zhì)量可能比較差,會(huì)存在相對(duì)較大的頻率漂移。分布式軟總線關(guān)鍵技術(shù)之一是時(shí)鐘同步算法,將不同設(shè)備原本不同步的時(shí)鐘做到統(tǒng)一同步。在軟時(shí)鐘算法的同步下,就可以進(jìn)行資源的調(diào)度。軟總線技術(shù)中提出了LaneHub的概念,可以理解為調(diào)度管理各通信通路的模塊。通過軟總線的LaneHub可以對(duì)這不同連接方式的設(shè)備進(jìn)行統(tǒng)一調(diào)度,達(dá)到減少干擾、提升速率的目的。
在分布式軟總線的基礎(chǔ)上,華為提出了”超級(jí)終端”的概念,就是通過分布式軟總線技術(shù)將手機(jī)外圍的其他相關(guān)設(shè)備連接在一起,形成了所謂的”超級(jí)終端”,即個(gè)體終端變成了群體終端。
一句話小結(jié)
盡管“一切程序都會(huì)歸于系統(tǒng)調(diào)用”,但軟件工程的效率提升是業(yè)界不變的追求,從進(jìn)程間通信到分布式軟總線也是如此,或許,基于FDBUS就可以相對(duì)容易地開發(fā)出類似HarmonyOS的分布式軟總線呢。
【參考資料】
- https://gitee.com/Janisa/Dcop/
- http://dbus.freedesktop.org/doc/dbus-faq.html
- https://github.com/skawu/fdbus
- https://git.openwrt.org/project/ubus.git
- https://developer.harmonyos.com/
- https://www.bilibili.com/video/BV16b4y1h75z?spm_id_from=333.999.0.0