SD 버스 속성 보기

SD 버스 속성 보기

ActiveState여러 시스템 서비스를 표시하는 GUI가 있습니다 .

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-logindCPU의 약 50%를 소비한다는 것입니다. 코드를 분석해 보면 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 속성을 알려줍니다.문제 변경 사항.

파일 설명자를 어떻게 얻거나 해당 변경 사항을 수신하기 위해 이벤트 루프에 들어가나요?


이것D-버스 사양org.freedesktop.DBus.Properties.PropertiesChanged속성이 변경되면 systemd가 신호를 생성함을 나타냅니다 . 신호를 구독하는 방법을 알아내야 할 것 같아요.

답변1

댓글을 추가할 수 없으므로 @Stewart의 답변을 확장하고 있습니다. 신호를 활성화하려면 다음을 수행해야 합니다.신청그들에게:

Subscribe()는 대부분의 버스 신호를 보낼 수 있습니다. 신호에 관심이 있는 클라이언트는 이 메서드를 호출해야 합니다. 신호는 하나 이상의 클라이언트가 이 메서드를 호출할 때만 방출됩니다.

sd_bus_wait왜 다시 돌아오지 않았는지 궁금하다면 다음과 같은 내용을 놓치고 있는 것입니다.

sd_bus_call_method(bus,
                   "org.freedesktop.systemd1",
                   "/org/freedesktop/systemd1",
                   "org.freedesktop.systemd1.Manager",
                   "Subscribe",
                   &error,
                   NULL,
                   NULL);

답변2

대답은 사용하는 것입니다sd_bus_match_signal(3)이벤트 필터를 설정합니다.

다음 중 하나를 수행하여 이벤트를 수신할 수 있습니다.

  1. sd_bus_wait(3)이벤트가 발생할 때까지 차단하고sd_bus_process(3)그들을 처리하기 위해.
  2. 루프 sd-bus에 연결sd-eventsd_bus_attach_event(3)(sd-event 루프를 설정해야 할 수도 있습니다).
  3. 사용sd_bus_get_fd(3),sd_bus_get_events(3)그리고sd_bus_get_timeout(3)sd-bus를 자신의 이벤트 루프에 연결하십시오.

다음은 이를 수행하는 방법을 보여주는 짧은 C 예입니다.

/* gcc main.c -lsystemd */

#include <systemd/sd-bus.h>
#include <stdio.h>
#include <stdlib.h>

static inline const char *strna(const char *s) {
        return s ?: "n/a";
}

int message_callback(sd_bus_message* m, void* userdata, sd_bus_error* ret_error) {
        printf("callback: path=%s interface=%s member=%s\n", 
                strna(sd_bus_message_get_path(m)), 
                strna(sd_bus_message_get_interface(m)), 
                strna(sd_bus_message_get_member(m))
        );
        return 0;
}

int main() {
        sd_bus* bus = NULL;
        sd_bus_error err = SD_BUS_ERROR_NULL;
        char* msg = NULL;
        void* userdata = NULL;

        sd_bus_default_system(&bus);

        sd_bus_match_signal(
                bus,                                             /* bus */
                NULL,                                            /* slot */
                NULL,                                            /* sender */
                "/org/freedesktop/systemd1/unit/foo_2eservice",  /* path */
                "org.freedesktop.DBus.Properties",               /* interface */
                "PropertiesChanged",                             /* member */
                NULL /*message_callback*/ ,                      /* callback */
                userdata
        );

        while( 1 ) { 
                sd_bus_wait(bus, UINT64_MAX);
                while ( sd_bus_process(bus, NULL) ) {  }

                sd_bus_get_property_string(
                        bus,                                             /* bus */
                        "org.freedesktop.systemd1",                      /* destination */
                        "/org/freedesktop/systemd1/unit/foo_2eservice", /* path */
                        "org.freedesktop.systemd1.Unit",                 /* interface */
                        "ActiveState",                                   /* member */
                        &err, 
                        &msg);

                printf("New state: %s\n", msg);
                free(msg);

        }

        sd_bus_error_free(&err);
        sd_bus_message_unref(ret);
        sd_bus_unref(bus);
        return 0;
}

콜백 메커니즘을 주석 처리했습니다.

변경사항에 대한 메시지를 받게 됩니다.어느장치의 속성입니다. 따라서 이와 같은 작업을 수행하면 systemctl stop몇 가지 메시지를 받을 수 있습니다.

관련 정보