# RTDM API와의 인터페이스

Xenomai의 RTDM(Real-Time Device Model)은 실시간 정밀도를 요구하는 응용 프로그램과 디바이스 드라이버 간의 인터페이스를 정의한 것이다. RTDM은 POSIX와의 호환성을 높이기 위해 설계되어, 실시간과 비실시간 코드 간의 심리스한 통합을 도와준다.

#### RTDM 개요

RTDM은 디바이스 드라이버들이 실시간 특성을 유지하면서 모듈형으로 설계될 수 있도록 지원한다. 다음과 같은 주요 특징을 가지고 있다:

* **실시간 성능**: 예상 가능한 응답 시간.
* **POSIX 호환성**: 표준 인터페이스를 통해 일반적인 POSIX 호환 코드와 호환 가능.
* **모듈화**: 드라이버와 애플리케이션을 체계적으로 분리하여 관리.

#### RTDM 드라이버 구조

RTDM 드라이버는 여러 구성 요소로 이루어져 있으며, 주요 구성 요소는 다음과 같다:

* **rtdm\_device 구조체**: 이 구조체는 디바이스의 주요 특성 및 동작을 정의한다.
* **sysfs 엔트리**: 사용자 공간에서 디바이스 드라이버를 접근하기 위한 파일 시스템 인터페이스.

#### rtdm\_device 구조체

`rtdm_device` 구조체는 드라이버가 제공하는 서비스에 대한 정보를 담고 있다. 주요 필드는 다음과 같다:

```c
struct rtdm_device {
    struct list_head    device_list;    // 드라이버 리스트
    const char          *device_name;   // 디바이스 이름
    int                 device_id;      // 디바이스 ID
    int                 device_flags;   // 디바이스 플래그
    struct module       *owner;         // 모듈 소유자
    struct rtdm_driver  *driver;        // 드라이버 메타 데이터
    struct rtdm_operations ops;         // 디바이스 연산
};
```

#### rtdm\_operations 구조체

`rtdm_operations` 구조체는 디바이스 드라이버의 주요 연산을 정의하는 함수 포인터들을 포함하고 있다. 주요 필드는 다음과 같다:

```c
struct rtdm_operations {
    int (*open_nrt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, int oflag);
    int (*open) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, int oflag);

    int (*close) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info);

    ssize_t (*read_nrt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, void *buf, size_t nbyte);
    ssize_t (*read_rt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, void *buf, size_t nbyte);

    ssize_t (*write_nrt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, const void *buf, size_t nbyte);
    ssize_t (*write_rt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, const void *buf, size_t nbyte);

    int (*ioctl_nrt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg);
    int (*ioctl_rt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg);
    
    int (*select_nrt) (struct rtdm_dev_context *context, rtdm_user_info_t *user_info, struct rtdm_fdset *fs);
};
```

#### 디바이스 등록

디바이스 드라이버를 등록하고 사용할 수 있도록 하기 위해서는 구조체를 초기화하고 `rtdm_dev_register` 함수를 호출해야 한다.

```c
struct rtdm_device my_device = {
    .device_name = "my_device",
    .device_id = 123,
    .device_flags = RTDM_NAMED_DEVICE,
    .ops = {
        .open_nrt = my_open_function,
        .close = my_close_function,
        .read_nrt = my_read_function,
        .write_nrt = my_write_function,
        .ioctl_nrt = my_ioctl_function,
    }
};

int ret = rtdm_dev_register(&my_device);
if (ret != 0) {
    // 오류 처리
}
```

### RTDM 디바이스 제거

디바이스 드라이버를 제거하는 경우에는 `rtdm_dev_unregister` 함수를 사용한다. 이를 통해 디바이스는 더 이상 접근이 불가능하게 된다.

```c
rtdm_dev_unregister(&my_device, 1000); // 1000ms 내에 디바이스를 안전하게 닫음
```

#### 예제: 간단한 RTDM 드라이버 작성

여기서는 간단한 RTDM 드라이버를 작성하여 Xenomai의 RTDM API 사용 방법을 소개한다.

1. **드라이버 초기화 및 해제 함수 작성**

   드라이버 초기화 함수와 해제 함수를 작성한다. 이 함수들은 커널 모듈이 로드되고 언로드될 때 호출된다.

```c
static int __init my_driver_init(void) {
    return rtdm_dev_register(&my_device);
}

static void __exit my_driver_exit(void) {
    rtdm_dev_unregister(&my_device, 1000); // 1000ms 내에 디바이스를 안전하게 닫음
}

module_init(my_driver_init);
module_exit(my_driver_exit);
```

2. **파일 조작 함수 정의**

   드라이버에서 필요한 파일 조작 함수들을 정의한다. 이는 `rtdm_operations` 구조체에 포함된다.

```c
static int my_open_function(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, int oflag) {
    // open 함수 로직
    return 0;
}

static int my_close_function(struct rtdm_dev_context *context, rtdm_user_info_t *user_info) {
    // close 함수 로직
    return 0;
}

static ssize_t my_read_function(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, void *buf, size_t nbyte) {
    // read 함수 로직
    return nbyte;
}

static ssize_t my_write_function(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, const void *buf, size_t nbyte) {
    // write 함수 로직
    return nbyte;
}

static int my_ioctl_function(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg) {
    // ioctl 함수 로직
    return 0;
}
```

3. **rtdm\_device 구조체 초기화 및 등록**

   드라이버에 대한 메타 데이터를 포함하는 `rtdm_device` 구조체를 초기화하고 등록한다.

```c
struct rtdm_device my_device = {
    .device_name = "my_device",
    .device_id = 123,
    .device_flags = RTDM_NAMED_DEVICE,
    .ops = {
        .open = my_open_function,
        .close = my_close_function,
        .read_nrt = my_read_function,
        .write_nrt = my_write_function,
        .ioctl_nrt = my_ioctl_function,
    }
};
```

#### 모듈 메타 정보

마지막으로, 모듈 메타 정보를 추가한다. 이는 모듈이 어떤 용도를 위한 것인지 설명한다.

```c
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple RTDM driver example");
MODULE_VERSION("1.0");
```

이제 간단한 RTDM 드라이버 작성 예제가 완료되었다. 이 예제는 너무 간단하므로 실제 프로젝트에서는 더욱 복잡한 논리와 에러 핸들링이 필요할 수 있다.

***

Xenomai의 RTDM API를 사용하면 실시간 애플리케이션과 하드웨어 간의 상호작용을 보다 효율적이고 예측 가능하게 할 수 있다. RTDM 드라이버는 기본적인 POSIX 표준을 준수하면서도 실시간 특성을 유지하며, 이를 통해 고성능의 실시간 시스템을 구축할 수 있다.
