日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux 进程间通信 dbus-glib【实例】详解三 数据类型和dteeth(类型签名type域)(层级结构:服务Service --> Node(对象、object) 等 )(附代码)

發布時間:2025/3/20 linux 41 豆豆

linux 進程間通信 dbus-glib【實例】詳解一(附代碼)(d-feet工具使用)

linux 進程間通信 dbus-glib【實例】詳解二(上) 消息和消息總線(附代碼)

linux 進程間通信 dbus-glib【實例】詳解二(下) 消息和消息總線(ListActivatableNames和服務器的自動啟動)(附代碼)

linux 進程間通信 dbus-glib【實例】詳解三 數據類型和dteeth(類型簽名type域)(層級結構:服務Service --> Node(對象、object) 等 )(附代碼)

linux 進程間通信 dbus-glib【實例】詳解四(上) C庫 dbus-glib 使用(附代碼)(編寫接口描述文件.xml,dbus-binding-tool工具生成綁定文件)

注意層級:服務Service --> Node(對象、object) --> 接口Interface --> 方法Method & 信號Signal

文章目錄

  • 1、dbus的數據類型
  • 2、dteeth
    • 2.1、運行dteeth
    • 2.2、源代碼
    • 2.3、dteeth的主要邏輯
    • 2.3、_introspect_parser的輸出格式
  • 3、python基礎
    • 3.1、代碼塊和縮進
    • 3.2、腳本文件格式
    • 3.3、列表、元組和字典
    • 4、結束語

我想在freerunner(一個開源linux手機)上查看fso(openmoko的諸多軟件版本之一)的dbus信息。但fso的python沒有gtk模塊,跑不了d-feet。 在上一講我介紹了d-feet的基本思路:用“org.freedesktop.DBus.ListNames”枚舉消息總線上的連接,用“org.freedesktop.DBus.Introspectable.Introspect” 從"/"開始遍歷連接的對象樹。上一講我們手工查看了兩個連接,那么我們能不能寫一個程序自動遍歷連接的對象樹, 輸出指定連接的所有對象的所有接口的所有方法和信號?

當然可以,為此我寫了一個叫dteeth的python腳本。不過在介紹這個腳本前,讓我們先看看dbus的數據類型。

1、dbus的數據類型

dbus用xml描述接口,例如:

<?xml version="1.0" encoding="UTF-8" ?><node name="/org/freesmartphone/GSM/Device"><interface name="org.freesmartphone.GSM.SMS"><method name="SendMessage"><arg name="number" type="s"/><arg name="contents" type="s"/><arg name="featuremap" type="a{sv}"/><arg type="i" direction="out"/></method><signal name="IncomingMessage"><arg name="address" type="s"/><arg name="contents" type="s"/><arg name="features" type="a{sv}"/></signal></interface> </node>

其實前兩講已經看過很多例子了。node就是接口中的對象,

node可以包含node,構成對象樹。 dbus的接口描述文件統一采用utf-8編碼。 我相信讀者很容易理解這個接口描述文件。我只想解釋一下描述參數數據類型的type域。 dbus的數據類型是由"s"或"a{sv}"這樣的類型簽名(Type Signatures)定義的。 類型簽名中可以使用以下標記:


a表示數組,數組元素的類型由a后面的標記決定。例如:

  • "as"是字符串數組。
  • 數組"a(i(ii))"的元素是一個結構。用括號將成員的類型括起來就表示結構了,結構可以嵌套。
  • 數組"a{sv}“的元素是一個鍵-值對。”{sv}"表示鍵類型是字符串,值類型是VARIANT。

在以后的例子中,我們會親手實現上面這個xml描述的接口,包括服務器和客戶程序。 到時候,讀者會對dbus的數據類型有更直觀的認識。

2、dteeth

2.1、運行dteeth

可以從這里下載dteeth的源代碼。其中包含兩個python腳本:dteeth.py和_introspect_parser.py。 dteeth.py是我寫的。_introspect_parser.py是個開源模塊,可以分析Introspect返回的xml數據。

dteeth用法如下:

$ ./dteeth.py -h Usage: dteeth [--system] <name of a connection on the bus >

默認連接session總線,除非你加上–system。可以一次指定同一消息總線的多個連接。先在PC上試一試:

$ ./dteeth.py org.fmddlmyy.Test org.fmddlmyy.Test/TestObjorg.fmddlmyy.Test.BasicmethodsAdd( in i arg0 , in i arg1 , out i ret )org.freedesktop.DBus.IntrospectablemethodsIntrospect( out s data )org.freedesktop.DBus.PropertiesmethodsSet( in s interface , in s propname , in v value )GetAll( in s interface , out a{sv} props )Get( in s interface , in s propname , out v value )

我也在fso版本的freerunner手機上運行了一下,得到了org.freesmartphone.ogsmd的所有對象的所有的接口的所有方法和信號:(打印出來太多了,略)

2.2、源代碼

下面是dteeth的源代碼:

