# 실시간 메일박스

### 개요

실시간 시스템에서 서로 다른 태스크 간의 데이터 교환은 매우 중요하다. Xenomai는 실시간 통신을 위한 여러 가지 메커니즘을 제공하며, 그 중 하나가 메일박스(mailbox)이다. 메일박스는 메시지 큐(queue)의 한 형태로, 송신자가 데이터를 전송하면 수신자가 이를 받아 처리할 수 있는 방식으로 동작한다.

### 메일박스의 기본 개념

메일박스는 실시간 통신을 위해 설계된 데이터 구조로, 메시지를 송수신하는 데 사용된다. 각 메일박스는 특정 크기의 버퍼를 가지며, 메시지를 저장하고 이를 대기 중인 수신자에게 전달한다.

#### 메일박스의 구성 요소

* **메시지 버퍼**: 송신된 메시지를 저장하는 버퍼.
* **송신 및 수신 태스크**: 데이터를 송신하는 태스크와 이를 수신하는 태스크가 있다.
* **동기화 메커니즘**: 송수신 간의 데이터 동기화를 위한 메커니즘.

### 메일박스 생성 및 초기화

먼저, 메일박스를 생성하고 초기화하는 함수들에 대해 알아본다.

```c
#include <rtdm/rtipc.h>
#include <native/mbox.h>
```

```c
int rt_mbx_create(RT_QUEUE *mbx, const char *name, size_t size);
```

`rt_mbx_create` 함수는 새로운 메일박스를 생성한다. 여기서 `mbx`는 메일박스를 참조하는 핸들, `name`은 메일박스의 이름, `size`는 메일박스의 크기를 나타낸다.

**예시**:

```c
RT_QUEUE mbx;
rt_mbx_create(&mbx, "Mailbox1", 256);
```

### 메일박스 삭제

메일박스를 더 이상 사용하지 않을 때, 이를 삭제해야 메모리 누수를 방지할 수 있다.

```c
int rt_mbx_delete(RT_QUEUE *mbx);
```

**예시**:

```c
rt_mbx_delete(&mbx);
```

### 데이터 송신

메일박스를 통해 데이터를 송신하는 함수는 다음과 같다.

```c
ssize_t rt_mbx_send(RT_QUEUE *mbx, const void *msg, size_t size);
```

`rt_mbx_send` 함수는 특정 메일박스에 데이터를 송신한다. `msg`는 송신할 데이터, `size`는 데이터의 크기이다.

**예시**:

```c
char message[] = "Hello, World!";
rt_mbx_send(&mbx, message, sizeof(message));
```

### 데이터 수신

메일박스로부터 데이터를 수신하는 함수들은 다음과 같다.

```c
ssize_t rt_mbx_receive(RT_QUEUE *mbx, void *msg, size_t size);
```

```c
ssize_t rt_mbx_receive_timed(RT_QUEUE *mbx, void *msg, size_t size, const RTIME *timeout);
```

`rt_mbx_receive` 함수는 메일박스로부터 데이터를 수신 대기하고, 데이터를 받으면 이를 `msg`에 저장한다. `rt_mbx_receive_timed` 함수는 타임아웃을 지정하여 수신 대기할 수 있다.

**예시**:

```c
char buffer[256];
rt_mbx_receive(&mbx, buffer, sizeof(buffer));

RTIME timeout = TM_INFINITE;  // 무한대기
rt_mbx_receive_timed(&mbx, buffer, sizeof(buffer), &timeout);
```

### 동기화 및 오류 처리

메일박스를 사용하면서 동기화와 오류 처리는 매우 중요한 요소이다. 송수신 태스크 간의 동기화 문제를 해결하고, 예상치 못한 상황에서의 오류 처리를 적절히 수행하여 시스템의 신뢰성을 높이는 것이 필요하다.

#### 동기화

