개요

Xenomai에서 실시간 메시지 큐(message queue)는 하나의 태스크(task)가 다른 태스크에 데이터를 보내거나 받을 수 있도록 하는 실시간 IPC(inter-process communication)의 중요한 방법 중 하나이다. 메시지 큐는 여러 태스크가 서로 통신하고 데이터를 안전하게 주고받을 수 있는 방법을 제공하여 실시간 시스템에서 매우 중요하다.

특징

실시간 메시지 큐는 여러 가지 중요한 특성을 가지고 있다:

  1. FIFO 순서: 메시지를 전송한 순서대로 도착한다.
  2. 블로킹 및 논블로킹 모드: 송신 및 수신할 때 블로킹 혹은 논블로킹 모드로 사용할 수 있다.
  3. 우선순위 기반: 메시지가 큐에 도착하는 순서를 송신자의 우선순위를 기준으로 설정할 수 있다.

메시지 큐 생성

메시지 큐를 생성하기 위해 rt_queue_create 함수를 사용한다. 이 함수는 큐 객체와 큐의 속성을 초기화 한다.

#include <native/queue.h>

RT_QUEUE queue;
int err;

err = rt_queue_create(&queue, "MyQueue", Q_SIZE, Q_LIMIT, Q_FIFO);

if (err) {
    // 에러 처리
}

여기서 중요한 매개변수는 다음과 같다:

메시지 보내기

메시지 큐에 메시지를 보내기 위해 rt_queue_send 함수를 사용한다.

int err;

err = rt_queue_send(&queue, message, message_size, Q_TIMEOUT);

if (err) {
    // 에러 처리
}

여기서 중요한 매개변수는 다음과 같다:

메시지 받기

메시지 큐에서 메시지를 받기 위해 rt_queue_receive 함수를 사용한다.

void *received_msg;
int err;

err = rt_queue_receive(&queue, &received_msg, TM_INFINITE);

if (err) {
    // 에러 처리
} else {
    // 메시지 처리
}

여기서 중요한 매개변수는 다음과 같다:

메시지 큐 삭제

메시지 큐를 사용한 후에는 이를 삭제하여 자원을 해제해 주어야 한다. 이를 위해 rt_queue_delete 함수를 사용한다.

int err;

err = rt_queue_delete(&queue);

if (err) {
    // 에러 처리
}

여기서 중요한 매개변수는 다음과 같다:

실용 예제

다음은 메시지 큐를 활용한 간단한 예제이다. 이 예제는 하나의 태스크가 메시지 큐에 메시지를 보내고, 다른 태스크가 해당 메시지를 받는 방식으로 작동한다.

송신 태스크

void sender_task(void *arg) {
    char message[] = "Hello, Receiver";
    int err;

    while (1) {
        err = rt_queue_send(&queue, message, sizeof(message), TM_INFINITE);
        if (err) {
            // 에러 처리
        }
        rt_task_sleep(1000000000);  // 1초 대기
    }
}

수신 태스크

void receiver_task(void *arg) {
    void *received_msg;
    int err;

    while (1) {
        err = rt_queue_receive(&queue, &received_msg, TM_INFINITE);
        if (err) {
            // 에러 처리
        } else {
            printf("Received message: %s\n", (char *)received_msg);
            // 여기서 message를 사용 후 메모리 해제 필요
            rt_queue_free(&queue, received_msg);
        }
    }
}

메인 함수

int main(void) {
    int err;

    // 큐 생성
    err = rt_queue_create(&queue, "MessageQueue", 1024, 10, Q_FIFO);
    if (err) {
        // 에러 처리
        return err;
    }

    // 송신 태스크 생성
    RT_TASK sender;
    err = rt_task_create(&sender, "Sender", 0, 50, 0);
    if (err) {
        // 에러 처리
        return err;
    }
    rt_task_start(&sender, sender_task, NULL);

    // 수신 태스크 생성
    RT_TASK receiver;
    err = rt_task_create(&receiver, "Receiver", 0, 50, 0);
    if (err) {
        // 에러 처리
        return err;
    }
    rt_task_start(&receiver, receiver_task, NULL);

    // 메인 스레드 대기
    pause();

    // 큐 삭제
    rt_queue_delete(&queue);
    return 0;
}

이 예제에서는 송신 태스크와 수신 태스크가 서로 다른 스레드에서 작동하며, 메시지 큐를 통해 통신하게 된다. sender_task는 1초마다 메시지를 보내고, receiver_task는 메시지를 수신하여 출력한다.

이러한 방식으로 실시간 메시지 큐를 활용하여 다양한 실시간 애플리케이션을 구현할 수 있다.