본문 바로가기
IT/임베디드 시스템

알토스의 기본단위 태스크(Task)를 알아보자

by 뽀짝뉴스 2020. 6. 3.

 

알토스로 작성되는 소프트웨어의 가장 기본적인 단위는 태스크입니다. 태스크를 작성하는 일은 매우 쉬운 편인데요, 대부분의 RTOS에서 태스크는 단순히 서브루틴에 불과합니다. 프로그램의 어떤 부분에서 각각의 태스크에 대해서 어떤 서브루틴이 시작점인지 뒤에서 다룰 태스크의 우선 순위 같은 변수와 태스크를 위한 스택이 메모리에 어디에 위치하고 있는지 등의 내용을 가지고 태스크를 시작하는 RTOS의 함수를 한 번 또는 여러번 호출할 수 있습니다. 대부분의 RTOS들은 현실적으로 원하는 만큼 태스크를 가질 수 있고요.

 

RTOS에서 각각의 태스크는 항상 몇 가지 상태 중의 하나입니다.

 

1) 실행 상태(러닝) : 마이크로프로세서가 이 태스크의 명령어를 수행하고 있다는 것을 의미합니다. 시스템이 여러 개의 프로세서들을 가지고 있지 않는 한, 하나의 마이크로 프로세서가 존재하기 때문에, 어떠한 특장히 주어진 순간에는 단 하나의 태스크가 실행될 것 입니다.

 

2) 준비 상태(레디) : 다른 태스크가 동작을 하고 있는 상태에서 이 태스크도 마이크로프로세서를 사용할 수 있는 상태라면 뭔가 실행시킬 것을 가지고 있는 단게라는 것을 뜻합니다. 어떤 태스크라고 할지라도 이 상태에서 머무를 수 있는 것이죠.

 

3) 대기 상태(블락) : 마이크로 프로세서를 사용할 수 있다고 해도, 바로 당장 실행시킬 수 없는 상태를 의미합니다. 어떤 외부의 이벤트를 기다리고 있는 상황이라고 한다면, 태스크는 이 상태로 변합니다. 네트워크로부터 들어오는 데이터를 처리하는 태스크라고 한다면 들어오는 데이터가 없을 때 아무 일도 하지 않겠죠? 사용하로부터 입력을 받아서 뭔가를 응답하는 태스크도 사용자가 버튼을 누르거나 특정 행동을 할 때까지는 아무 일도 하지 않습니다. 마찬가지로 어떤 태스크도 이 상태에 있을 수 있습니다.

 

대부분의 RTOS들은 많은 여타 태스크 상태들을 제공하는 것처럼 보입니다. 서스펜드, 팬드, 웨이트, 동면, 지연 등이 포함되겠죠. 이런 것들은 방금 언급한 대기와 준비 상태에 대한 세분화된 분류라고 이해하면 쉽습니다. 이런 모든 태스크 상태를 실행, 준비, 대기로 묶어서 사용할겁니다. 사용하려는 RTOS의 상태들과 세 가지 상태가 어떠한 연관을 가지고 있는 지를 알고시다면 제공받은 RTOS의 매뉴얼을 읽어보기 바랍니다. 그에 대한 이해는 실력이 쌓이면 더 쉽게 와닿겠죠.

 

 

[스케줄러]

 

스케줄러라고 불리는 RTOS의 기능은 태스크들의 상태를 관리하고 어떤 태스크가 실행 상태로 되어야 하는 지를 결정하는 일을 담당합니다. 유닉스나 윈도우의 스케줄러와는 다르게 대부분의 RTOS에서 스케줄러들은 어떤 태스크를 다음에 실행시켜야 하는지에 대해서 어멍 단순한 전략을 가지고 있습니다. 스케줄러는 태스크에 할당된 우선 순위를 보고나서 대기 상태가 아닌 태스크들을 살펴보고 가장 우선 순위가 높은 태스크를 싱핼시키고 다른 것들은 준비상태인채로 ㅜㅂ니다. 스케줄러는 태스크의 우선 순위를 가지고 장난을 치지 않거든요. 만약 낮은 우선 순위의 태스크가 준비 상태로 기다리는 동안에 가장 높은 우선 순위의 태스크가 장기간 프로세서를 사용하는 게산에 매달려 있다고 한다면 낮은 우선 순위의 태스크에게는 무척 서글픈 일이 따로 없겠죠. 그냥 무작정 기다려야하는 신세가 되니까요. 스케줄러는 프로그래머가 태스크의 순서를 책정할 때 어떤 일이 일어날지에 대해서 모두 알고 있다고 임의로 설정하겠습니다.

 

여기서는 대기상태로 들어간다는 의미로 대기한다는 말을 쓰고, 태스크가 실행상태로 들어가면 실행한다, 어떤 태스크를 실행으로 전환한다면 전환한다는 말을 사용할 것입니다. 결론만 말하자면 몇 가지로 애기할 수 있습니다.

 

