임베디드 레시피

Egloos | Log-in





Context Swtiching과 TCB - Task의 상태변화

Kernel Level의 Context Switching, 문맥교환 이라는 거 실제로 어떤 모냥인지 알아야 하겠지요. 익히 Context라는 걸 몇 번 보아왔던 바, 현재의 Context라는 것만 잘 보전해 주면 다른 곳에 갔다 와서도 지금 하던 일을 계속 진행할 수 있다는 점을 잊지 않았겠죠. ARM에서의 Context는 현재의 Register set이니까, 이 녀석만 잘 저장해 두면 어디든지 갔다 올 수 있음이에요.
 
 
그러면, 이걸 어떻게 저장을 해 두면 좋을까요. 해당 Task에 Stack에 저장해 두면 좋겠네요. Context Switching이 이루어 질 때, 현재의 Context를 저장해 두는 방법에 대해서 고민해 BoA요. 이제 중요한 건 Kernel이 어떻게 Task를 관리하는 지를 알아 두면 편합니다. System상에 살아 있는 모든 Task는 자기 자신만의 Stack과 TCB (Task Control Block)을 가지고요, Task Stack은 우리가 알고 있는 바로 그 Stack이고요, TCB는 각 Task를 Control하기 위해서 Task의 정보를 저장해 놓는 Data Structure라고 보시면 큰 무리 없지요. TCB에 들어갈 수 있는 정보들은 만드는 사람 마음이겠지만, 대부분 Scheduling과 Context Switching을 위한 정보들이 들어가고요, 대표적인 예로는 Task name, Task Stack Pointer, 기다리는 wait Signal, priority등이 있어요. 그러면 각 TCB와 CPU, 그리고 Stack의 관계를 한번 볼까요.
 
 
 
제가 엄청 감명 깊어하는 그림인데, 출처는 솔직하게 -,.- 모르겠습니다. 여하튼 더 좋은 그림을 선사해 주고 싶지만 이걸 능가하는 그림을 그린다는 게 도저히 무리 인지라, 감명 깊어하는 그림에 조금 더 손을 대서 실제와 가깝게 만들긴 했습니다요. 여하튼, 각각의 TCB는 각 Task의 Priority와 SP (Stack Pointer)를 가리키고 있지요. 현재 Wait을 하거나, Ready상태인 Task의 TCB의 Stack은 방금 전까지 실행하던 Context를 마지막에 Stack에 넣고 그 Stack의 끝을 가리키고 있지요. (여기서의 Stack은 Full Descending Stack이에요) 그러니까 각각의 Task는 자기가 어디까지 실행되었었는지를 항상 간직하고 있는 셈이지요. 역시나 Stack 입장에서도 아까까지 쓰고 있던 SP를 그대로 복구한 셈이 되지요. 만일 Task2가 Ready가 되어서 다시 실행될 순서가 되면 SP가 가리키고 있던 Context를 그대로 다시 CPU의 Register에 복사해 넣는 일로 Context Switching을 완성하게 되는 것이죠.
 
 
그러고 나면 SP는 Context를 복구하면서 pop 한 만큼 변화되어 그 자리부터 다시 해당 Task의 Stack으로 사용하는 거죠. 그러면 실행되던 Task가 Stop되고 다른 Task로 실행이 바뀔 때는 당연히 반대로 해당 Task의 Stack에 Context를 저장(Push)하고 SP를 Push한 만큼 update하고 나서 CPU사용권에서 벗어나면 되겠죠. 완전 초간단 이에요.
 
그러면, TCB의 Status라는 건 어떤 걸까요? Scheduler에게 현재 Task의 상태를 알려주는 flag 비스므리한 건데, Ready 상태인지 아닌지를 알려주는 뭐 그런 거에요. 그러면, 이전에 말했던 Ready 상태와 Wait 상태의 구분은 어떻게 되는지 기억나시나 모르겠습니당. Wait상태는 Task가 wait_signal()을 이용해서 자발적으로 wait 상태에 들어간 거고, Ready 상태는 Wait 상태의 Task에게 어떤 다른 Task가 Signal을 날려서 일을 시킨 상태라고 보시면 되겠지요.
 
그러면 구현 자체는 Status에 두 가지 구분을 두면 그 상태를 구분할 수 있겠어요. 구분하기 힘드니까, Task_A()와 Task_B() 두 개로 구분해서 생각을 Organize해 볼께요. Task_A()의 Status는 wait_signal과, receive_signal이라는 두 가지 Flag를 두어서 구분할 수 있겠는데요, wait_signal에는 Task_A()가 wait_signal()을 통해서 해당 Task가 기다리는 Signal을 넣어두고요, receive_signal에는 Task_B()가 Task_A()에게 일을 시키고 싶을 때 send_signal()을 할 텐데, send_signal()이 된 signal을 Task_A()의 receive_signal에 넣어 두는 거죠.
 
이렇게 했을 때, send_signal()을 이용해서 Task_A()가 signal을 받은 순간에, receive_signal과 wait_signal을 비교해서 두 개의 값이 같으면, wait_signal을 0으로 clear하는거에요. wait_signal이 0인 경우라면 Scheduler가 보기에는 Signal을 누군가로 부터 받았고, 그럼 일을 해야 하니까 Ready 상태라고 판단하게 하는 거에요. 그리고, receive_siganal은 어떻게 처리하느냐, Task_A()가 Running Task가 된 후에, receive_signal을 확인해서 해야 할 일을 판단하고, receive_signal을 지우는 거죠. 어떤 Task가 0x3 signal을 기다린다고 가정하면, 
 
 
 
그러니까, Wait 상태의 Task는 wait_signal이 뭔가 있음, receive_signal은 0. Ready 상태의 Task는 wait_signal은 0, receive_signal에는 뭔가 있음. Running 상태의 Task는 wait_signal도 0, receive_signal도 0 인 게죠. 중요한 건 wait_signal이 0인 것들은 다음 scheduling의 대상이 되는데, ready, running이 모두 그렇죠. 이 상태를 근거로 Scheduler가 Task Context Switching/ Scheduling을 할 거니까, 잘 알아두세요.
 
한가지. Wait이거나, Ready인 상태의 Task의 SP는 TCB에 저장되어 있는 값이겠네요, 하지만 현재 Running중이던 Task의 SP는 TCB에 저장되어 있는 SP냐! 하면 딱 그것만 다른 Story겠네요. SP에서 Context를 빼내오고 그걸 CPU Register에 넣으면서 SP를 update한 셈이니까, 현재 Running중인 Task의 SP는 CPU Register의 R13 (SP)가 되겠사옵니다. 냐하.
 

by 히언 | 2009/08/13 20:40 | RTOS팩토리(커널) | 트랙백 | 핑백(2)

Linked at 친절한 임베디드 시스템 개발자.. at 2009/10/01 12:45

... ⓕ Context Swtiching과 TCB - Task 상태변화 ... more

Linked at TERMS OF PROGRAM.. at 2017/06/04 12:51

... 2.naver.com/helloworld/47667 *PCB(process control block) : http://blog.eairship.kr/257 http://recipes.egloos.com/5079866 *mutual exclusion, Mutex https://ko.wikipedia.org/wiki/%EC%83%81%ED%98%B8_%EB%B0%B ... more

◀ 이전 페이지          다음 페이지 ▶