DBUS的理解

dbus是一个轻量级的IPC,用于进程间通信或进程与内核间的通信,dbus通信结构下图:

Bus daemon:总线守护进程,dbus是点对点进行通信的,所以基本上dbus进程连接的都是bus daemon,bus daemon负责将收到的dbus消息进行路由、转发。dbus进程将消息发送给bus daemon,bus daemon会结合消息的目标地址、对象路径、消息的类型、以及dbus进程希望收到的消息进行综合,然后转发。

下面是一个dbus进程连接的结构:

System bus:一个持久的系统总线,在引导时就会启动。由操作系统和后台使用,安全性好。普通进程也可以连接到这个总线上接收消息,但是发送消息却是受限的。

Session bus:用户登录后启动,属于那个用户的私有总线。是用户的应用程序间用来通信的一个总线。

Dbus 的连接:一个dbus进程向后台dbus进行连接,会得要一个连接名(bus name),bus name有两种情况:公共名、唯一名。每个dbus连接一定会有一个唯一名,且唯一名在整个后台dbus的生命周期内唯一。如下图,“:1.0”是唯一名,“org.xfce.xfdesktop”是公共名,如下图:

 

Object path:dbus连接下面可以有多个object path,如bluez连接下面有bluez、bluez/hciconfig等,个人认为之所以有object path,是为了区分不同的服务,如bluez可以理解为蓝牙的协议层,而hciconfig是控制层;

Interface:object path 下面也有很多接口,以bluez为例,下面存在Adapter1、AgentManager1等;

Method:每个interface下也有很多接口,以Adapter1为例,下面有startDiscovery、stopDiscovery等方法;而Method又分为四类:

(1). Method call消息:进程发送消息(目标连接名、对象路径、接口、方法、方法参数)到bus daemon上,bus daemon收到消息后,根据消息的目标名、对象路径,发送到目标进程上,目标进程收到后,使用发送过来的参数,执行这个方法;

(2). Method return 消息:在上述结果执行完成后,一些需要返回结果的接口,会通过这个接口将结果返回回去。

(3). signal消息:希望收到此信号的dbus进程需要在后台dbus上注册,表示自己希望收到这个信号消息,当bus daemon收到此消息时,会将消息转发给注册此信号的进程。

(4). Error消息:

通信示意图

 

下面代码是一个Method call消息的内容:

int a = 2, b = 3;
msg = dbus_message_new_method_call("test.wei.dest", "/test/method/Object", "test.method.type", "Method");
DBusMessageIter iter;
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &a);     
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &b);

上面代码中消息的内容包括了目标连接、对象路径、接口、方法、参数。这样bus daemon就可以根据消息的内容,进行转发到test.wei.dest的连接上,并在目标连接的进程内使用参数a、b执行Method这个方法。相当于是test.wei.dest对外提供了一个Method的方法,供外部使用。

下面是一个自发自收的demo:

#include<stdio.h> 
#include<stdlib.h> 
#include<dbus/dbus.h> 


//消息循环处理,对外提供了两个方法,Add、Quit;
DBusHandlerResult dbus_message_handler(DBusConnection* conn, DBusMessage* msg, void* user_data) 
{ 
	if (dbus_message_is_method_call(msg, "com.example.Calculator", "Add")) 
	{
		// 处理 Add 方法
		DBusMessageIter iter; 
		int a, b, sum;
		dbus_message_iter_init(msg, &iter); 
		dbus_message_iter_get_basic(&iter, &a); 
		dbus_message_iter_next(&iter);
		dbus_message_iter_get_basic(&iter, &b); 
		sum = a + b; 
		DBusMessage* reply = dbus_message_new_method_return(msg); 
		DBusMessageIter reply_iter; 
		dbus_message_iter_init_append(reply, &reply_iter); 
		dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &sum);
		dbus_connection_send(conn, reply,NULL); 
		dbus_message_unref(reply); 
		return DBUS_HANDLER_RESULT_HANDLED; 
	}
	else if (dbus_message_is_method_call(msg, "com.example.Calculator", "Quit"))
	{ 
		// 处理 Quit 方法 
		dbus_connection_close(conn); 
		return DBUS_HANDLER_RESULT_HANDLED;
	} 
	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 
} 

//收到的应答消息处理
void dbus_reply_handler(DBusPendingCall* pending, void* user_data) 
{
	int* sum = (int*)user_data;
	DBusMessage* reply =dbus_pending_call_steal_reply(pending);
	DBusMessageIter iter;
	if (reply)
	{
		if (dbus_message_iter_init(reply, &iter))
		{ 
			dbus_message_iter_get_basic(&iter, sum); 
			printf("The sum is: %d\n", *sum);
		} 
		dbus_message_unref(reply);
	} 
	dbus_pending_call_unref(pending);
}

int main() 
{ 
    DBusError error; 
    DBusConnection* conn; 
    DBusMessage* msg; 
    DBusPendingCall* pending;
    int sum = 0;
    DBusObjectPathVTable dbus_interface = { .message_function = &dbus_message_handler }; 
    dbus_error_init(&error);

    // 建立到会话总线的连接
    conn = dbus_bus_get(DBUS_BUS_SESSION, &error);
    if (dbus_error_is_set(&error)) 
    {
      fprintf(stderr, "Error connecting to system bus: %s\n", error.message);
      dbus_error_free(&error);
      return EXIT_FAILURE;
    }

    // 注册对象路径和消息处理函数
    dbus_bus_request_name(conn, "com.example.Calculator", 0, &error);       //向dbus申请公共名
    if (dbus_error_is_set(&error))
    {
      fprintf(stderr, "Error requesting name: %s\n", error.message);
      dbus_error_free(&error);
      return EXIT_FAILURE;
    }
	dbus_connection_register_object(conn, "/com/example/Calculator", &dbus_interface, NULL); 

    // 创建DBus消息,并将参数添加到消息中
	int a = 2, b = 3;
    msg = dbus_message_new_method_call("com.example.Calculator", "/com/example/Calculator", "com.example.Calculator", "Add");
    DBusMessageIter iter;
    dbus_message_iter_init_append(msg, &iter);
    dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &a);     
    dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &b);

    // 发送DBus消息并等待应答
    dbus_connection_send_with_reply(conn, msg, &pending, -1);
    dbus_message_unref(msg);
    dbus_pending_call_set_notify(pending, dbus_reply_handler, &sum, NULL);     //将应答消息放到dbus_reply_handler去处理

    while (dbus_connection_read_write_dispatch(conn, -1)) {

    }
	while(1);
    dbus_connection_unref(conn);    //销毁连接

    return EXIT_SUCCESS;
}

参考:https://blog.csdn.net/yishuige/article/details/52852531

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值