서론
Xenomai는 실제 실시간 성능이 중요한 애플리케이션을 개발할 수 있도록 지원하는 실시간 커널이다. 이 중에서도 네이티브 스킨은 가장 기본적인 API 집합을 제공하며, 사용자는 이를 통해 실시간 태스크를 생성하고 관리할 수 있다.
태스크 생성 및 삭제
Xenomai 네이티브 스킨에서 태스크(Task)는 실시간 애플리케이션의 기본 단위이다. 태스크는 rt_task_create()
함수를 사용하여 생성할 수 있다.
태스크 생성
#include <native/task.h>
RT_TASK task;
int rt_task_create (RT_TASK *task, const char *name, int stksize, int prio, int mode);
task
: 태스크 핸들.name
: 태스크의 이름.stksize
: 태스크 스택 크기 (0이면 시스템 기본값 사용).prio
: 태스크의 우선순위 (0~99, 값이 높을수록 높은 우선순위).mode
: 태스크 모드 (0 또는 여러 모드 플래그의 결합).
예제:
RT_TASK my_task;
int res = rt_task_create(&my_task, "MyTask", 0, 50, 0);
if (res != 0) {
// 에러 처리
}
태스크 삭제
생성된 태스크는 rt_task_delete()
함수를 사용하여 삭제할 수 있다.
#include <native/task.h>
int rt_task_delete (RT_TASK *task);
task
: 태스크 핸들.
예제:
rt_task_delete(&my_task);
태스크 시작 및 정지
태스크 시작
rt_task_start()
함수는 생성된 태스크를 시작한다. 태스크는 시작 시 실행될 함수(entry point)와 그 함수에 전달될 인자들을 지정할 수 있다.
#include <native/task.h>
int rt_task_start (RT_TASK *task, void (*entry)(void *arg), void *arg);
task
: 태스크 핸들.entry
: 실행될 함수.arg
: 함수에 전달될 인자.
예제:
void task_function(void *arg) {
// 태스크 동작 정의
}
rt_task_start(&my_task, task_function, NULL);
태스크 정지
태스크는 rt_task_suspend()
함수를 통해 정지시킬 수 있다.
#include <native/task.h>
int rt_task_suspend (RT_TASK *task);
task
: 태스크 핸들.
예제:
rt_task_suspend(&my_task);
태스크 속성 변경
실시간 태스크의 속성은 태스크가 실행 중일 때에도 동적으로 변경할 수 있다. rt_task_set_priority()
함수를 사용하여 태스크의 우선순위를 변경할 수 있다.
int rt_task_set_priority (RT_TASK *task, int prio);
task
: 태스크 핸들.prio
: 새로운 우선순위.
예제:
rt_task_set_priority(&my_task, 60);
주기적 태스크
주기적 태스크는 일정 시간 간격으로 반복적으로 실행되는 태스크이다. rt_task_set_periodic()
함수와 rt_task_wait_period()
함수를 사용하여 구현할 수 있다.
주기 설정
rt_task_set_periodic()
함수는 태스크의 주기를 설정한다.
int rt_task_set_periodic (RT_TASK *task, RTIME idate, RTIME period);
task
: 태스크 핸들.idate
: 최초 주기 시작 시간 (0이면 바로 시작).period
: 주기.
예제:
RTIME period = 1000000000; // 1초 주기
rt_task_set_periodic(&my_task, TM_NOW, period);
주기 대기
rt_task_wait_period()
함수는 현재 주기가 끝날 때까지 대기한다.
int rt_task_wait_period (void);
예제:
void task_function(void *arg) {
while (1) {
rt_task_wait_period();
// 주기적 작업 수행
}
}
태스크 동기화
Xenomai 네이티브 스킨은 태스크 간의 동기화 및 커뮤니케이션을 위한 다양한 메커니즘을 제공한다. 여기에는 세마포어, 메시지 큐, 이벤트 플래그 등이 포함된다.
세마포어
세마포어는 태스크 간의 동기화에 사용되며, 동일한 리소스를 여러 태스크가 접근하는 것을 조정한다.
세마포어 생성
#include <native/sem.h>
RT_SEM sem;
int rt_sem_create (RT_SEM *sem, const char *name, unsigned long ivalue, int mode);
sem
: 세마포어 핸들.name
: 세마포어 이름.ivalue
: 초기 값.mode
: 세마포어 모드.
예제:
RT_SEM my_sem;
rt_sem_create(&my_sem, "MySem", 1, S_PRIO);
세마포어 잠금
int rt_sem_p (RT_SEM *sem, RTIME timeout);
sem
: 세마포어 핸들.timeout
: 타임아웃 시간 (TM_INFINITE이면 무한 대기).
예제:
rt_sem_p(&my_sem, TM_INFINITE);
세마포어 해제
int rt_sem_v (RT_SEM *sem);
sem
: 세마포어 핸들.
예제:
rt_sem_v(&my_sem);
메시지 큐
메시지 큐는 태스크 간 메시지 전달을 위한 큐잉 메커니즘을 제공한다.
메시지 큐 생성
#include <native/msg.h>
RT_QUEUE mq;
int rt_queue_create (RT_QUEUE *q, const char *name, size_t poolsize, Q_PARAM qparam);
q
: 큐 핸들.name
: 큐 이름.poolsize
: 큐 메모리 크기.qparam
: 큐 파라미터.
예제:
RT_QUEUE my_queue;
size_t poolsize = 10 * sizeof(int);
rt_queue_create(&my_queue, "MyQueue", poolsize, Q_UNLIMITED);
메시지 큐 전송
int rt_queue_send (RT_QUEUE *q, const void *msg, size_t size, int mode);
q
: 큐 핸들.msg
: 메시지 포인터.size
: 메시지 크기.mode
: 큐 모드 (Q_NORMAL, Q_URGENT 등).
예제:
int data = 42;
rt_queue_send(&my_queue, &data, sizeof(data), Q_NORMAL);
메시지 큐 수신
int rt_queue_receive (RT_QUEUE *q, void **msg, size_t size, RTIME timeout);
q
: 큐 핸들.msg
: 메시지 포인터에 대한 포인터.size
: 메시지 크기.timeout
: 타임아웃 시간.
예제:
int *recv_ptr;
rt_queue_receive(&my_queue, (void **)&recv_ptr, sizeof(int), TM_INFINITE);
int received_data = *recv_ptr;
이벤트 플래그
이벤트 플래그는 특정 이벤트의 발생을 다른 태스크에 알리기 위해 사용된다.
이벤트 플래그 생성
#include <native/event.h>
RT_EVENT evt;
int rt_event_create (RT_EVENT *evt, const char *name, int mode);
evt
: 이벤트 핸들.name
: 이벤트 이름.mode
: 이벤트 모드.
예제:
RT_EVENT my_event;
rt_event_create(&my_event, "MyEvent", 0);
이벤트 플래그 설정
int rt_event_signal (RT_EVENT *evt, eventflg_t mask);
evt
: 이벤트 핸들.mask
: 설정할 이벤트 플래그 마스크.
예제:
rt_event_signal(&my_event, 0x01);
이벤트 플래그 대기
int rt_event_wait (RT_EVENT *evt, eventflg_t mask, unsigned flags, RTIME timeout);
evt
: 이벤트 핸들.mask
: 대기할 이벤트 플래그 마스크.flags
: 대기 조건 플래그 (EV_ANY, EV_ALL 등).timeout
: 타임아웃 시간.
예제:
rt_event_wait(&my_event, 0x01, EV_ALL, TM_INFINITE);
관리 및 모니터링
네이티브 스킨은 태스크, 세마포어, 메시지 큐, 이벤트 등 다양한 리소스의 상태를 모니터링하고 관리하기 위한 함수들을 제공한다. 이를 통해 시스템 상태를 추적하고 성능을 최적화할 수 있다.
태스크 정보 조회
rt_task_inquire()
함수는 특정 태스크의 상태 정보를 조회한다.
#include <native/task.h>
int rt_task_inquire (RT_TASK *task, RT_TASK_INFO *info);
task
: 태스크 핸들.info
: 태스크 정보 구조체.
예제:
RT_TASK_INFO info;
rt_task_inquire(&my_task, &info);
printf("Task name: %s\n", info.name);
시스템 상태 조회
Xenomai는 다양한 시스템 상태를 조회할 수 있는 여러 함수를 제공한다. 예를 들어, rt_cpu_time()
함수는 현재 CPU 시간을 반환한다.
#include <native/timer.h>
RTIME rt_cpu_time (void);
예제:
RTIME cpu_time = rt_cpu_time();
printf("CPU time: %llu\n", cpu_time);
이 장에서는 Xenomai 네이티브 스킨을 사용한 태스크 생성, 관리 및 동기화 방법을 다루었다. 이러한 기법들을 사용하여 실시간 애플리케이션의 성능과 안정성을 높일 수 있는 다양한 방법들을 배울 수 있었다.