실시간 시스템에서는 태스크들이 데이터 전송 시, 동기화 문제를 겪을 수 있다. 메일박스는 이 동기화를 지원하기 위해 다양한 동기화 메커니즘을 제공한다. 예를 들어, `rt_mbx_send` 함수는 메일박스가 가득 찬 경우, 데이터를 전송하려는 태스크를 블록(block) 상태로 만든다. 반대로 `rt_mbx_receive` 함수는 메일박스가 비어 있는 경우, 데이터를 기다리는 태스크를 블록 상태로 만든다. 이를 통해 송수신 태스크 간의 동기화가 보장된다.

#### 오류 처리

메일박스를 사용할 때 발생할 수 있는 주요 오류들은 다음과 같다.

* 메일박스 생성 실패: 메일박스 생성 시 사용 가능한 메모리가 부족한 경우 발생.
* 송신 실패: 메일박스가 가득 찬 경우 발생.
* 수신 실패: 메일박스가 비어 있는 경우 발생.
* 삭제 실패: 삭제하려는 메일박스가 유효하지 않은 경우 발생.

이와 같은 오류 상황을 체크하고, 적절한 예외 처리를 통해 시스템의 신뢰성을 확보해야 한다.

**예시**:

```c
if (rt_mbx_create(&mbx, "Mailbox1", 256) != 0) {
    // 오류 처리: 메일박스 생성 실패
}

if (rt_mbx_send(&mbx, message, sizeof(message)) < 0) {
    // 오류 처리: 데이터 송신 실패
}

if (rt_mbx_receive(&mbx, buffer, sizeof(buffer)) < 0) {
    // 오류 처리: 데이터 수신 실패
}

if (rt_mbx_delete(&mbx) != 0) {
    // 오류 처리: 메일박스 삭제 실패
}
```

### 샘플 코드

다음은 메일박스를 사용하여 데이터를 송수신하는 간단한 샘플 코드이다.

**송신 태스크**:

```c
void sender_func(void *arg) {
    RT_QUEUE *mbx = (RT_QUEUE *)arg;
    char message[] = "Hello, Xenomai!";
    
    while (1) {
        if (rt_mbx_send(mbx, message, sizeof(message)) < 0) {
            printf("Error sending message\n");
        }
        rt_task_sleep(1000000000);  // 1초 대기
    }
}
```

**수신 태스크**:

```c
void receiver_func(void *arg) {
    RT_QUEUE *mbx = (RT_QUEUE *)arg;
    char buffer[256];
   
    while (1) {
        if (rt_mbx_receive(mbx, buffer, sizeof(buffer)) < 0) {
            printf("Error receiving message\n");
        } else {
            printf("Received message: %s\n", buffer);
        }
        rt_task_sleep(500000000);  // 0.5초 대기
    }
}
```

**메인 함수**:

```c
int main() {
    RT_QUEUE mbx;
    RT_TASK sender, receiver;
   
    // 메일박스 생성
    if (rt_mbx_create(&mbx, "Mailbox1", 256) != 0) {
        printf("Failed to create mailbox\n");
        return -1;
    }
   
    // 태스크 생성
    rt_task_create(&sender, "Sender", 0, 50, 0);
    rt_task_create(&receiver, "Receiver", 0, 50, 0);
   
    // 태스크 시작
    rt_task_start(&sender, &sender_func, &mbx);
    rt_task_start(&receiver, &receiver_func, &mbx);
   
    // 메인 함수 대기
    pause();
   
    // 태스크 종료 및 메일박스 삭제
    rt_task_delete(&sender);
    rt_task_delete(&receiver);
    rt_mbx_delete(&mbx);
   
    return 0;
}
```

이 샘플 코드는 간단한 송수신 메커니즘을 구현하여, sender 태스크가 주기적으로 메시지를 메일박스로 송신하고, receiver 태스크가 이를 수신하여 출력하는 예제이다.

***

Xenomai의 메일박스는 실시간 시스템에서 데이터를 효율적으로 송수신할 수 있는 강력한 메커니즘을 제공한다. 이를 통해 실시간 통신이 요구되는 다양한 애플리케이션에서 안정적이고 동기화된 데이터 전송을 구현할 수 있다. 다양한 동기화 메커니즘과 함께 오류 처리 방안을 고려하여, 시스템의 신뢰성을 높이는 것이 중요하다.
