dev/rtos

세마포어(Semaphore)

조뎅 2020. 8. 4. 21:58
728x90

세마포어 정의

세마포어(세마포어 토큰이라고도 함)는 실행 중인 여러 태스크가동기화 또는 상호배제를 목적으로 획득(acquire)하거나 반환(release) 할 수 있는 커널 오브젝트

세마포어는 세마포어 컨트롤 블록(SCB), 고유 ID, 초기값(바이너리 또는 카운트),태스크 대기 리스트 등을 할당 받음

 

세마포어 종류

바이너리 세마포어

  • 또는 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