$ cat -n dteeth.py1 #!/usr/bin/env python2 # -*- coding: utf-8 -*-34 import dbus5 import _introspect_parser6 import getopt, sys78 MARGIN_WIDTH = 49 ONE_MARGIN = ' ' * MARGIN_WIDTH1011 # signal是個元組,它有一個元素,是一個列表。列表的元素是signal的參數12 # 列表的每個元素都是字典。它有兩個元素,鍵值分別是'type'和'name'13 def show_signal(name, signal, margin):14 print margin+name+'(',15 args = signal[0]16 for i, arg in enumerate(args):17 if i > 0:18 print ',',19 if arg['name']:20 print '%s %s' % (arg['type'], arg['name']),21 else:22 print '%s' % arg['type'],23 print ')'2425 # method是個元組,它有兩個元素,都是列表。前一個列表的元素是輸入參數,后一個列表的元素是輸出參數26 def show_method(name, method, margin):27 print margin+name+'(',28 # 輸入參數29 args = method[0]30 in_num = len(args)31 out_num = len(method[1])32 for i, arg in enumerate(args):33 if i > 0:34 print ',',35 if arg['name']:36 print 'in %s %s' % (arg['type'], arg['name']),37 else:38 print 'in %s' % arg['type'],39 # 輸出參數40 if (in_num > 0) and (out_num > 0) :41 print ',',42 args = method[1]43 for i, arg in enumerate(args):44 if i > 0:45 print ',',46 if arg['name']:47 print 'out %s %s' % (arg['type'], arg['name']),48 else:49 print 'out %s' % arg['type'],50 print ')'5152 def show_property(name, property, margin):53 print margin+name54 print margin,55 print property5657 # interfaces是個字典,它有三個元素,鍵值分別是'signals'、'methods'和'properties'58 def show_iface(name, iface, margin):59 print margin + name60 margin += ONE_MARGIN61 signals=iface['signals']62 l = len(signals)63 if l > 0:64 print margin+'signals'65 for node in signals:66 show_signal(node, signals[node], margin+ONE_MARGIN)6768 methods=iface['methods']69 l = len(methods)70 if l > 0:71 print margin+'methods'72 for node in methods:73 show_method(node, methods[node], margin+ONE_MARGIN)7475 properties=iface['properties']76 l = len(properties)77 if l > 0:78 print margin+'properties'79 for node in properties:80 show_property(node, properties[node], margin+ONE_MARGIN)8182 def show_obj(bus, name, obj_name, margin):83 obj=bus.get_object(name, obj_name)84 iface=dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')85 xml=iface.Introspect();86 data = _introspect_parser.process_introspection_data(xml)8788 # data是個字典,它有兩個元素,鍵值分別是'child_nodes'和'interfaces'89 if len(data['interfaces']) > 0:90 print margin + obj_name9192 for node in data['interfaces']:93 iface=data['interfaces'][node]94 show_iface(node, iface, margin+ONE_MARGIN)9596 for node in data['child_nodes']:97 if obj_name == '/':98 show_obj(bus, name, '/' + node, margin)99 else:100 show_obj(bus, name, obj_name + '/' + node, margin)101102 def show_connection(bus, name, margin):103 print margin + name104 show_obj(bus, name, '/', margin+ONE_MARGIN)105106 def usage():107 print "Usage: dteeth [--system] "108109 def main():110 try:111 opts, args = getopt.getopt(sys.argv[1:], "h", ["help", "system"])112 except getopt.GetoptError, err:113 # print help information and exit:114 print str(err) # will print something like "option -a not recognized"115 usage()116 sys.exit(2)117118 if len(args) == 0:119 usage()120 sys.exit(2)121122 use_system = False123 for o, a in opts:124 if o in ("-h", "--help"):125 usage()126 sys.exit()127 if o == "--system":128 use_system = True129 else:130 assert False, "unhandled option"131132 if use_system:133 bus=dbus.SystemBus()134 else:135 bus=dbus.SessionBus()136137 for arg in args:138 show_connection(bus, arg, "")139140 if __name__ == "__main__":141 main()

dteeth是我寫的第一個超過10行的python腳本。對于熟悉python的讀者,dteeth應該是很簡單的。 不過我還是簡單解釋一下dteeth的主要邏輯。

2.3、dteeth的主要邏輯

main函數分析命令行,對命令行上指定的每個連接調用show_connection函數。 show_connection在打印連接名后調用show_obj函數。show_obj從根對象"/"開始遍歷連接的對象樹。

show_obj對輸入對象調用Introspect方法,返回的xml數據交由_introspect_parser處理。 _introspect_parser會從xml數據中分出inerface和node。 show_obj對inerface調用show_iface顯示。 show_obj對node會遞歸調用show_obj,實現對象樹的遍歷。

2.3、_introspect_parser的輸出格式

_introspect_parser.process_introspection_data函數分析Introspect方法返回的xml數據。 為了了解_introspect_parser的輸出格式,我們可以寫個小腳本:

$ cat ti.py #!/usr/bin/env python import dbus import _introspect_parser bus=dbus.SessionBus() obj=bus.get_object('org.freesmartphone.ogsmd', '/org/freesmartphone/GSM/Device') iface=dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable') xml=iface.Introspect(); data = _introspect_parser.process_introspection_data(xml) print data

