※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)


Context Switching을 공부해보자. 우선 설명을 하기 전에 밑에서 사용할 예제는 임베디드 관련 유명 블로거이신 히언님의 블로그에서 따온 것임을 먼저 알려드리께요.

[Reference] http://recipes.egloos.com/


이 블로그의 다음 글을 읽고 제 글을 읽어주시길 바래요. 그래야 이해가 쉬울 거에요.

[Reference] http://recipes.egloos.com/4986854

앞서 말했듯이, Context Switching은 현재 동작하고 있는 프로세스의 CPU 레지스터 값을 메모리 스택에 저장하는 과정이다. 이렇게 저장된 값을 가지고 나중에 값을 불러내면 프로세스가 돌아가고 있던 예전의 그 시점부터 다시 실행시킬 수 있게 된다.



전체적인 과정은 위와 같다. 우선, PUSH를 통해 스택에 모든 레지스터 값들을 집어 넣는다. (레지스터값은 번호가 매겨져있다. R14부터 R0까지, 단 R13은 특별한 이유로 제외,의 값을 저장한다.) 그리고 스택 포인터를 새로운 값으로 업데이트 하여 나중에 그 스택 포인터 값으로 돌아가서 이전의 값들을 불러온다.


Context Switching의 과정을 자세하게 들여다보자. Context Switching을 하기 전의 스택 상태와 메모리 상태가 다음과 같다고 하자.



위에서 저장해야할 값들은 R0부터 R14까지이다. 단, R13은 제외. 이 값들을 메모리의 스택에 저장해야 한다. (위의 그림에서는 가장 오른쪽에 열에 나와있다.) 저장하기 전의 스택은 다음과 같은 값을 보인다.


빨간 화살표가 가리키고 있는 저 위치가 현재 스택 포인터가 가르키는 주소이다. 이 위치 이전 주소부터 낮은 주소 방향으로 스택을 저장하기 시작한다. (01141E88 → 01141E84 → 01141E80 → ...이 방향으로) 

R14는 0B49 ..... R0은 01E4

이와 같은 값을 가지고 있으니까, context를 저장하고 나면 다음과 같은 형태가 된다.


위와 같이 스택의 값이 바뀌고 스택 포인터가 가리키는 값도 바뀌게 되었다. (01141E80 → 01141E4C)

이때, 주의할 것은 R14값인 B49는 linked register(lr)이라고 하는데, 이 값은 새로운 프로세스가 동작할 때, 현재의 스택 포인터 값으로 업데이트된다. 즉, 위의 상황에서 R14 레지스터의 값은 01141E8C가 된다.

※ linked register : JUMP 명령어를 수행하기 이전의 값을 가지고 있는다. 즉, 후에 original address로 돌아오기 위한 레지스터이다.


그 다음에 CPU에서는 이상한 다른 프로세스들이 돌아가기 시작할 것이다. 그 프로세스도 CPU 점유권을 잃고 context saving을 한 후 다시 이전 프로세스의 context를 불러오게 될 것이다.(context restore)


어떻게 복구할까?

Idea는 간단하다. 우리는 linked register 값만 알면 복구할 수 있다. linked register가 가리키는 값에서 우리는 점프를 했으니까, 그 값만 알면 원래의 주소로 돌아갈 수 있다.

이 값은 R14에 저장되어있다고 위에서 설명했다. 그렇다면 이 값은 어떻게 알까? 그림으로 보면 더 쉬우려나?



위 과정은 전체적인 Context Switching 과정이다. 즉, 스택 포인터를 통해서 R0으로 접근하고 R0부터 차례대로 거슬러 올라가서 R14를 알아낸 후, 그 지점으로 점프한 후, R0 ~ R14를 CPU register에 저장한 후 이전의 프로세스를 다시 시작하면 된다.

(※ 여기서, 스택 포인터가 애초에 0x000055CD를 가리키고 있었던 이유는 무엇일까? 이전에 T2에 대한 context saving 과정에서 스택 포인터 값이 업데이트되었기 때문이다.)


아마 처음 본 사람들은 이해하기가 매우 어려울 거에요. 6개월 전에 이걸로 프리젠테이션을 했던 저도 다시 보니까 아리까리 하네요. 다음 포스팅에서는 더욱 쉽게 설명해보려고 노력해볼게요.

Posted by 빛나유
,