我有一个 GUI,可以在其中显示ActiveState
几个 systemd 服务。
在 10Hz 时,我使用 sd-bus api 来查询每个服务,如下所示:
sd_bus* bus;
sd_bus_error err = SD_BUS_ERROR_NULL;
char* msg = 0;
sd_bus_default_system(&bus);
sd_bus_get_property_string(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1/unit/foo_2eservice",
"org.freedesktop.systemd1.Unit",
"ActiveState",
&err,
&msg);
我的问题是,当我运行这段代码时,/sbin/init
还是/lib/systemd/systemd-logind
消耗了大约 50% 的 CPU。分析代码显示sd_bus_get_property_string
. 我需要减少调用此函数的次数。
d-bus接口的自省很有意思:
busctl introspect \
org.freedesktop.systemd1 \
/org/freedesktop/systemd1/unit/foo_2eservice \
org.freedesktop.system1.Unit
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.Kill method si - -
.Ref method - - -
.Reload method s o -
.ReloadOrRestart method s o -
.ReloadOrTryRestart method s o -
.ResetFailed method - - -
.Restart method s o -
.SetProperties method ba(sv) - -
.Start method s o -
.Stop method s o -
.TryRestart method s o -
.Unref method - - -
.ActiveEnterTimestamp property t 0 emits-change
.ActiveEnterTimestampMonotonic property t 0 emits-change
.ActiveExitTimestamp property t 0 emits-change
.ActiveExitTimestampMonotonic property t 0 emits-change
.ActiveState property s "inactive" emits-change
...
这告诉我 ActiveState 属性发出了一个 change。
如何获取文件描述符,或点击事件循环以接收该更改?
D-Bus 规范建议 systemd 将在属性更改时发出信号org.freedesktop.DBus.Properties.PropertiesChanged
。我想我需要弄清楚如何订阅该信号。
我不允许添加评论,因此我扩展了@Stewart 的答案。要启用信号,必须订阅它们:
如果您想知道为什么
sd_bus_wait
永远不会回来,那么您会错过类似的东西答案是用来
sd_bus_match_signal(3)
设置事件过滤器。您可以通过执行以下操作之一来监听事件:
sd_bus_wait(3)
阻塞直到事件发生并sd_bus_process(3)
处理它们。sd-bus
到sd-event
循环sd_bus_attach_event(3)
(您可能还需要设置 sd-event 循环)。sd_bus_get_fd(3)
,sd_bus_get_events(3)
和sd_bus_get_timeout(3)
将 sd-bus 连接到您自己的事件循环。这是一个简短的 C 示例,说明如何执行此操作:
我已经注释掉了回调机制。
请注意,您会收到有关任何单位属性更改的消息。因此,如果您执行类似的操作
systemctl stop
,您可能会收到几条消息。