可以用這個腳本直接打印process_introspection_data返回的數據。下面是整理后的輸出:

{'interfaces': {u'org.freedesktop.DBus.Introspectable': {'signals': {}, 'methods': {u'Introspect': ([], [{'type': u's', 'name': u'data'}])}, 'properties': {}}, u'org.freedesktop.DBus.Properties': {'signals': {}, 'methods': {u'Set': ([{'type': u's', 'name': u'interface'}, {'type': u's', 'name': u'propname'}, {'type': u'v', 'name': u'value'}], []), u'GetAll': ([{'type': u's', 'name': u'interface'}], [{'type': u'a{sv}', 'name': u'props'}]), u'Get': ([{'type': u's', 'name': u'interface'}, {'type': u's', 'name': u'propname'}], [{'type': u'v', 'name': u'value'}])}, 'properties': {}}, u'org.freesmartphone.GSM.SMS': {'signals': {u'IncomingMessage': ([{'type': u's', 'name': None}, {'type': u's', 'name': None}, {'type': u'a{sv}', 'name': None}],)},'methods': {u'SendMessage': ([{'type': u's', 'name': u'number'}, {'type': u's', 'name': u'contents'}, {'type': u'a{sv}', 'name': u'featuremap'}], [{'type': u'i', 'name': u'arg3'}])},'properties': {}}}, 'child_nodes': [] }

所有字符串前面都有前綴u,表示這些字符串都是Unicode編碼。在python中,字典用{},元組用(),列表用[]。從括號我們就能看出數據格式。

我們看到process_introspection_data返回返回一個字典。這個字典有兩個映射。一個映射的鍵值是"interfaces",另一個映射的鍵值是"child_nodes"。

映射"child_nodes"的值是一個列表,列出所有子節點的名稱。

映射"interfaces"的值還是一個字典。這個字典的每個映射的鍵值是一個接口名稱。每個映射的值類型還是字典, 這個字典有3個映射,映射的鍵值分別是’signals’、‘methods’和’properties’,映射的值類型都是字典。

'signals’對應字典的每個鍵值是一個信號名稱。每個映射的值類型是元組。這個元組只有一個元素,類型是列表, 即信號的參數列表。

參數列表的元素類型是字典。這個字典有2個映射,映射的鍵值分別是’type’和’name’。'type’是參數類型,'name’是參數名稱。 映射的值類型都是字符串。

'methods’對應字典的每個鍵值是一個方法名稱。每個映射的值類型是元組。這個元組有兩個元素,類型是列表, 分別是方法的輸入參數列表和輸出參數列表。參數列表的元素類型和信號的參數列表相同。

我看到’properties’映射都是空的,就沒有研究。

3、python基礎

簡單介紹一下與dteeth有關的python語法。

3.1、代碼塊和縮進

python用縮進來區分語句所屬的代碼塊,從類定義、函數到for、if的代碼塊都是用縮進來去區分的。 沒有縮進的代碼塊是腳本的主體代碼。 一個腳本文件也被稱作一個模塊。 不管模塊被直接運行還是被其它模塊導入,主體代碼都會在載入時被執行。 例如dteeth的主體代碼只有兩句:

140 if __name__ == "__main__":141 main()

__xxx__這樣的標志符通常是python的系統變量。如果模塊被導入,__name__的值是模塊的名字。 如果模塊被直接執行,__name__的值是"__main__"。 我們通常在模塊被直接執行時,調用主函數或模塊的測試函數。

3.2、腳本文件格式

python腳本的起始行通常是:/p>

1 #!/usr/bin/env python

env是一個可以修改環境變量并執行程序的工具,它可以自動在系統路徑中搜索要執行的程序。 python腳本文件必須以0A為換行符,默認僅支持ASCII字符。 如果要寫中文注釋(顯然是不提倡的),可以在起始行后用以下語句將文件指定為utf-8編碼:

2 # -*- coding: utf-8 -*-

這時,文件必須被保存為沒有BOM的utf-8編碼文件。

3.3、列表、元組和字典

列表類似于C的數組,列表元素用[]包括。元組是不可變的列表,元組元素用()包括。元組的元素個數和類型在創建后就不能改變了。 元組中基本類型的值是不能改變的,但如果元組的一個元素是列表,我們可以改變列表內容, 即我們可以改變元組中可變元素的內容。例如:

>>> a=(1,2,['abc']) >>> a[2]='def' Traceback (most recent call last):File "", line 1, in TypeError: 'tuple' object does not support item assignment >>> a[2][0]='def' >>> a (1, 2, ['def'])

字典是鍵-值對的集合,字典元素用{}包括。

4、結束語

本文介紹了一個叫作dteeth的python腳本。 這個腳本邏輯很簡單,讀者可以根據需要修改或擴充。 講了這么多dbus,我們還沒有接觸C代碼。下一講,我們討論dbus的C實例。

總結

以上是生活随笔為你收集整理的linux 进程间通信 dbus-glib【实例】详解三 数据类型和dteeth(类型签名type域)(层级结构:服务Service --> Node(对象、object) 等 )(附代码)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。