반응형

 

소스코드

파일 이름: dbus_signal_receiver.c

#include <gio/gio.h>
#include <stdio.h>
#include <stdlib.h>

// signal 핸들러 콜백 함수
static void onAlarmRinging(GDBusConnection *connection,
                     const gchar *sender_name,
                     const gchar *object_path,
                     const gchar *interface_name,
                     const gchar *signal_name,
                     GVariant *parameters,
                     gpointer user_data)
{
    gchar *parameters_str = g_variant_print(parameters, TRUE);
    printf("Received signal: %s\n", signal_name);
    printf("Sender: %s\n", sender_name);
    printf("Object Path: %s\n", object_path);
    printf("Interface: %s\n", interface_name);
    printf("Parameters: %s\n", parameters_str);
    
    /* 받은 paramter들을 여기서 처리 */
    
    g_free(parameters_str);
}

int main(int argc, char *argv[])
{
    GMainLoop *loop;
    GDBusConnection *connection;
    GError *error = NULL;
    guint subscription_id;

    // GMainLoop 초기화
    loop = g_main_loop_new(NULL, FALSE);

    // 시스템 D-Bus 연결
    connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
    if (error != NULL) {
        g_printerr("Error connecting to D-Bus: %s\n", error->message);
        g_error_free(error);
        return EXIT_FAILURE;
    }

    // signal 구독
    subscription_id = g_dbus_connection_signal_subscribe(
        connection,
        NULL, // 발신자(sender) 지정 안 함 (모든 발신자 허용)
        "org.sound", // 인터페이스
        "AlarmRinging", // 신호 이름
        "/watch", // 객체 경로
        NULL, // arguments 필터링 안 함
        G_DBUS_SIGNAL_FLAGS_NONE,
        onAlarmRinging, // 콜백 함수
        NULL, // 사용자 데이터
        NULL  // 사용자 데이터 해제 함수
    );

    printf("Listening for AlarmRinging signals...\n");

    // 메인 루프 실행
    g_main_loop_run(loop);

    // 정리
    g_dbus_connection_signal_unsubscribe(connection, subscription_id);
    g_object_unref(connection);
    g_main_loop_unref(loop);

    return EXIT_SUCCESS;
}

 

 

코드 설명

  1. GDBus 연결: g_bus_get_sync를 사용하여 시스템 D-Bus에 연결합니다. 이 때, 타입은 SYSTEM 타입이고, 연결 정보가 담긴 connection을 동기식으로 가져옵니다.
  2. 신호 구독: g_dbus_connection_signal_subscribeorg.freedesktop.DBus.Properties 인터페이스의 PropertiesChanged 신호를 구독합니다. 이 신호는 시스템 서비스(예: NetworkManager, BlueZ 등)에서 속성이 변경될 때 발생합니다.
  3. 콜백 함수: on_properties_changed는 신호가 발생할 때 호출되며, 신호의 세부 정보를 출력합니다.
  4. 메인 루프: GMainLoop를 사용하여 프로그램이 신호를 대기하도록 합니다.

 

컴파일 방법

위 코드를 컴파일하려면 gio-2.0 라이브러리가 필요합니다. 아래 명령어로 컴파일하세요:

gcc -o dbus_signal_receiver dbus_signal_receiver.c `pkg-config --cflags --libs gio-2.0`

 

 

dbus-send 명령어

dbus-send --system --type=signal \
    /watch \
    org.sound.AlarmRinging \
    string:"Wakeup"

 

dbus-send 명령어 설명

  • --system: 시스템 D-Bus로 전송.
  • --type=signal: 신호 타입 지정.
  • /org/freedesktop/DBus: 신호를 보낼 객체 경로.
  • org.freedesktop.DBus.Properties.PropertiesChanged: 신호의 인터페이스와 이름.
  • string:"org.example.Test": 변경된 인터페이스 이름.
  • dict:string:string:"TestProperty","NewValue": 변경된 속성(키-값 쌍).
  • array:string:: 무효화된 속성 배열(여기선 빈 배열).

 

 

  • 특정 서비스의 신호를 테스트하려면, d-feetbusctl 같은 도구로 D-Bus 인터페이스와 객체 경로를 확인하세요. (혹은 dbus-monitor)
  • 예제는 시스템 D-Bus를 사용하지만, 세션 D-Bus를 사용하려면 G_BUS_TYPE_SYSTEMG_BUS_TYPE_SESSION으로 변경하세요.

 

실행결과

Received signal: AlarmRinging
Sender: :1.192
Object Path: /watch
Interface: org.sound
Parameters: ('Wakeup',)

 

[번외] Signal Sender 코드

dbus-send 명령어 대신 아래의 코드로도 signal을 보낼 수 있다.

- 파일 이름: dbus_signal_sender.c

#include <gio/gio.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    GDBusConnection *connection;
    GError *error = NULL;

    // 시스템 D-Bus 연결
    connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
    if (error != NULL) {
        g_printerr("Error connecting to D-Bus: %s\n", error->message);
        g_error_free(error);
        return EXIT_FAILURE;
    }

    // 신호 전송
    g_dbus_connection_emit_signal(
        connection,
        NULL, // destination (NULL은 모든 클라이언트로 브로드캐스트)
        "/watch", // 객체 경로
        "org.sound.AlarmRinging", // 인터페이스 이름
        "AlarmRinging", // 신호 이름
        g_variant_new("(s)", "Wakeup"), // 매개변수: string "Wakeup"
        &error
    );

    if (error != NULL) {
        g_printerr("Error sending signal: %s\n", error->message);
        g_error_free(error);
        g_object_unref(connection);
        return EXIT_FAILURE;
    }

    printf("Signal sent: org.sound.AlarmRinging with parameter 'Wakeup'\n");

    // 연결 종료
    g_object_unref(connection);

    return EXIT_SUCCESS;
}

 

컴파일

gcc -o dbus_signal_receiver dbus_signal_receiver.c `pkg-config --cflags --libs gio-2.0`
반응형