2016年2月1日 星期一

Dbus Introduction & implement

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

大家可以參考看看,如果有問題可以提出來,畢竟我也不是很懂~~
只要透過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資料。








沒有留言:

張貼留言