Xenomai 세마포어
세마포어란 무엇인가
세마포어는 동기화 도구로, 여러 스레드가 자원을 안전하게 공유할 수 있도록 도와준다. 쉽게 말해, 세마포어는 특정 자원에 접근하려는 스레드의 수를 제어하는 역할을 한다.
세마포어의 작동 원리
세마포어는 내부적으로 카운터를 유지하며, 이 카운터는 잠금 및 해제 시 증가하거나 감소한다.
- 리소스 접근 (P 연산):
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 연산):
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를 많이 따른다. 주요 함수는 다음과 같다:
rt_sem_p()
: 세마포어 대기 (P 연산)rt_sem_v()
: 세마포어 해제 (V 연산)rt_sem_create()
: 세마포어 생성rt_sem_delete()
: 세마포어 삭제
세마포어 예제 코드
#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) 상태를 갖는다.
- 잠금 (Lock): 자원을 사용하려는 스레드는 뮤텍스를 잠금으로 설정한다.
- 만약 뮤텍스가 이미 잠긴 상태라면, 해당 스레드는 블록된다.
- 잠금 해제 (Unlock): 자원을 다 사용한 후, 잠금을 해제하여 다른 스레드가 자원을 사용하도록 한다.
Xenomai에서의 뮤텍스 사용법
Xenomai는 기본적으로 POSIX 뮤텍스 API를 많이 따른다. 주요 함수는 다음과 같다:
rt_mutex_create()
: 뮤텍스 생성rt_mutex_delete()
: 뮤텍스 삭제rt_mutex_acquire()
: 뮤텍스 잠금rt_mutex_release()
: 뮤텍스 잠금 해제
뮤텍스 예제 코드
#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 활용 시, 세마포어와 뮤텍스를 적절히 사용하는 것이 매우 중요하다. 각각의 특징과 작동 원리를 이해하고, 제시된 예제 코드를 바탕으로 응용하면, 실시간 운영 체제에서 안전하고 효율적인 스레드 동기화를 구현할 수 있다.