- 단지 태스크가 스스로 판단해서 해야 할 일이 없을 때, 대기하게 될 것입니다. 시스템에 있는 다른 태스크들이나 스케줄러는 태스크가 무엇인가를 기다릴 필요가 있는지 없는지를 결정할 수 없어요. 이런 이유 때문에 태스크는 대기하기 전에 반드시 실행된 상태여야 합니다. 태스크는 더 이상 할 것이 남아 있는지를 알기 위해서 명령어를 수행해야 하기 때문입니다.

 

- 태스크가 대기하고 있는 동안에는 그 태스크는 마이크로프로세서를 사용할 수 없습니다. 따라서 인터럽트 루틴이나 시스템이 있는 다른 태스크가 그 태스크가 기다리는 무언가를 발생한다면 시그널을 줘야합니다. 만약 무작정 기다리라고 한다면 당연히 영원한 잠에 빠져들겠죠.

 

- 태스크들 사이의 준비와 실행 상태의 전환은 완전히 스케줄러의 몫입니다. 태스크들은 스스로 대기 상태로 들어갈 수 있는데 다른 태스크들이나 인터럽트 루틴은 다른 태스크를 대기 상태로부터 준비 상태로 만들수 있는 반면 스케줄러는 실행 상태를 제어합니다 물론 태스크가 대기 상태에서 준비 상태로 전환했다면 현재 실행 되고 있는 태스크보다 우선 순위를 가지고 이쓴 경우에 한해서 스케줄러는 즉시 이 태스크를 실행합니다. 이런 경우에는 태스크는 준비 상태를 전혀 거치지 않았다고 할 수 있겠지만서도 이는 단지 의미론상의 주장에 불과합니다. 실제로는 응용 프로그램의 어떤 부분에서 태스크가 대기 상태로부터 나오도록 무엇인가를 한 후에 스케줄러가 결정을 내리게됩니다.

 

이쯤에서 발생할 수 있는 질문에 대해서 답해보겠습니다.

 

스케줄러는 어떻게 태스크가 대기 상태인지 아닌지 알 수 있을까?

RTOS는 태스크들이 호출해서 스케줄러에게 어떤 이벤트가 일어나길 기다리고 있고, 이벤트가 일어나서 시그널을 보내려고 한다는 것을 알려주는 여러 종류의 함수를 제공합니다. 남은 부분과 함수에 대해서도 다뤄봐야겠네요

 

모든 태스크들이 대기 상태면 어떤 일이 발생할까?

만약에 모든 태스크들이 대기 상태로 지속될 경우에는 스케줄러가 어떤 일이 발생하기를 마냥 기다리면서 RTOS 안에 있는 짧은 루프를 계속해서 돌게 되겠죠. 영원히 아무것도 발생하지 않는다면 명백히 프로그래머가 잘못했다고 할 수 있습니다. 태스크를 대기 상태에서 빠져 나오게 하는 어떤 RTOS 함수를 부르는 인터럽트 루틴을 첨가해서 언젠가는 뭔가 발생하도록 해야하는 숙명이 생깁니다. 당연하게도 그렇게 하지 못하면 소프트웨어가 제대로 동작하지 않겠죠.

 

만약 우선 순위가 같은 두개의 태스크가 모두 준비 상태이면 어떻게 될까?

이에 대한 대답은 사용하는 RTOS가 어떤 맵을 사용하지는지에 달려있습니다. 우선 시스템이 같은 우선순위를 갖는 두 개의 태스크를 갖는 것을 허용하지 않게해서 간단하게 이 문제를 해결 가능합니다. 또 다른 방법은 이런 두 개의 태스크 간에 시분할을 이용해서 문제를 해결하는 방법이고, 둘 중의 하나의 태스크를 먼저 실행하고 이 태스크가 대기 상태가 되면, 다른 태스크를 실행하는 식으로 해결할 수 있습니다. 이 때 어떤 태스크를 먼저 실행할 것인지는 어떤 알토스를 사용할 것인가에 따라서 또 다릅니다. 여러가지의 태스크 중 먼저 발동해야할 것이 어떤 것인지에 대한 얘기도 해봐야겠네요.

 

하나의 태스크가 실행되고 있을 때, 우선 순위가 높은 다른 태스크가 대기 상태에서 빠져 나왔다고하면 현재 실행되고 있는 태스크는 바로 멈추고 대기 상태로 들어가는가?

선점형 (Preemptive) RTOS는 더 높은 우선 순위의 태스크가 대기 상태에서 해제되자마자 낮은 순위의 태스크를 정지시켜버립니다. RTOS가 선점형이라고 생각하고 얘기를 이어가겠습니다. 비선점형은 매우 다른 특성을 보인다는 것 알아두세요.

댓글