Dbus Implement
前言
最近有一些工作上的要求,所以希望可以導入Dbus的功能到機器上。 所以就開始進行Dbus的相關研究。 希望可以快速並且達到自己想要的功能及目標。
目標
想透過DBus去進行分發,例如下圖所示。透過Server 端去跟Dbus-Daemon註冊某個特定參數,使得Dbus再收到Client端傳來的資料時,可以先濾掉一些特定條件,去確保Server端不會一直收到無意義的資料。
單純透過DBus的內建功能去濾掉不需要收到的資訊。 |
也就是當我要特別處理特殊字串,或是一些我需要後處理而Dbus提供的功能卻無法做到的。 我就必須要使得Server端必須要有收到該資料並且自行去做Filter。而 Filter的callback函式,Dbus是有提供的。也就是定義為Dispatcher的功能。
這樣的做法,算是後處理,就是不透過Dbus的方式去做前處理。
如: http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html#ga66ba7df50d75f4bda6b6e942430b81c7
這樣的做法,算是後處理,就是不透過Dbus的方式去做前處理。
如: http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html#ga66ba7df50d75f4bda6b6e942430b81c7
大家可以參考看看,如果有問題可以提出來,畢竟我也不是很懂~~
只要透過Dispatcher的這種功能,就會讓架構圖變成如下所示。
每個Server都會收到資訊,但是可以確保自己想要看的值是否有超過自己預設的值。 |
當然,也可以將上述兩者進行整合,做到混合性的完整功能,達成我想要的目標,既可以提高效率,也可以針對收到的字串進行處理。
實作方法
實作架構圖 1 的方法:Server Side Partial Code:
1. 先Create a variable to set the param.
1 2 3 4 5 6 7 | memset(tBusMessageRule.acBusMatchRule, 0, sizeof(tBusMessageRule.acBusMatchRule)); snprintf(tBusMessageRule.acBusMatchRule, sizeof(tBusMessageRule.acBusMatchRule), "type=\'%s\',interface=\'%s\',%s", tBusMessageRule.acMessageType, tBusMessageRule.acInterface, pNewRule ); |
2. 定義pNewRule的內容,但是此定義要放在第一點之前喔!! 只是為了要一步一步的分析才這樣放的~
我們期待的pNewRule規則應該要Follow dbus_bus_add_match()的spec要求:http://dbus.freedesktop.org/doc/api/html/group__DBusBus.html
那他的要求會是什麼?
Rules are specified as a string of comma separated key/value pairs
也就是必須是A=B的這種Pairs,基本上他有可以接受的一般定義參數,如下所示:
1: type='signal',sender='org.freedesktop.DBus', interface='org.freedesktop.DBus',member='Foo', path='/bar/foo',destination=':452345.34
那當我想要新增除了這個定義之外的條件規則時該怎麼處理呢?
Possible keys you can match on are type, sender, interface, member, path, destination and numbered keys to match message args (keys are 'arg0', 'arg1', etc.).
看到這個描述,大家可能還是不懂,那我簡單一句話來帶過,要怎麼樣新增除了基本定義之外的參數呢~
1: arg0='test',arg1='test2'.....etc
我想大家應該就懂了
那第二點的code,如下:
我這邊是三維陣列,因為我要存取10個規則,但是每個規則都需要用2維陣列來做儲存,那如果我要存10個,勢必要多開一個陣列。
NewRule的參數就是Result的回傳值。
1 2 3 4 5 6 7 8 9 10 11 12 | for (j = 0; j < MAXRULENUM; j++) { if (tBusMessageRule.tRegisterFormat.acConfigParamSeparate[iIndex][j][0] == '\0') { break; } snprintf (pResult + strlen(pResult), 1024, "arg%d=\'%s\'", j, tBusMessageRule.tRegisterFormat.acConfigParamSeparate[iIndex][j]); if (tBusMessageRule.tRegisterFormat.acConfigParamSeparate[iIndex][j + 1][0] != '\0') { snprintf (pResult + strlen(pResult), 1024, ","); } } |
3. 接下來就是如何使用dbus_bus_add_match()
緊張了吧!!!
這個功能非常的厲害,只要...
1: dbus_bus_add_match(dbconn, tBusMessageRule.acBusMatchRule, &dberr);
Server side的部分已經做完了!
Client Side Partial Code:
client端比較麻煩的就只有送出去的訊息要怎麼送而已!!
這裡會介紹兩種方法去送訊息,但是各有優缺。
以下的兩種方法,在一開始定義argv的時候,必須是用pointer去接或是定義。
1 2 | char *myargv[10]; char **argv = myargv |
如果傳到以下兩個函式,不是*的type,將會出現segmentation fault
1. dbus_message_append_args()
API URL: http://dbus.freedesktop.org/doc/api/html/group__DBusMessage.html#ga591f3aab5dd2c87e56e05423c2a671d9
1 2 3 4 5 6 7 | if (!dbus_message_append_args(dbmsg, DBUS_TYPE_STRING, &argv[0], DBUS_TYPE_STRING, &argv[1], DBUS_TYPE_STRING, &argv[2], DBUS_TYPE_STRING, &argv[3], DBUS_TYPE_INVALID)) { return -1; } |
缺點: 必須要準準的去寫死你要傳幾個Key/pairs,但是程式設計者會以彈性的方式去傳送才對。
優點: 當沒有要求要送什麼的Key/pairs,就可以用這種方法,將自己要傳送的字串直接送出。
定義的部分就是有被寫在spec中! 可以根據提供的type去定義自己要傳送的內容。
2. dbus_message_iter_append_basic()
API URL:
http://dbus.freedesktop.org/doc/api/html/group__DBusMessage.html#ga17491f3b75b3203f6fc47dcc2e3b221b
1 | DBusMessageIter args; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | dbus_message_iter_init_append(dbmsg, &args); for (i = 0; i < 10; i++) { if (argv[argnum] != '\0') { printf ("%s\n", argv[argnum]); if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &argv[argnum])) { fprintf(stderr, "Out Of Memory!\n"); exit(1); } argnum++; } } |
缺點: 需要用到for loop去append自己想要傳送出去的資料。 不能用上面第一點的方式,直接全串再一起,寫一行即可。 而且如果需要append不同的type必須要去修改修正API中間的type值。
優點: 可以非常的彈性去增加N組不同的RULE或arg資料。
沒有留言:
張貼留言