본문 바로가기
임베디드 관련/FreeRTOS

[FreeRTOS] Critical Section(임계 영역), 공유자원 보호하기

by minhyeok.lee 2024. 6. 10.
반응형

FreeRTOS에서 Critical Section(임계 영역), 공유자원 보호하기

 

임계 영역이란?

2024.05.21 - [소프트웨어 공학 용어 정리] - [SW 용어] 동기화(Synchronization), 임계 영역(Critical Section)

 

[SW 용어] 동기화(Synchronization), 임계 영역(Critical Section)

동기화(Synchronization)1. 동기화는 시스템을 동시에 작동시키기 위해 여러 사건들을 조화시키는 것을 의미한다.2. 병행성과 관련해서 공유되는 자원에 대한 이해와 공유자원 사용과 관련해서 생길

kfdd6630.tistory.com

 


임계 영역을 보호하는 4가지 방법

1. 인터럽트 중단(taskENTER_CRITICAL(), taskEXIT_CRITICAL() 사용)

1. taskENTER_CRITICAL()과 taskEXIT_CRITICAL()를 사용하여 interrupt를 막는다.

2. interrupt를 막아 preemtion(선점)과 context switching(문맥 교환)을 방지하여 독점을 보장한다.

3. 임계 영역 진입 전에 taskENTER_CRITICAL()를 호출하여 인터럽트를 비활성화하고 수행 후 taskEXIT_CRITICAL()를 호출하여 인터럽트를 활성화한다.

4. taskENTER_CRITICAL()과 taskEXIT_CRITICAL()는 FreeRTOS에서 제공하는 커널 API로 인터럽트보다 우선순위가 높다.

 

예시)

taskENTER_CRITICAL();
// 공유 자원 접근 및 사용
taskEXIT_CRITICAL();

 



2. Semaphore/Mutex 사용

1. 임계 영역에 대한 lock(p, wait, take)연산과 unlock(v, signal, give) 연산을 통해 자원에 대한 독점을 보장한다.

2. 자체 오버헤드가 존재하지만 유연하게 안전한 프로그램을 만들 수 있다.


Semaphore

Semaphore(세마포어)는 동기화 및 공유자원 보호 그리고 이벤트 전달 용도로 사용한다.

1. 세마포어를 초기화한다.

2. 공유자원에 접근하기 위해서는 세마포어를 획득한다.

3. 공유자원을 다 사용한 뒤에는 세마포어를 반환해야 한다.

4. 사용하지 않는 세마포어는 제거한다.

초기화: xSemaphoreCreateBinary(), xSemaphoreCreateCounting()

SemaphoreHandle_t xSemaphore;

// xSemaphoreCreateBinary 생성 예제
void vATask( void * pvParameters )
{
    xSemaphore = xSemaphoreCreateBinary();

    if( xSemaphore == NULL )
    {
    }
}

// xSemaphoreCreateCounting 생성 예제
void vATask( void * pvParameters )
{
    xSemaphore = xSemaphoreCreateCounting( 10, 0 );

    if( xSemaphore != NULL )
    {
    }
}

획득: p, wait, take연산이라 한다. ( xSemaphoreTake(), xSemaphoreTakeFromISR() )

반환: v, signal, give연산이라 한다. ( xSemaphoreGive(), xSemaphoreGiveFromISR() )

제거: vSemaphoreDelete()

 

세마포어는 공유자원에 따라 두 가지 종류를 가진다.

- Binary Semaphore(이진 세마포어)

1. 0과 1 값으로만 이뤄진 세마포어이다.

2. 임계 영역에 대해 p연산을 수행하면 semaphore가 0이 되서 다른 task의 접근을 막는다.

3. 접근을 요청한 task는 blocked 상태가 되며 들어갈 때 까지 기다린다. (take 함수에서 기다리는 시간을 설정할 수 있다.)

 

- Counting Semaphore(수가 존재하는 세마포어)

1. 0부터 사용자가 설정한 수까지 값을 가지는 세마포어다.

2. 공유자원이 n의 크기를 가지는 배열일 때, 세마포어를 n으로 초기화하면, Counting semaphore는 n을 의미한다.

3. 세마포어가 0이 되면 해당 배열이 가득 찼음을 의미하며 접근을 요청한 task는 blocked상태가 되며 기다린다.

 


 

Mutex

1. binary semaphore과 거의 같은 기능을 수행한다.

2. Priority Inversion(우선순위 역전)를 Priority Inheritance(우선순위 상속)으로 해결할 수 있다.

