Motor_task는 Task구조와 Signal 에서 보았던 기본 적인 Task형태에요. Motor_task는 WORK이라는 signal을 받으면 Ready가 되고 Scheduler에 의해서 순번이 돌아오면 Context Switching되어 Motor를 켰다 껐다 하는 일을 하지요.
void Motor_task ()
{
Motor_task_init();
Motor_init();
/* 우선은 초기화는 무조건 하네 */
while (1)
{
wait (WORK); /* 여기서 WORK이라는 signal을 일단 무작정 기다린다 */
/* while(1)이니까 한번 깜빡이면 항상 여기서 signal을 기다린다 */
/* Signal을 받기만 하면, 일을 시작 할테야 */■
clear (WORK); /* WORK을 받았으니, 다음번에도 WORK을 받을 수 있도록 초기화 해 주자 */
Motor_on();
time_wait (100); /* wait 100uS */
Motor_off();
time_wait (100); /* wait 100uS */
send (LAMP, WORK); /* Lamp task야 Lamp를 깜빡여봐 */
}
}
너무 한산한 풍경이죠. Motor_task는 Motor를 켰다 껐다 하는 일을 100uS을 사이에 두고 일을 하는데, Motor_task에게 100uS말고 다른 시간을 인자로 주어서, 깜박거리게 하고 싶으면 어떻게 하면 좋을 까 궁리해 보아요. 일단은 Motor_task()가 인자로 뭔가 받기 위해서 Queue 자료 구조를 한번 이용해 보는 게 어떨까 생각하고 있습니다만. Queue는 FIFO 구조로서, 먼저 받은 녀석을 먼저 처리 하는 구조인 게죠. 자 그러면 이런걸 한번 생각해 보시죠. WORK이라는 Signal을 받은 경우에는 Queue에서 더 자세한 내용을 꺼내 보는 구조.
void Motor_task ()
{
int ret;
Motor_task_init();
Motor_init();
/* 우선은 초기화는 무조건 하네 */
while (1)
{
wait (WORK); /* 여기서 WORK이라는 signal을 일단 무작정 기다린다 */
/* while(1)이니까 한번 깜빡이면 항상 여기서 signal을 기다린다 */
/* Signal을 받기만 하면, 일을 시작 할테야 */■
clear (WORK); /* WORK을 받았으니, 다음번에도 WORK을 받을 수 있도록 초기화 해 주자 */
ret = queue_get(); /* Queue에서 뭔가를 꺼내 온다 */
Motor_on();
time_wait (ret); /* wait ret 만큼 */
Motor_off();
time_wait (ret); /* wait ret 만큼 */
send (LAMP, WORK); /* Lamp task야 Lamp를 깜빡여봐 */
}
}
어때요. 뭔지 모르겠지만, Queue에 뭔가 들어와 있으면 그걸 꺼내서 time_wait의 시간을 바꿀 수 있겠네요. 그렇다면 다른 Task에서는 Motor_task의 Queue에 이런 값만 제대로 넣어주면 되겠네요.
void Control_task ()
{
int random;
while (1)
{
wait (WORK); /* 여기서 WORK이라는 signal을 일단 무작정 기다리죠 */
/* while(1)이니까 한번 깜빡이면 항상 여기서 signal을 기다리죠 */
/* Signal을 받기만 하면, 일을 시작 할테야 */
clear (WORK); /* WORK을 받았으니 다음번에도 WORK을 받을 수 있도록 초기화 해주자 */
random = rand(); /* random한 숫자를 generation 해 주는 함수 */
queue_put (Motor_task, random); /* Motor_task가 가지고 있는 Queue에 random 숫자를 넣자 */
send (MOTOR, WORK); /* Motor task야 Motor를 돌려봐 */
}
}
자, 어때요. Control_task는 Motor_task에게 random한 숫자를 넘겨주는 구조로 되어 있지요. 이제부터 Motor_task가 제어하는 Motor의 징~ 소리는 Random하게 울릴 거에요. 물론 Control_task도 누군가가 일을 시켜야 하겠지요. 아마도 Timer_service를 이용하면, Control_task도 주기적으로 일을 시킬 수 있겠죠. 이런 Queue를 이용하게 되면 Control_task이외의 다른 Task 들도 Motor_task에게 Queue를 통해서 일을 시킬 수 있을 것이고, Motor_task는 Queue에 해야 할 일들을 받아 두었다가, 자기가 CPU사용권을 할당 받았을 때는 while loop를 돌면서 Queue가 모두 비어질 때 까지 일을 하면 wait 상태에서 다른 녀석들이 해달라고 요청한 걸 모두 처리 할 수 있겠죠. 으흐흐.
이런 Queue를 각각의 Task마다 가지고 있을 수 있게 Task구조를 만들어 준다면, Task끼리의 통신을 Queue를 통해서 가능하게 해 줄 수 있어요. 더 큰 예를 든다면 이런 것도 있을 수 있겠죠.
void Waiter_task ()
{
int ret;
waiter_task_init();
waiter_init();
/* 우선은 초기화는 무조건 하네 */
while (1)
{
wait (WORK); /* 여기서 WORK이라는 signal을 일단 무작정 기다린다 */
/* while(1)이니까 한번 깜빡이면 항상 여기서 signal을 기다린다 */
/* Signal을 받기만 하면, 일을 시작 할테야 */■
clear (WORK); /* WORK을 받았으니, 다음번에도 WORK을 받을 수 있도록 초기화 해 주자 */
ret = queue_get(); /* Queue에서 뭔가를 꺼내 온다 */
switch (ret)
{
case WORK:
work();
break;
case ORDER:
order();
break;
............
}
}
}
뭐 이런 식도 가능하겠죠. Queue를 이용하게 되면 무궁무진하게 Task에게 많은 일을 시킬 수 있는 방법이 생겨난 거에요. 이러니 Queue는 RTOS Kernel에서 중요한 대접을 받는 자료 구조가 되겠죠. Incentive라도 줘서 대우해 줘야 할 판이라니깐요.
요즘들어, 멋들어진 그림들을 넣지않아 조금 속상하지만, 금방 또 나오겠지요.
댓글