Linux DBUS匯流排__Linux

來源:互聯網
上載者:User

D-Bus三層架構

D-Bus是一個為應用程式間通訊的訊息匯流排系統, 用於進程之間的通訊。它是個3層架構的IPC 系統,包括:

1、函數庫libdbus ,用於兩個應用程式互相聯絡和互動訊息。

2、一個基於libdbus構造的訊息匯流排守護進程,可同時與多個應用程式相連,並能把來自一個應用程式的訊息路由到0或者多個其他程式。

3、基於特定應用程式架構的封裝庫或捆綁(wrapper libraries or bindings )。例如,libdbus-glib和libdbus-qt,還有綁定在其他語言,例如Python的。大多數開發人員都是使用這些封裝庫的API,因為它們簡化了D-Bus編程細節。libdbus被有意設計成為更高層次綁定的底層後端(low-levelbackend )。大部分libdbus的 API僅僅是為了用來實現綁定。

 

匯流排

  在D-Bus中,“bus”是核心的概念,它是一個通道:不同的程式可以通過這個通道做些操作,比如方法調用、發送訊號和監聽特定的訊號。在一台機器上匯流排守護有多個執行個體(instance)。這些匯流排之間都是相互獨立的。

一個持久的系統匯流排(system bus):

它在引導時就會啟動。這個匯流排由作業系統和後台進程使用,安全性非常好,以使得任意的應用程式不能欺騙系統事件。它是案頭會話和作業系統的通訊,這裡作業系統一般而言包括核心和系統守護進程。這種通道的最常用的方面就是發送系統訊息,比如:插入一個新的存放裝置;有新的網路連接;等等。

還將有很多會話匯流排(session buses):

這些匯流排當使用者登入後啟動,屬於那個使用者私人。它是使用者的應用程式用來通訊的一個會話匯流排。同一個案頭會話中兩個傳統型應用程式的通訊,可使得案頭會話作為整體整合在一起以解決進程生命週期的相關問題。這在GNOME和KDE案頭中大量使用。

  對於一些遠端工作站,在system bus中可能會有一些問題,例如熱插拔,是否需要通知遠端的terminal,這會使得kernel暴露一些裝置的能力,不過,我們現在關心D-Bus,是因為手持終端裝置的使用,這些將不會出現。在Internet Tablet,也包括我們的手機系統,所有的應用程式都是使用一個使用者ID啟動並執行,所以只有一個會話通道,這一點是和Linux案頭系統是有明顯區別的。

  D-Bus是低延遲而且低開銷的,設計得小而高效,以便最小化傳送的往返時間。另外,協議是二進位的,而不是文本的,這樣就排除了費時的序列化過程。從開發人員的角度來看,D-BUS 是便於使用的。有線協議容易理解,客戶機程式庫以直觀的方式對其進行封裝。D-Bus的主要目的是提供如下的一些更高層的功能:

A、結構化的名字空間

B、獨立於架構的資料格式

C、支援訊息中的大部分通用資料元素

D、帶有異常處理的通用遠程調用介面

E、支援廣播類型的通訊

 

Bus daemon匯流排守護

       Bus daemon是一個特殊的進程:這個進程可以從一個進程傳遞訊息給另外一個進程。當然了,如果有很多applications連結到這個通道上,這個 daemon進程就會把訊息轉寄給這些連結的所有程式。在最底層,D-Bus只支援點對點的通訊,一般使用本地通訊端(AF_UNIX)在應用和bus daemon之間通訊。D-Bus的點對點是經過busdaemon抽象過的,由busdaemon來完成定址和發送訊息,因此每個應用不必要關心要把訊息發給哪個進程。D-Bus發送訊息通常包含如下步驟(正常情況下):

建立和發送訊息 給後台bus daemon進程,這個過程中會有兩個內容相關的切換。

後台bus daemon進程會處理該訊息,並轉寄給目標進程,這也會引起內容相關的切換目標程式接收到訊息,然後根據訊息的種類,做不同的響應:要麼給個確認、要麼應答、還有就是忽略它。最後一種情況對於“通知”類型的訊息而言,前兩種都會引起進一步的環境切換。

綜上原因,如果你準備在不同的進程之間傳遞大量的資料,D-Bus可能不是最有效方法,最有效方法是使用共用記憶體,但是對共用記憶體的管理也是相當複雜的。

 

D-Bus進程通訊簡單架構

 

D-Bus常見概念

原生對象和物件路徑

所有使用D-BUS的應用程式都包含一些對象, 當經由一個D-BUS串連收到一條訊息時,該訊息是被發往一個對象而不是整個應用程式。在開發中程式架構定義著這樣的對象,例如JAVA,GObject,QObject等等,在D-Bus中成為native object。

對於底層的D-Bus協議,即libdbus API,並不理會這些native object,它們使用的是一個叫做object path的概念。通過object path,高層編程可以為對象執行個體進行命名,並允許遠程應用引用它們。這些名字看起來像是檔案系統路徑,例如一個對象可能叫做“/org/kde/kspread/sheets/3/cells/4/5”。易讀的路徑名是受鼓勵的做法,但也允許使用諸如“/com/mycompany/c5yo817y0c1y1c5b”等,只要它可以為你的應用程式所用。Namespacing的物件路徑以開發人員所有的網域名稱開始(如 /org/kde)以避免系統不同代碼模組互相干擾。

簡單地說:一個應用建立對象執行個體進行D-Bus的通訊,這些對象執行個體都有一個名字,命名方式類似於路徑,例如/com/mycompany,這個名字在全域(session或者system)是唯一的,用於訊息的路由。

 

方法和訊號Methodsand Signals

