728x90
반응형
구현에 앞서 세마포어에 대해서 간단히 알아보겠습니다.
세마포어라는 말은 많이 들어봤지만 확실하게 이해를 하고 있는 사람이 적은거 같아 간단하게 설명합니다.
일정한 작업영역에 있어서 이 작업영역에서 일할수 있는 태스크의 수가 제한되어있는 지역입니다.
예를 들자면 역시 화장실이 가장 적합할꺼같군요
화장실이 1개 있고 안에 소변기가 5개가 있다고 가정합니다.
그럼 이 화장실에는 최대 5명의 사람이 볼일(?)을 볼수가 있습니다.
하지만 6명이되면 어떻게 될까요?
화장실에 먼저 도착한 순서대로 5명이 볼일을보고 있습니다.
이때 6번째 화장실에 도착한 사람의 행동은 어떨까요?
만약에 이미 볼일을 보고 있는 소변기에 같이 볼일을 본다면..
이 6번째 사람은 세마포어에 대한 개념이 없는 사람일 겁니다.
하지만 5명중에 한명이 볼일을 끝내고 나가기를 기다리고 있다면
이 6번째 사람은 세마포어에 대해 잘 이해하고 있는 사람입니다.
여기서 화장실은 작업영역이 될 것이고, 소변기는 동시접근가능한 태스크의 수가 되겠습니다.
RTOS에서 예를 들어보겠습니다.
TASK1, TASK2 이렇게 2개의 태스크가 있습니다.
우선순위는 TASK1 > TASK2 이고 두개의 태스크 모두 동일한 세마포어 영역에 접근한다고 가정합니다.
그리고 이 세마포어 구간에는 단 1개의 태스크만 작업을 해야하는 구간이라고 가정한다면
그림으로 그려보면 아래와 같이 되겠습니다.
먼저 TASK1이 세마포어 구간에 접근하고 있는도중 Tick인터럽트에 의한
스캐쥴러가 호출되었다고 생각해보면
TASK2가 실행준비상태에 놓여있지만 TASK1의 우선순위가 현재 가장 높기 때문에
아무련 영향을 주지못하고 TASK1은 세마포어구간을 무사히(?) 빠져나가게 됩니다.
문제는 TASK2가 세마포어 구간에 접근하고 있는 도중 Tick 인터럽트에 의한
스캐쥴러가 호출되었을때 입니다.
TASK1이 실행준비상태가 되어있고 TASK1의 우선순위가 TASK2보다 높기 때문에
스캐쥴러가 이를 인지하여 태스크전환이 일어나게 됩니다.
TASK2는 세마포어 구간을 벗어나지도 못했는데 TASK1또한 세마포어구간에
들어오게 됩니다.
이 결과 잘못된연산을 수행하게될 가능성은 매우 높아지며,
세마포어 구간에 대한 데이터의 신뢰성 또한 떨어지게 됩니다.
단순한 세마포어의 구현방법은 단순한 카운트 변수 1개로 해결이 됩니다.
1. 세마포어를 만들고(변수선언), 초기값을 입력합니다. 여기서 초기값이 최대 접근가능한 태스크의 수가 되겠습니다.
2. 세마포어 구간에 들어가기전에 세마포어 카운트 변수 값을 확인합니다.
3. 카운트 변수값이 0보다 크면 1을 감소시키고 그대로 진행합니다
카운트 변수값이 0과 같거나 작으면 카운트 변수값이 0보다 커질때까지 기다립니다.
4. 세마포어 구간이 끝나게 되면 세마포어 카운트 변수 값을 1 증가 시킵니다.
실제 구현은 이렇습니다.
1. 세마포어 만들기(Create_Sem)
사용하지 않는 인터태스크 컨트롤 블록(ICB)을 하나 할당하여 초기 카운트값을 설정하고 ICB핸들을 반환합니다.
2. 세마포어 얻기(Pend_Sem)
ICB 핸들에 대한 몇가지 안전검사를 한뒤 ICB내의 세마포어 카운트 변수값을 확인합니다.
세마포어 카운트 변수값이 0보다 크면 1을 감소시키고 그대로 진행합니다.
세마포어 카운트 변수값이 0과 같거나 작으면
현재 태스크의 상태를 세마포어 대기 상태로 바꾸고
ICB내의 대기 리스트에 현재 태스크를 추가하고 시스탬자원을 실행준비중인 태스크에게 넘겨줍니다.
3. 세마포어 반환(Post_Sem)
ICB 핸들에 대한 몇가지 안전검사를 한뒤 ICB내의 대기 리스트를 확인합니다.
대기리스트에 대기중인 태스크가 없으면 세마포어 카운트 변수값을 1증가 시키고 빠져나옵니다.
대기리스트에 대기중인 태스크가 있으면 대기리스트에서 가장 오래 기다린 태스크를 얻은뒤
태스크의 상태를 실행준비상태로 바꾸고 스캐쥴러에 의해 실행될 수 있도록 만듭니다.
태스트 내용
TASK1, 2는 작업중에 동일한 함수를 호출하게 됩니다.
이 함수는 단순히 인자로 받은 문자1개를 5번 연달아 출력하고 마지막에 공백문자를 출력하는 함수 입니다.
1. 세마포어가 없을 시
TASK1은 아무런 방해없이 문자 a를 5번 출력하는것을 볼수 있으나 TASK2는 문자 b를 찍는 도중에
TASK1의 방해를 받아 5개를 연달아 찍을수가 없는 현상이 일어나는것을 볼 수 있습니다.
2. 세마포어 적용 시
세마포어가 없을 때는 TASK2가 세마포어 구간의 작업을 진행하는도중 TASK1의 방해를 받았지만
세마포어 적용시 TASK1이 수행하는 도중 세마포어 구간에 진입하게 될때 이미 TASK2가 사용중에 있어서
TASK2의 세마포어 구간의 작업이 모두 끝나기를 대기하다가 끝나고나서 수행되는걸 볼 수 있습니다.
728x90