Xenomai 세마포어

세마포어란 무엇인가

세마포어는 동기화 도구로, 여러 스레드가 자원을 안전하게 공유할 수 있도록 도와준다. 쉽게 말해, 세마포어는 특정 자원에 접근하려는 스레드의 수를 제어하는 역할을 한다.

세마포어의 작동 원리

세마포어는 내부적으로 카운터를 유지하며, 이 카운터는 잠금 및 해제 시 증가하거나 감소한다.

P(s) \text{ 즉 } \text{wait}(s): \begin{cases} \text{if } (s > 0) \\ \quad s \leftarrow s - 1 \\ \text{else} \\ \quad \text{block the thread} \end{cases}
V(s) \text{ 즉 } \text{signal}(s): \begin{cases} s \leftarrow s + 1 \\ \text{if any threads are blocked} \\ \quad \text{unblock a single thread} \end{cases}

Xenomai에서의 세마포어 사용법

Xenomai는 기본적으로 POSIX 세마포어 API를 많이 따른다. 주요 함수는 다음과 같다:

세마포어 예제 코드

#include <native/sem.h>
#include <native/task.h>
#include <rtdk.h>

RT_SEM semaphore;

void task1(void *arg) {
    rt_task_set_periodic(NULL, TM_NOW, 1e5); // 주기 설정
    while(1) {
        rt_sem_p(&semaphore, TM_INFINITE); // 세마포어 잠금
        rt_printf("Task 1: Critical section\n");
        rt_sem_v(&semaphore); // 세마포어 해제
        rt_task_wait_period(NULL);
    }
}

void task2(void *arg) {
    rt_task_set_periodic(NULL, TM_NOW, 1e5); // 주기 설정
    while(1) {
        rt_sem_p(&semaphore, TM_INFINITE); // 세마포어 잠금
        rt_printf("Task 2: Critical section\n");
        rt_sem_v(&semaphore); // 세마포어 해제
        rt_task_wait_period(NULL);
    }
}

int main(int argc, char* argv[]) {
    rt_sem_create(&semaphore, "MySemaphore", 1, S_PRIO);
    rt_task_create(&task1_t, "Task 1", 0, 50, 0);
    rt_task_create(&task2_t, "Task 2", 0, 50, 0);
    rt_task_start(&task1_t, &task1, NULL);
    rt_task_start(&task2_t, &task2, NULL);
    pause();
    rt_sem_delete(&semaphore);
    return 0;
}

Xenomai 뮤텍스

뮤텍스란 무엇인가

뮤텍스(Mutex)는 Mutual Exclusion의 약자로, 주요 기능은 한 번에 하나의 스레드만 특정 자원에 접근하도록 보장하는 것이다. 뮤텍스는 잠금을 얻은 스레드만 자원을 사용할 수 있으며, 다른 스레드는 잠금이 해제될 때까지 대기한다.

뮤텍스의 작동 원리

뮤텍스는 두 가지 기본 상태인 '잠김'(Locked)과 '잠금 해제'(Unlocked) 상태를 갖는다.

Xenomai에서의 뮤텍스 사용법

Xenomai는 기본적으로 POSIX 뮤텍스 API를 많이 따른다. 주요 함수는 다음과 같다:

뮤텍스 예제 코드

#include <native/mutex.h>
#include <native/task.h>
#include <rtdk.h>

RT_MUTEX mutex;

void task1(void *arg) {
    rt_task_set_periodic(NULL, TM_NOW, 1e5); // 주기 설정
    while(1) {
        rt_mutex_acquire(&mutex, TM_INFINITE); // 뮤텍스 잠금
        rt_printf("Task 1: Critical section\n");
        rt_mutex_release(&mutex); // 뮤텍스 해제
        rt_task_wait_period(NULL);
    }
}

void task2(void *arg) {
    rt_task_set_periodic(NULL, TM_NOW, 1e5); // 주기 설정
    while(1) {
        rt_mutex_acquire(&mutex, TM_INFINITE); // 뮤텍스 잠금
        rt_printf("Task 2: Critical section\n");
        rt_mutex_release(&mutex); // 뮤텍스 해제
        rt_task_wait_period(NULL);
    }
}

int main(int argc, char* argv[]) {
    rt_mutex_create(&mutex, "MyMutex");
    rt_task_create(&task1_t, "Task 1", 0, 50, 0);
    rt_task_create(&task2_t, "Task 2", 0, 50, 0);
    rt_task_start(&task1_t, &task1, NULL);
    rt_task_start(&task2_t, &task2, NULL);
    pause();
    rt_mutex_delete(&mutex);
    return 0;
}

세마포어와 뮤텍스의 차이점


Xenomai 활용 시, 세마포어와 뮤텍스를 적절히 사용하는 것이 매우 중요하다. 각각의 특징과 작동 원리를 이해하고, 제시된 예제 코드를 바탕으로 응용하면, 실시간 운영 체제에서 안전하고 효율적인 스레드 동기화를 구현할 수 있다.