Xenomai가 컴파일되고 설치된 후, 우리가 실행하려는 시스템에서 제대로 작동하는지 확인하는 과정이 필요하다. 이 절에서는 Xenomai의 설치를 확인하는 방법을 다룬다.

uname으로 확인

가장 먼저, 적절한 Xenomai 커널이 로드되었는지 확인해야 한다. 이를 확인하려면 uname 명령어를 사용한다.

uname -a

이 명령어는 현재 커널과 관련된 모든 정보를 출력한다. 만약 Xenomai가 올바르게 설치되었고 현재 커널에 패치되었다면, 출력 결과에 Xenomai라는 단어가 포함되어 있어야 한다. 예를 들어:

Linux hostname 5.4.50-xenomai-3.1.x #1 SMP PREEMPT Wed Jun 24 14:31:21 PDT 2020 x86_64 GNU/Linux

위의 예에서 5.4.50-xenomai-3.1.x는 Xenomai가 커널에 제대로 패치되었음을 나타낸다.

xeno-test로 성능 테스트

Xenomai 배포판은 다양한 테스트 프로그램을 제공하며, 이러한 프로그램들을 통해 시스템이 실시간 요구 사항을 충족하는지 확인할 수 있다. 그 중 xeno-test는 기본적인 성능 테스트를 수행하며 Xenomai 설치 확인의 중요한 도구이다.

  1. xeno-test를 실행한다:
sudo /usr/xenomai/bin/xeno-test
  1. 테스트 결과를 분석한다:
  2. 테스트가 성공적으로 완료되면, 각종 통계 정보와 시스템의 실시간 응답 시간에 대한 정보가 표시된다.
  3. 실패하거나 비정상적으로 높은 지연 시간이 발생하는 경우, 커널 설정 또는 하드웨어 구성의 문제일 수 있다.

latency 테스트

latency 테스트 프로그램은 시스템의 실시간 성능을 측정하는 또 다른 유용한 도구이다. 이 프로그램은 시스템의 최대 및 평균 지연 시간을 보여준다.

  1. latency 프로그램 실행:
sudo /usr/xenomai/bin/latency
  1. 테스트 결과 분석:
  2. 이 테스트는 시스템의 최대 지연 시간과 평균 지연 시간을 표시한다.
  3. 일반적으로 실제 실시간 시스템에서는 지연 시간이 마이크로초 단위에서 유지되어야 한다.

dual-core 시스템에서의 확인

듀얼 코어 시스템이나 멀티 코어 시스템에서는 각 코어가 실시간 요구사항을 적절히 처리하는지 확인해야 한다. 이를 위해, Xenomai는 klatency 테스트 프로그램을 제공한다.

  1. klatency 프로그램 실행:
sudo /usr/xenomai/bin/klatency
  1. 결과 분석:
  2. 테스트 동안 각 코어에서 발생하는 최대 및 평균 지연 시간을 모니터링할 수 있다.
  3. 각 코어의 지연 시간이 실시간 요구사항을 충족하는지 확인한다.

이제 Xenomai가 올바르게 설치되고 시스템이 실시간 요구 사항을 제대로 처리할 수 있는지 확인되었으므로, 간단한 예제를 통해 실제로 Xenomai 애플리케이션을 작성해본다. 이 예제에서는 가장 기본적인 Xenomai 실시간 태스크를 생성하고 실행하는 방법을 보여준다.

코드 작성

아래는 Xenomai 프로그램을 작성하는 기본 예제이다. 이 예제는 실시간 태스크를 생성하고 주기적으로 메시지를 출력하는 프로그램이다.

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <alchemy/task.h>

#define TASK_PRIO 99        /* Highest RT priority */
#define TASK_MODE 0         /* No flags */
#define TASK_STKSZ 0        /* Default stack size */
#define TASK_PERIOD 1e9     /* 1 second in nanoseconds */

RT_TASK demo_task;

void catch_signal(int sig)
{
    /* Handle CTRL+C to exit program */
    printf("Exiting program\n");
    rt_task_delete(&demo_task);
    exit(0);
}

void demo(void *arg)
{
    int count = 0;
    rt_task_set_periodic(NULL, TM_NOW, TASK_PERIOD);

    while (1) {
        rt_task_wait_period(NULL);
        printf("task execution, count = %d\n", ++count);
    }
}

int main(int argc, char *argv[])
{
    signal(SIGTERM, catch_signal);
    signal(SIGINT, catch_signal);

    /* Avoids memory swapping for this program */
    mlockall(MCL_CURRENT | MCL_FUTURE);

    /* Create real-time task */
    rt_task_create(&demo_task, "Xenomai_demo_task", TASK_STKSZ, TASK_PRIO, TASK_MODE);

    /* Start real-time task */
    rt_task_start(&demo_task, &demo, NULL);

    pause();

    return 0;
}

컴파일

작성한 Xenomai 프로그램을 컴파일하기 위해 알맞은 컴파일 명령어를 사용해야 한다. 이 예제 프로그램을 demo.c 파일로 저장했다면, 다음과 같이 컴파일할 수 있다:

gcc -o demo demo.c -lxenomai -lpthread -lnative

실행

이제 프로그램을 실행하여, 실시간 태스크가 주기적으로 메시지를 출력하는지 확인할 수 있다:

sudo ./demo

프로그램이 성공적으로 동작한다면, 출력 창에 주기적으로 task execution, count = n과 같은 메시지가 출력된다. 여기서 n은 현재 실행 주기를 나타낸다.

시그널 처리

위 예제에서는 CTRL+C 나 SIGTERM 시그널을 받아 프로그램이 안전하게 종료될 수 있도록 시그널 핸들러를 등록하였다. 이 핸들러는 실시간 태스크를 삭제하고 프로그램을 종료한다.

메모리 잠금

mlockall(MCL_CURRENT | MCL_FUTURE) 함수 호출은 프로그램이 메모리 스왑으로 인해 지연되지 않도록 메모리를 잠급니다. 실시간 시스템에서는 매우 중요한 작업 중 하나이며, 예기치 않은 메모리 스왑으로 실시간 응답성이 떨어지는 것을 방지한다.

이로써 기본적인 Xenomai 실시간 태스크 프로그래밍 방식을 익혔습니다. 이제 이를 토대로 더욱 복잡하고, 다양한 실시간 애플리케이션을 개발할 수 있다.