每一個對象有兩類成員:方法和訊號。方法就是JAVA中同樣概念,方法是一段函數代碼,帶有輸入和輸出。訊號是廣播給所有興趣的其他實體,訊號可以帶有資料payload。

在 D-BUS 中有四種類型的訊息:方法調用(method calls)、方法返回(method returns)、訊號(signals)和錯誤(errors)。要執行 D-BUS 對象的方法,您需要向對象發送一個方法調用訊息。它將完成一些處理(就是執行了對象中的Method,Method是可以帶有輸入參數的。)並返回,返回訊息或者錯誤訊息。訊號的不同之處在於它們不返回任何內容:既沒有“訊號返回”訊息,也沒有任何類型的錯誤訊息。

 

介面Interface

每一個對象支援一個或者多個介面,介面是一組方法和訊號,介面定義一個對象實體的類型。D-Bus對介面的命名方式,類似org.freedesktop.Introspectable。開發人員通常將使用程式設計語言類的的名字作為介面名字。

 

Proxies代理

代理對象用來表示其他的remote object。當我們觸發了proxy對象的method時,將會在D-Bus上發送一個method_call的訊息,並等待回覆,根據回覆返回。使用非常方便,就像調用一個本地的對象。

 

Bus Names匯流排名字

  當一個應用串連到bus daemon,daemon立即會分配一個名字給這個串連,稱為unique connection name ,這個唯一標識的名字以冒號:開頭,例如:34-907,這個名字在daemon的整個生命週期是唯一的。但是這種名字總是臨時分配,無法確定的,也難以記憶,因此應用可以要求有另外一個名字well-known name 來對應這個唯一標識,就像我們使用網域名稱來對應IP地址一樣。例如可以使用com.mycompany來映射:34-907。應用程式可能會要求擁有額外的周知名字(well-knownname )。例如,你可以寫一個規範來定義一個名字叫做 com.mycompany.TextEditor。你的協議可以指定自己擁有這個名字,一個應用程式應該在路徑/com/mycompany /TextFileManager下有一個支援介面org.freedesktop.FileHandler的對象。應用程式就可以發送訊息到這個匯流排名字,對象,和介面以執行方法調用。

當一個應用結束或者崩潰是,OS kernel會關閉它的匯流排串連。匯流排發送notification訊息告訴其他應用,這個應用的名字已經失去他的owner。當檢測到這類notification時,應用可以知道其他應用的生命週期。這種方式也可用於只有一個執行個體的應用,即不開啟同樣的兩個應用的情況。

 

地址

串連建立有server和client,對於bus daemon,應用就是client,daemon是server。一個D-Bus的地址是指server用於監聽,client用於串連的地方,例如unix:path=/tmp/abcedf標識server將在路徑/tmp/abcedf的UNIX domain socket監聽。地址可以是指定的TCP/IP socket或者其他在或者將在D-Bus協議中定義的傳輸方式。

  如果使用bus daemon,libdbus將通過讀取環境變數自動擷取session bus damon的地址,通過檢查一個指定的UNIX domain socket路徑擷取system bus的地址。如果使用D-bus,但不是daemon,需要定義那個應用是server,那個是client,並定義一套機制是他們認可server的地址,這不是通常的做法。

  通過上面的描述,我們可以獲得下面的視圖:

Address –> [BusName] –> Path –> Interface –> Method

bus name不是必要的,它只在daemon的情況下用於路由,點對點的直接連接是不需要的。

簡單地說:Address是D-Bus中server用來監聽client的地址,當一個client串連上D-Bus,通常是Daemo的方式,這個client就有了一個Bus Name。其他應用可以根據訊息中所帶的Bus Name,來判斷和哪個應用相關。訊息在匯流排中傳遞的時候,傳遞到應用中,再根據objectpath,送至應用中具體的對象執行個體中,也就是是應用中根據Interface建立的對象。這些Interface有method和singal兩種,用來發送、接收、響應訊息。

 

一個例子的示意圖:

 

D-Bus 訊息

訊息通過D-Bus在進程間傳遞。有四類訊息:

一、Method call訊息:將觸發對象的一個method 

二、Method return訊息:觸發的方法返回的結果

       三、Error訊息:觸發的方法返回一個異常 

四、Signal訊息:通知,可以看作為事件訊息。

 

一個訊息有訊息頭header,裡面有field,有一個訊息體body,裡面有參數arguments。訊息頭包含訊息體的路由資訊,訊息體就是淨荷payload。頭欄位可能包括髮送者的bus名,目的地的bus名,方法或者signal名等等,其中一個頭欄位是用於描述body中的參數的類型,例如“i”標識32位整數,"ii”表示淨荷為2個32為整數。

 

發送Method call訊息的情境

  一個method call訊息從進程A到進程B,B將應答一個method return訊息或者error訊息。在每個call訊息帶有一個序號,應答訊息也包含同樣的號碼,使之可以對應起來。他們的處理過程如下:

如果提供proxy,通過觸發本地一個對象的方法從而觸發另一個進程的遠端對象的方法。應用調用proxy的一個方法,proxy構造一個method call訊息發送到遠端進程。

對於底層的API,不使用proxy,應用需要自己構造method call訊息。

一個method call訊息包含:遠端進程的bus name,方法名字,方法的參數,遠端進程中object path,可選的介面名字。

method call訊息發送到bus daemon

bus daemon查看目的地的bus name。如果一個進程對應這個名字,bus daemon將method call訊息發送到該進程中。如果沒有發現匹配,bus daemon建立一個error訊息作為應答返回。

進程接收後將method call訊息分拆。對於簡單的底層API情況,將立即執行方法,並發送一個method reply訊息給bus daemon。對於高層的API,將檢查對象path,interface和method,觸發一個native object的方法,並將傳回值封裝在一個method reply訊息中。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.