3. 세마포어는 임계 영역 및 공유자원에 대한 독점권을 보장할 수 있는 동기화 수단이지만, 치명적인 문제인 Priority Inversion(우선순위 역전)를 유발할 수 있다.

 

- 뮤텍스 초기화 ( xSemaphoreCreateMutex() )

 

Priority Inversion(우선순위 역전)

1. 우선순위가 높은 task가 우선순위가 낮은 task의 수행이 끝날 때까지 기다리는 상황이다.

2. 우선순위가 높은 순서대로 task1, task2, task3이 있다고 가정하자.

  - 우선순위가 가장 높은 task1과 우선순위가 가장 낮은 task3은 같은 자원을 공유한다.

  - task3이 세마포어 Take()연산을 수행하고 작업을 하고 있다면 task1은 실행될 때 Blocked 상태가 된다.

 - 이때 공유자원을 사용하지 않는 task2가 실행된다면 task3보다 우선순위가 높기때문에 선점하여 task2가 먼저 실행된다.

 - task2가 모두 실행되고 task3이 다시 실행 후 Give()연산을 수행하면 task1이 실행된다.

이때 우선순위가 가장 높은 task1이 task2에 의해 우선순위가 역전되는 현상을 의미한다.


Priority Inheritance(우선순위 상속)

1. 우선순위 역전 문제를 해결하기 위해 FreeRTOS에서는 우선순위 상속을 사용한다.

2. 위와 같은 예제에서 task3이 Take()연산을 수행하고 task1이 이에 의해 Blocked 상태가 된다면 task3을 task1과 같은 우선순위로 만들어주어 task2에 의해 선점되지 않게 만든다.

3. 이때 task3이 Give()연산을 수행하자마자 원래 우선순위로 돌아간다.

4. 이를 통해 역전 현상을 완전히 해결할 수 있다고는 할 수 없지만 역전 현상의 빈도를 상당히 낮추고 만약 발생하더라도적정한 Time Bound내에 해결되는 좋은 방법이다.

 

전체 예제코드

SemaphoreHandle_t xSemaphore = NULL;

/* 세마포어를 만드는 작업 */
void vATask( void * pvParameters )
{
    /* 공유 자원을 보호하기 위해 세마포어를 만든다. 
    상호 배제를 위해 세마포어를 사용하기 때문에 
    이진 세마포어가 아닌 뮤텍스 세마포어를 만든다.*/
    xSemaphore = xSemaphoreCreateMutex();
}

/* 세마포어를 사용하는 작업 */
void vAnotherTask( void * pvParameters )
{
    /* 다른 코드 수행 영역 */

    if( xSemaphore != NULL )
    {
        /* 세마포를 얻을 수 있는지 확인하고 세마포를 얻을 수 없다면
           10틱을 기다려 사용 가능한 상태가 되는지 확인한다. */
        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
        {
            /* 세마포어를 얻고나서 공유 자원에 액세스할 수 있다. */

            /* 공유 자원 접근 부분 */

            /* 공유 자원 접근을 완료 후 세마포어를 해제*/
            xSemaphoreGive( xSemaphore );
        }
        else
        {
            /* 세마포어를 얻을 수 없어 공유 자원에 안전하게 접근할 수 없을 시 수행 코드*/
        }
    }
}

Mutex, Semaphore란?

2024.05.27 - [소프트웨어 공학 용어 정리] - [SW 용어] Mutex, Semaphore 정리

 

[SW 용어] Mutex, Semaphore 정리

Mutex(뮤텍스)와 Semaphore(세마포어)1. 프로세스 간 메시지를 전송하거나, 공유메모리를 통해 공유된 자원에 여러 개의 프로세스가 동시에 접근할 때 필요한 임계 영역 문제가 발생할 수 있다.2. 이

kfdd6630.tistory.com

 


 

3. 공유자원 또는 전역변수를 사용하지 않는다.

1. 전체 로직적으로 문제가 되지않는다면 공유자원을 사용하지 않고 서비스를 구현하는 것이 최선의 방법이 될 수 있다.

2. FreeRTOS에서는 task의 갯수를 최소화하며 특정 HW 자원에 대한 접근을 task에게 독점/제한하게 한다.

3. 만약 독점/제한하지 못하는 상황이 발생한다면 위 1, 2의 방법중 한가지를 선택하여 해결하면 된다.

 

 


 

4. 스케줄링 중단

1. 문맥 교환을 막기 위해 스케줄링을 중단한다.

2. FreeRTOS에서 지원하지 않으며 오버헤드가 매우 큰 해결방법이라 지양한다.

 

 

반응형

댓글