【问题标题】:Low Level DBus C API main loop低级 DBus C API 主循环
【发布时间】:2018-02-03 17:06:27
【问题描述】:

当尝试对 DBus 回复使用回调函数时,我无法创建一个良好/运行良好的主循环。

我想做的很简单,做一个 DBus 调用并指定一个函数,当回复到来时应该调用它。这是因为我不想一直阻塞我的线程,直到计算出回复并到达。

我首先使用 dbus_connection_send_with_reply(..) 获取 DBusPendingCall,然后使用 dbus_pending_call_set_notify(..) 指定回调函数。在此之前,当连接到总线时,我已经启动了另一个线程,它应该等待响应并调用回调函数。我根本没有找到任何例子,也没有很好的文档来说明我应该如何设计这样的 dbus 主循环。我试过了:

// Main dbus loop handling data transfer and callbacks..
void *dbus_main(void *args)
{
    my_dbus dbus = (my_dbus)args;

    while (MY_DBUS_STATUS_STOPPING != dbus->status
            && dbus_connection_read_write_dispatch(dbus->conn, -1))
        ;

    return 0;
}

// Start the dbus main loop in a new thread
void dbus_main_start(my_dbus dbus) {
    if (!pthread_create(&dbus->th, NULL, dbus_main, dbus)) {
        // PRINT ERROR
    }
}

我的问题有两个:

  • 我尝试通过将 dbus->status 标志设置为 MY_DBUS_STATUS_STOPPING 并等待线程加入来停止应用程序。如果线程在 dbus_connection_read_write_dispatch(..) 函数中被阻塞,这将不起作用。如果我希望应用程序快速停止,那么我需要指定一个非常短的超时时间。我不能用其他方式唤醒被阻塞的线程吗?

  • 更严重的是,使用此代码,我不会从我调用的方法中获得任何回调。如果我添加一些 fprintf(..) 来写入标准输出,我可能会突然收到我的回调。这似乎很随机,所以也许是某种僵局?我尝试在发送消息和使用 _set_notify(..) 函数添加回调之间使用 dbus_connection_flush(..) 。没有任何区别......但是在同一个地方打印一些字母到标准输出可以解决问题。在 dbus-main-loop 中打印到标准输出,插入一个空的“;”有时似乎可以解决问题...

那么任何人都有使用低级dbus api和异步方法的例子,即不使用_block(..)??

【问题讨论】:

    标签: c linux dbus low-level-io freedesktop.org


    【解决方案1】:

    您可以如下创建一个简单的 DBus 应用程序...

    要设置服务器来处理传入消息,请调用dbus_connection_register_object_path 传递一个包含函数指针的 VTable 来处理消息。如:

    { .unregister_function = UnregisteredMessage, .message_function = ServiceMessage }

    要发送新消息,请调用dbus_connection_send_with_reply,然后调用dbus_pending_call_set_notify 以关联回调函数来处理回复。

    接下来您需要为 DBus 提供服务。这可以在单独的线程中完成,也可以通过在同一线程中使用非阻塞调用定期调用来完成,如下所示:

    /* Non-blocking read of the next available message */
    dbus_connection_read_write ( MyDBusConnection, 0 ) ;
    
    while ( dbus_connection_get_dispatch_status ( MyDBusConnection ) == DBUS_DISPATCH_DATA_REMAINS )
    {
       dbus_connection_dispatch ( MyDBusConnection ) ;
    }
    

    这里有一些使用 DBUS C API 的好例子:http://www.matthew.ath.cx/misc/dbus

    【讨论】:

      【解决方案2】:

      强烈建议您使用除 libdbus 之外的 D-Bus 库其他,因为正如您所发现的那样,libdbus 的正确使用非常繁琐。如果可能,请改用GDBusQtDBus,因为它们是更高级的绑定,更易于使用。如果您需要较低级别的绑定,sd-bus 比 libdbus 更现代。

      如果你使用 GDBus,你可以使用GMainLoop 来实现一个主循环。如果你使用sd-bus,你可以使用sd-event

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-06
        • 1970-01-01
        • 2023-03-05
        • 1970-01-01
        • 2019-09-08
        • 2016-04-23
        • 1970-01-01
        • 2020-07-03
        相关资源
        最近更新 更多