使用gdbus-codegen生成的管理器代理时,我无法接收系统的DBus信号。但是我能够通过DBus成功调用systemd提供的方法。
我在网上搜索并查看了这些链接,但收效甚微。当gdbus-codegen用于系统化API时,如何执行此操作的示例并不多。
这是我与代码段一起做的。
1)我生成了systemd内省,并使用该XML作为gdbus-codegen的输入。
...剪
<interface name="org.freedesktop.systemd1.Manager">
<signal name="JobRemoved">
<arg type="u"/> <arg type="o"/> <arg type="s"/> <arg type="s"/>
</signal>
...剪
2)编写我的客户端代码,以使用gdbus-codegen生成的C API并创建一个管理器代理。(一切都在系统总线上)。
SystemdManager *systemdProxy = systemd_manager_proxy_new_for_bus_sync(
G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
"org.freedesktop.systemd1", "/org/freedesktop/systemd1",
NULL, error);
3)定义一个信号处理程序
static void on_done(GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
LOG_ERROR("on_done");
}
4)将信号处理程序连接到JobRemoved信号的代理。
if (g_signal_connect(systemdProxy, "job-removed",
G_CALLBACK(on_done), NULL) <= 0 )
{
LOG_ERROR("Failed to connect to signal job-removed");
}
5)使用代理启动systemd服务。这将返回成功,并且我可以看到单元启动并运行一两秒钟并终止。
ret = systemd_manager_call_start_unit_sync(
systemdProxy, unit_name, unit_mode, &job_obj,
NULL, &error);
6)systemd生成JobRemoved信号。dbus-monitor显示它。
signal sender=:1.0 -> dest=(null destination) serial=11931
path=/org/freedesktop/systemd1;
interface=org.freedesktop.systemd1.Manager;
member=JobRemoved
uint32 7009
object path "/org/freedesktop/systemd1/job/7009"
string "mysample.service"
string "done"
7)我的信号处理程序永远不会被调用。(一切都使用系统总线,没有其他总线)。我曾尝试各种串detailed_signal
的第二个参数g_signal_connect
(如:JobRemoved
,job_removed
,::job-removed
,一些不被接受g_signal_connect
)。
任何帮助是极大的赞赏!
解决的办法是glib event loop
在我的程序中使用。我的程序没有运行GMainLoop
,因此无法从中获取任何回调glib
。这不是一种优雅的方法,但是由于种种原因,我决定生成一个新线程,然后将其阻塞在g_main_loop_run上。这是它的样子。
void *event_loop_thread(void *unused) {
GMainLoop *loop = g_main_loop_new(NULL, 0);
g_main_loop_run(loop);
}
int main() {
// snip
pthread_create(&thread_id, NULL, event_loop_thread, NULL);
// do steps 2 to 6, and at step 7 signal handler is called
}
另外,我还必须修复信号处理程序签名以使其与信号兼容,以接收有意义的参数。
static void on_done(SystemdManager *manager,
guint32 job_id,
gchar *job_obj,
gchar *unit_name,
gchar *status)
{
LOG_ERROR("on_done");
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句