c++ d-bus通信 c++ linux如何使用d-bus进行进程间通信

阿宇酱_2721

阿宇酱_2721

2026-03-22

608人浏览

原创

dbus-c++因维护停滞、abi兼容性差、无超时控制且高并发性能低,生产环境应优先选用稳定、功能完备的原生libdbus。

c++ d-bus通信 c++ linux如何使用d-bus进行进程间通信

怎么用 dbus-c++ 发送一个简单方法调用

直接用 dbus-c++(即 libdbus-c++)发请求,核心是拿到远程对象的代理(proxy),再调用其方法。它底层封装了原始 libdbus 的繁琐流程,但前提是 D-Bus 服务已启动且接口定义正确。

常见错误现象:DBus::FatalException 抛出、org.freedesktop.DBus.Error.ServiceUnknown、或调用后无响应——基本都是 bus 连接没通、服务名没注册、或路径/接口名写错。

  • 确保服务端已运行,并在系统总线(system)或会话总线(session)上正确注册:用 busctl --system list-names | grep your.service.name 或 dbus-send --session --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames 验证
  • 客户端连接必须匹配服务端使用的 bus 类型:DBus::Connection conn = DBus::Connection::SessionBus() 或 ::SystemBus()
  • 代理构造时三个参数缺一不可:conn.request_name("your.service.name") 不是必须的(客户端不用占名),但 conn.create_interface("your.service.name", "/object/path", "interface.name") 中的服务名、路径、接口名必须和 Introspect 输出完全一致(大小写敏感,含点号)
  • 方法调用前建议先检查接口是否可用:if (iface->is_valid()) { ... },否则直接调用会 crash

dbus-c++ 和原生 libdbus 哪个更稳

dbus-c++ 封装层薄、API 简洁,但长期维护停滞(最后更新在 2014 年左右),在较新 glibc 或 systemd 版本下容易因 ABI 变更或线程模型不兼容而 segfault;而原生 libdbus 虽然写法啰嗦,但稳定、文档全、发行版默认带,且支持异步模式和完整错误码映射。

使用场景:小工具、原型验证可用 dbus-c++;生产环境、需处理超时/重连/权限失败等边界情况,务必切回 libdbus。

  • dbus-c++ 不支持 DBUS_TIMEOUT_USE_DEFAULT 以外的超时控制,调用卡住只能 kill 进程
  • 它的信号监听依赖轮询(conn.dispatch()),没做 epoll/kqueue 适配,在高并发 IPC 场景下 CPU 占用明显偏高
  • 某些发行版(如 Ubuntu 22.04+)已移除 libdbus-c++ 包,需手动编译,且与 dbus-1.14+ 链接时可能报 undefined reference to dbus_connection_set_watch_functions

如何用 libdbus 同步调用一个方法并读返回值

同步调用本质是发消息 + 阻塞等回复。关键不是“怎么发”,而是“怎么安全收”:必须检查消息类型、序列号、错误字段,不能假设 reply 一定成功。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

示例中省略了内存释放和错误跳转,但实际代码里每一步 dbus_pending_call_block() 或 dbus_message_iter_get_arg_type() 后都应判断返回值。

DBusMessage *msg = dbus_message_new_method_call(
    "org.example.MyService",      // service name
    "/org/example/MyObject",      // object path
    "org.example.MyInterface",    // interface
    "GetValue"                    // method name
);
DBusMessageIter iter;
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &input_val);

DBusMessage *reply = dbus_connection_send_with_reply_and_block(
    conn, msg, DBUS_TIMEOUT_USE_DEFAULT, &err
);
if (dbus_set_error_from_message(&err, reply)) {
    fprintf(stderr, "D-Bus error: %s\n", err.message);
    dbus_error_free(&err);
} else if (reply) {
    dbus_message_iter_init(reply, &iter);
    int result;
    if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_INT32) {
        dbus_message_iter_get_basic(&iter, &result);
    }
}
dbus_message_unref(msg);
if (reply) dbus_message_unref(reply);
  • 别漏掉 dbus_error_init(&err),否则未初始化的 err 可能导致段错误
  • dbus_connection_send_with_reply_and_block() 在 dbus 1.12+ 默认启用 DBUS_TIMEOUT_USE_DEFAULT(约 25s),但若服务端 hang 住,整个线程就卡死——生产中必须设明确 timeout(毫秒)
  • 返回值类型必须严格匹配接口定义,dbus_message_iter_get_arg_type() 返回 DBUS_TYPE_INVALID 很可能是服务端没填 reply 或类型写错

为什么 dbus-send 能通,C++ 程序却连不上

最常被忽略的是 bus 类型和地址不一致。dbus-send 默认走会话总线,但 C++ 代码如果硬编码了 dbus_bus_get(DBUS_BUS_SYSTEM, &err),而服务只在 session 注册,自然连不上;反之亦然。

另一个高频坑是 SELinux 或 systemd user session 权限限制:普通用户进程无法访问 session bus 的某些服务,除非服务配置了 AllowSendMessages 规则。

  • 查当前程序看到的 bus 地址:echo $DBUS_SESSION_BUS_ADDRESS,然后在 C++ 里用 dbus_connection_open() 显式连接该地址,而非依赖 dbus_bus_get()
  • 用 dbus-monitor --session "type='method_call',interface='org.example.MyInterface'" 抓包,确认你的程序是否真的发出了消息(有时 connect 成功但 send 失败静默丢弃)
  • 服务端若用 gdbus 或 sd-bus 实现,注意它们默认不兼容老式 libdbus 的线程模型——需在服务端显式调用 dbus_connection_set_exit_on_disconnect(conn, FALSE)

真正麻烦的从来不是“怎么调通一次”,而是“怎么让调用在服务重启、总线重载、权限变更后依然可靠”。这些细节不写进日志、不加断言、不跑压测,上线后第一周就出问题。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

2023.10.17

580

4

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

2023.10.18

876

5

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

2025.08.19

1906

14

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.18

989

5

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.25

2960

5

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3148

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

4909

12

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2025.12.29

3789

9

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2026.01.19

446

15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习