728x90
세마포어 정의
세마포어(세마포어 토큰이라고도 함)는 실행 중인 여러 태스크가동기화 또는 상호배제를 목적으로 획득(acquire)하거나 반환(release) 할 수 있는 커널 오브젝트
세마포어는 세마포어 컨트롤 블록(SCB), 고유 ID, 초기값(바이너리 또는 카운트),태스크 대기 리스트 등을 할당 받음
세마포어 종류
바이너리 세마포어
- 0 또는 1의 상태값을 갖음
- 0일 때 사용 불가능(unavailable or empty), 1 일 때 사용 가능(available or full)
- 전역 자원(global resource)으로써 기존에 세마포어를 획득한 태스크가 아닌 어떤 태스크라도 자유롭게 세마포어 변환 가능
카운팅 세마포어
- 내부 카운터(내부 토큰 개수) 사용하여 여러 차례 획득하고 반환 할 수 있음
- 초기 토큰 개수를 지정하여 세마포어를 생성(초기 토큰 개수 = 0 or초기 토큰 개수> 0)
- 초기 토큰 개수 0으로 생성 시 세마포어 사용 불가능 상태로 생성
- 전역 자원(global resource)으로써 기존에 세마포어를 획득한 태스크가 아닌 어떤 태스크라도 자유롭게 세마포어 변환 가능
- 바운디드 세마포어(초기 카운트 값이 세마포어의 최대 카운트 값으로 생성),언바운디드 세마포어(카운트 값이 세마포어의 최대 카운트 값을 넘어설 수 있음)으로 나뉨
상호배제 세마포어 / Mutex(mutual exclusion semaphore)
- 특별한 형태의 바이너리 세마포어
- 0일 때 풀림 상태(획득 가능), 1일 때 잠김 상태(획득 불가능)
- 뮤텍스는 풀림 상태로 생성되어 바로 획득 가능
- 소유권, 재귀적 잠금, 안전한 태스크 삭제,우선 순위 역전 회피 등의 기능 지원
뮤텍스 특징
뮤텍스 소유권 / Mutex Ownership
- 태스크가 뮤텍스를 획득했다면,뮤텍스 소유권을 얻음, 뮤텍스 반환 시 소유권도 잃음
- 소유권이 없는 다른 태스크들은 해당 뮤텍스를 획득 할 수 없음
재귀적 잠금 / Recursive Locking
- 뮤텍스를 획득한 태스크가 잠긴 상태의 뮤텍스를 몇번이고 획득 할 수 있는 기능
- 획득한 횟수 만큼 반환해야 풀림 상태가 됨
안전한 태스크 삭제 / Task Deletion Safety
- 태스크 삭제 방지 기능을 활성화한 뮤텍스를 소유한 태스크는 뮤테스를 소유하는 동안 다른 태스크에 의해 삭제되지 않음
우선 순위 역전 회피 / Priority Inversion Avoidance
- 우선 순위 상속 프로토콜(priority inheritance protocol): 뮤텍스를 획득한 낮은 우선 순위의 태스크의 우선 순위를 임시로 뮤텍스를 요청한 높은 우선 순위의 태스크와 같게 변경
- 상한 우선 순위 프로토콜(ceiling prioirty protocol): 태스크가 뮤텍스를 획득 할 때 태스크의 우선 순위를 해당 뮤텍스를 사용할 가능성이 있는 태스크 중 가장 높은 우선 순위를 가진 태스크의 우선 순위로 변경
읽기/쓰기 세마포어(Read/Write Semaphore)
- 공유자원에 접근 성능 향상을 위해 제공
- 공유자원에 대해서는 읽기/쓰기(Read/Write) 두가지의 행위로만 이뤄짐
- 만일 하나의 태스크가 읽기 모드로 해당 세마포어를 획득하였다면, 다른 태스크가 쓰기 모드로는 해당 세마포어를 획득 할 수 없지만,읽기 모드로는 해당 세마포어가 획득 가능
- 하여 공유자원에 대한 읽기 성능에 대해 최적화 할 수 있음
세마포어 함수
세마포어 함수(VxWorks 7 기준)
Function | Description |
semBInitialize() | 할당되어있는 바이너리 세마포어 초기화 |
semCInitialize() | 할당되어있는 카운팅 세마포어 초기화 |
semMInitialize() | 할당되어있는 뮤텍스 세마포어 초기화 |
semRWInitalize() | 할당되어있는 읽기/쓰기 세마포어 초기화 |
semBCreate() | 바이너리 세마포어 할당 |
semCCreate() | 카운팅 세마포어 할당 |
semMCreate() | 뮤텍스 세마포어 할당 |
semRWCreate() | 읽기/쓰기 세마포어 할당 |
semDelete() | 세마포어 해제(모든 타입) |
semTake() | 세마포어 획득(모든 타입, 쓰기 모드) |
semRTake() | 읽기/쓰기 세마포어 획득(읽기 모드) |
semWTake() | 읽기/쓰기 세마포어 획득(쓰기 모드) |
semGive() | 세마포어 반환(바이너리 | 카운팅 | 뮤텍스) |
semRWGive() | 읽기/쓰기 세마포어 반환 |
semMGiveForce() | 뮤텍스 세마포어 반환(디버깅 목적) |
semRWGiveForce() | 읽기/쓰기 세마포어 반환(디버깅 목적) |
semFlush() | 모든 대기 태스크 제거(바이너리 | 카운팅) |
semExchange() | SMP(대칭형다중처리) 시스템에서의 세마포어 교환을 제공 |
세마포어 생성 옵션
Option | Description |
SEM_Q_PRIORITY | 태스크 우선순위에 따라 대기 |
SEM_Q_FIFO | 태스크 선입선출에 따라 대기 |
SEM_EMPTY | 세마포어 사용 불가능(empty) 상태로 생성 |
SEM_FULL | 세마포어 사용 가능(full) 상태로 생성 |
SEM_KERNEL | 커널 레벨로 세마포어 생성(뮤텍스) |
SEM_INVERSION_SAFE | 우선 순위 역전 회피 옵션(뮤텍스, SEM_Q_PRIORITY옵션과 함께 사용) |
SEM_DELETE_SAFE | 안전한 태스크 삭제 옵션(뮤텍스) |
세마포어 매크로
Macro | Description |
VX_BINARY_SEMAPHORE | 바이너리 세마포어 선언 |
VX_COUNTING_SEMAPHORE | 카운팅 세마포어 선언 |
VX_MUTEX_SEMAPHORE | 뮤텍스 세마포어 선언 |
VX_READ_WRITE_SEMAPHORE | 읽기/쓰기 세마포어 선언 |
세마포어 선언 예제
함수 호출
#include <vxWorks.h>
#include <semLib.h>
SEM_ID mySemBId; /* semaphore ID for further operations */
STATUS initializeFunction (void)
{
if ((mySemBId = semBCreate(SEM_Q_FIFO, SEM_EMPTY) == NULL)
return(ERROR); /* initialization failed */
else
return(OK);
}
매크로 호출
#include <vxWorks.h>
#include <semLib.h>
VX_BINARY_SEMAPHORE(mySemB); /* declare the semaphore */
SEM_ID mySemBId; /* semaphore ID for further operations */
STATUS initializeFunction (void)
{
if ((mySemBId = semBInitialize(mysemB, options, 0)) == NULL)
return(ERROR); /* initialization failed */
else
return(OK);
}
세마포어 예제
대기-신호(Wait - Singal) 동기화
#include <vxWorks.h>
#include <semLib.h>
SEM_ID mySemB;
mySemB = semBCreate(SEM_Q_FIFO, SEM_EMPTY); // 세마포어 할당
tWaitTask() // 우선 순위 높음
{
semTake(mySemB, WAIT_FOREVER); // 바이너리 세마포어 획득 요청
... // 작업 수행
}
tSignalTask()
{
semGive(mySemB); // 바이너리 세마포어 반환
}
여러 태스크의 대기-신호(Wait-Signal) 동기화
#include <vxWorks.h>
#include <semLib.h>
SEM_ID mySemB;
mySemB = semBCreate(SEM_Q_FIFO, SEM_EMPTY); // 세마포어 할당
tWaitTask() // 우선 순위 높음
{
semTake(mySemB, WAIT_FOREVER); // 바이너리 세마포어 획득 요청
... // 태스크 별 작업 수행
semGive(mySemB); // 바이너리 세마포어 반환
}
tSignalTask()
{
semFlush(mySemB); // 바이너리 세마포어 대기 리스트를 비움(Flush)
}
크레딧-트랙킹(Credit-Tracking) 동기화
#include <vxWorks.h>
#include <semLib.h>
SEM_ID mySemC;
mySemC = semCCreate(SEM_Q_FIFO, SEM_EMPTY); // 세마포어 할당
tWaitTask()
{
semTake(mySemC, WAIT_FOREVER); // 카운팅 세마포어 획득 요청
... // 작업 처리 수행
}
tSignalTask() // 우선 순위 높음, 주기 실행
{
semGive(mySemC); // 카운팅 세마포어 반환
... // 작업 발행
}
단일 공유자원 접근 동기화
#include <vxWorks.h>
#include <semLib.h>
SEM_ID mySemB;
mySemB = semBCreate(SEM_Q_FIFO, SEM_FULL); // 세마포어 할당
tAccessTask()
{
semTake(mySemB, WAIT_FOREVER); // 바이너리 세마포어 획득 요청
... // 공유자원 데이터 읽기/쓰기
semGive(mySemB); // 바이너리 세마포어 반환
}
재귀적 공유자원 접근 동기화
#include <vxWorks.h>
#include <semLib.h>
SEM_ID mySemM;
mySemM = semMCreate(SEM_Q_FIFO); // 세마포어 할당
tAccessTask()
{
semTake(mySemM, WAIT_FOREVER); // 뮤텍스 획득 요청
... // 공유자원 데이터 읽기/쓰기
RoutineA(); // Routine A 호출
semGive(mySemM); // 뮤텍스 반환
}
RoutineA()
{
semTake(mySemM, WAIT_FOREVER); // 뮤텍스 획득 요청
... // 공유자원 데이터 읽기/쓰기
RoutineB(); // Routine B 호출
semGive(mySemM); // 뮤텍스 반환
}
RoutineB()
{
semTake(mySemM, WAIT_FOREVER); // 뮤텍스 획득 요청
... // 공유자원 데이터 읽기/쓰기
semGive(mySemM); // 뮤텍스 반환
}
복수 공유자원 접근 동기화
#include <vxWorks.h>
#include <semLib.h>
SEM_ID mySemC;
mySemC = semCCreate(SEM_Q_FIFO, 2); // 세마포어 할당
tAccessTask()
{
semTake(mySemC, WAIT_FOREVER); // 카운팅 세마포어 획득 요청
... // 공유자원 데이터 읽기/쓰기
semGive(mySemC); // 카운팅 세마포어 반환
}
728x90
'dev > rtos' 카테고리의 다른 글
메시지 큐(Message Queue) (0) | 2020.08.04 |
---|---|
태스크(Task) (0) | 2020.08.04 |
RTOS란? (0) | 2020.08.04 |