공부가 좀 익어간다고 생각을 했는데 아직도 기초에서 헤매는 것을 보면
항상 초심을 유지 하는 것이 얼마나 중요한 것인지 새삼 느낍니다.
프로세스의 가상 주소는 컴파일 타임에 할당 됩니다.
프로그램을 실행 하면 물리 메모리의 가용 공간에 올라 갑니다.
즉, 프로세스에 물리주소가 할당 됩니다.
이때 페이지 디렉토리와 페이지 테이블에 주소 변환 정보가 채워지게 될 것입니다.
이후 PC는 프로세스의 첫 명령어의 주소를 가상주소 영역에서 읽어오고 MMU와 변환 테이블을 거쳐
물리 메모리에서 가져오게 될것입니다.
MMU가 변환 테이블을 어떻게 사용하는지는 이해를 했는데
변환 테이블에 내용이 어떤 원리로 채워지는지 모르겠습니다.
커널이 페이지 디렉토리와 페이지 테이블을 생성하고 특정한 메커니즘에 의해 가상 주소와 물리주소의 매핑 정보를
테이블에 기록 할거라는 막연한 추측을 해볼뿐입니다.
답변 부탁드립니다.
비가 많이 오네요.
건강 조심하세요. ^^;
댓글 16
-
유경환
2011.07.12 14:04
-
유강희
2011.07.12 18:58
지나가다 허접하게나마 답변을 드리자면
1. 다른 아키텍쳐는 잘 모르겠습니다만.. arm 같은 경우에는 찾으시는 코드를
arch/arm/mm 디렉토리 안에서 찾으실 수 있습니다.
2. arch/arm/mm/proc-xxx 안의 xxx_switch_mm 을 보시면 TTBR을 설정 하는 코드를 보실수 있습니다.
-
이상철
2011.07.15 13:54
아 그리고 page table entry에는 물리주소가 들어가고, struct page의 주소가 들어가 있지는 않습니다. 그러므로 가상에서 물리주소로 변환 시 page구조체를 읽어 주소변환을 하지는 않습니다. page구조체가 필요할 경우 가상주소에서 물리주소로 변환 후 이 물리주소를 통해 pfn(page frame number)을 구하고, 해당 주소에 맞는 struct page 구조체를 찾습니다.
-
이상철
2011.07.15 13:42
생각하시는게 맞는거로 알고 있습니다.
리눅스 커널에서 struct page는 물리 메모리 한 페이지당 하나씩 있습니다.(x86 32bit에서는 high memory 공간이 때문에 아닌 경우가 있습니다.) 각각 구조체는 page frame number(pfn)순서대로 테이블로 관리 되고 있고, 이를 메모리 관리 시 이용합니다.
그리고 각각의 프로세스 마다 task_struct가 할당되는데 여기안에 mm_struct->pgd를 context switch 할때 마다 mmu에 로드 함으로써 mmu를 통해 하드웨어적으로 가상주소가 물리주소로 변환되어 사용합니다. 로드하는 과정이 x86에서는 cr3를 갱신하는 것이고, arm에서는 mmu관련 코프로세서 레지스터에 접근하여 갱신하는것으로 알고 있습니다.
-
myskan
2011.07.15 16:58
S/W가 커널 처럼 직접 매핑이 되어 있다면 일말의 가능성은 있겠지만
-> uClinux 같은 경우가 이렇게 운용이 됩니다. VA와 PA가 1:1로 매핑이 되지요.
즉 VA를 변화 시킬 필요가 없는 것입니다.
-
홍문화
2011.07.15 15:38
곰곰히 생각을 해보니 의문 자체가 바보스럽다는 결론을 내렸습니다.
MMU의 주소 변환 기능을 S/W가 할 수 있지 않나라는 의문이었는데
변환 기능을 하는 S/W의 주소가 먼저 변환되어야 하는 모순적인 상황이 되어버리네요.
만일 이 S/W가 커널 처럼 직접 매핑이 되어 있다면 일말의 가능성은 있겠지만 매우 성능이
떨어질거 같습니다. MMU의 고마움을 새롭게 깨달았습니다.
의문을 품되 질문을 하려면 제대로 고민을 해야 겠습니다.
괜히 상철님만 귀찮게 해드린것 같아 죄송하네요.
-
홍문화
2011.07.15 14:05
먼저 저의 무지를 일깨워 주시기위한 노력에 진심으로 감사드립니다. ^^;
MMU가 없는 간단한 프로세서를 예로 들어보겠습니다.
프로세스가 명령어를 실행 하기위해 최초 명령어 fetch 동작을 해야 할 것입니다.
이를 위해 명령어의 물리 주소를 내어놓아 메모리 버스, 메모리 컨트롤러를 거쳐 RAM에서
명령어를 가져올것입니다.
MMU가 있는 프로세서를 예로 들어보겠습니다.
명령어 fetch 동작을 하기위해 프로세스가 이번에는 가상주소를 내어놓을 것입니다.
이를 물리 주소로 변환 하기 위해서는 최초로 페이지 디렉토리의 베이스 주소에 접근을
해야 할것입니다. 페이지 디렉토리의 물리 베이스 주소는 struct mm_struct 내의 pgd 필드에
있을테니 메모리 버스와, 메모리 컨트롤러를 통해 RAM에 접근을 하게 될 것입니다. 이제 페이지
디렉토리의 물리 베이스 주소를 알았으니 페이지 테이블의 물리 베이스 주소에 접근을
해야 할 것입니다. 이 주소는 가상주소의 상위 10비트가 가리키는 페이지 디렉토리의 엔트리
내에서 가져오게 될테고 이와 같은 과정으로 페이지 테이블의 특정 엔트리에 접근을 하면
엔트리 내의 20비트를 통해 물리 페이지 프레임의 베이스 주소를 알 수 있을 것입니다.
이와 같은 과정이 MMU가 관여를 하지 않아도 프로세서가 메모리 버스와 메모리 컨트롤러 그리고
가상 주소로 페이지 테이블의 내용을 분석하는 제어 구조(S/W가 되었든 프로세서 내부의
제어 로직이 되었든)로 달성 할 수 있지 않을까 하는 생각 입니다.
물론 MMU와 TLB를 통해 고속으로 주소변환을 달성 할 수 있습니다.
하지만 MMU가 없어서 상용화 하기 힘들 정도로 주소 변환이 느리게 일어난다고 해도 이론적으로는
가능하지 않을까 하는 생각입니다.
중요한 것은 확신을 가지고 주장을 펼치는 것이 아니라 현재 제가 도달한 수준이 이정도 이므로
가르침을 주시면 감사히 깨달을수 있을거라는 생각에 글을 써보는 바입니다.
제 생각이 논의 거리도 되지 못한다 싶으면 좀 더 깊이 생각해보라는 한문장만 써주시면 됩니다.
시간이 걸리더라도 깨닫게 되는 날이 올테니까요. ^^;
-
myskan
2011.07.15 13:24
1. MMU는 기본적으로 메모리 보호 + 주소 변환 기능을 가지고 있습니다.
프로세스가 접근 권한이 없는 주소나 잘못된 주소에 접근을 하면 MMU가 data abort, prefetch abort
exception을 H/W적으로 프로세서에 보낼 것입니다.
-> 네 맞습니다.
2. 순수하게 주소변환 동작만은 S/W적으로(MMU 없이) 할 수도 있지 않나-> 어떻게요??? 생각하시는 것을 간단하게 하드웨어 동작을 설명해 주시면 감사드리겠습니다.
3. MMU의 TLB는 물리 메모리에 존재하는 Page table의 일부 영역을 저장하고 있는 작은 메모리입니다. 그래서 저희 스터디 그룹에서 캐시라고 비교하신 분이 있으셨습니다. (이렇게 말씀드림련 이해가 쉬우시려나요?)
그럼 캐시와 TLB의 차이점은... 캐시는 해당 주소의 데이터를 가지고 있는 것이고 TLB는 해당 주소의 PA를 가지고 있는 것입니다.
뭔가 굉장히 중요한 것...
1. Integer Core 에서 명령어 패치 및 load, store 명령어 실행에 의한 메모리에 접근은 모두 VA 입니다.
2. Page table은 물리 메모리에 존재합니다.
3. 즉 홍문화님 말씀데로라면 Integer Core는 명령어 패치 및 메모리 접근을 할때 마다 Page table에 접근해서 PA 값을 획득해야 합니다.
4. 어쩌죠? 명령어도 못 읽어 왔고, 메모리 접근 실행 명령어도 수행되지 않고 있는데 page table에 접근하는 명령어는 어떻게 읽어오고 어떻게 수행 해야 할까요???
-
홍문화
2011.07.15 13:03
상철님 답글 보고나서 살짝 헷갈리는 부분이 생겼습니다.ㅋ
MMU는 기본적으로 메모리 보호 + 주소 변환 기능을 가지고 있습니다.
프로세스가 접근 권한이 없는 주소나 잘못된 주소에 접근을 하면 MMU가 data abort, prefetch abort
exception을 H/W적으로 프로세서에 보낼 것입니다.
하지만 순수하게 주소변환 동작만은 S/W적으로(MMU 없이) 할 수도 있지 않나 하는 생각이 갑자기
들었습니다. 주소변환 과정을 살펴보면 32비트 가상 주소의 상위 10비트는 페이지 디렉토리의
엔트리 인덱스입니다. 그 다음 10비트는 페이지 테이블의 엔트리 인덱스 입니다. 마지막 12비트는
물리 페이지 프레임 내의 옵셋입니다. 페이지 디렉토리의 베이스 주소는 struct mm_struct 내부의
pgd 필드에 저장되어 있고 페이지 테이블의 베이스 주소는 페이지 디렉토리의 엔트리 내에 저장되어
있습니다. 이렇게 주소 변환이 이루어 질때 MMU라는 주소 변환 장치의 도움 없이도 물리 주소로 변환이
가능한게 아닐까 하는 생각이 듭니다.
뭔가 굉장히 중요한걸 하나 간과하고 있는것 같은데... 뭘까요?
-
myskan
2011.07.15 11:32
소프트웨어적으로 가상주소가 물리주소 변환이 가능하다는 말이 전 이해가 되지 않습니다.
예를 들면 프로세서에서 load, store 명령어 의하여 A 라는 가상주소에 접근하고 있는데
해당 명령어가 완료되지 않은 시점에서 어떻게 S/W적으로 페이지테이블과 struct page의 값을 load 해서
A 라는 가상 주소를 물리 주소로 변경 할 수 있는지 저는 모르겠습니다.
-
유경환
2011.07.14 09:44
답 감사합니다. 그래도 안풀리는 의문이 있어 다시 질문 드립니다.
ARM이나 x86기준으로 리눅스 코드를 보면 가상주소를 물리주소로 바꾸는 과정이
메모리에 올라와 있는 페이지테이블과 struct page를 이용해 물리주소를 바꿀수 있음을 알수 있었습니다.
그래서 하드웨어 MMU 로직의 사용처가 의문입니다.
소프트웨어적 가상주소에 물리주소 변환이 가능한 상황에서 하드웨어 MMU의 사용이 명시적으로
나와있는 부분을 찾기도 힘들고 해서 다시 추측을 해보는것이
혹시 컴파일러에서 컴파일타임에 가상주소 변환 과정을 하드웨어 MMU(TLB의 활용, 물리메모리 주소 계산 연산..)를 사용하도록 바꾸어주는것이 아닌가 해서요.
추측이 맞나요? 아니면 헛다리 짚은건가요? ^^;; 커널코드에서 해당 부분이 잘 안보이네요 ^^;;
(xxx_switch_mm을 쫓아 가면 결국 MOV pc, lr 이런 리턴주소 올리는 코드 하나 나오는데 머가 더있는지도 알고 싶고요.)
-
myskan
2011.07.12 20:14
MMU가 hardware page table work 를 지원하는지 해당 프로세서의 메뉴얼을 살펴 보세요.
-
홍문화
2011.07.12 15:18
와~ 유경환님 공부 많이 하셨네요. 코드를 분석 하셨나보네요. 멋쟁이 ^^;
그렇다면 프로그램이 메모리에 로드 될 때 프로그램은 물리 페이지 프레임 단위(4KB)로 나뉘어져
메모리의 빈 공간에 들어가게 될텐데 struct page가 프로그램의 물리 페이지 프레임마다 하나씩 할당이
되겠군요. struct page는 NUMA -> Node -> Zone -> Page 의 계층적 구조로 커널이 관리 하고 있을테니
프로그램의 text section, data section이 어느 물리 페이지 프레임에 위치하게 되었는지를 struct page로
알 수 있을것 같습니다. 물론 text section 인지 data section 인지는 ELF 포맷으로 부터 정보를 얻게 되지
않을까 생각합니다. 이제 남은 일은 가상 주소에 할당 된 페이지와 struct page의 정보를 매칭시켜
페이지 디렉토리와 테이블에 기록하게 되는 것이겠죠?
-
홍문화
2011.07.12 16:17
이제 좀 메모리 관리에 대한 전체적인 윤곽이 그려지네요.
실제 MMU 제어 관련 코드는 다음 파트에 나오는것 같습니다.
분량으로 보아서 이번주 스터디에 마무리 할 수 있을것 같네요.
감사합니다. ^^;
-
유경환
2011.07.12 16:00
네. 그런식으로 각 태스크별로 생성된 페이지 테이블(pgd)에 실제 물리메모리 정보를 담은 struct page들이 등록된다고 생각합니다 그래서 컴파일시 가상주소로 매핑된 프로그램들의 실행이 물리메모리에서 정상적으로 동작되는거겠죠. 해당 가상메모리 주소의 페이지테이블의 entry(PTE)에 물리 페이지 프레임 정보인 struct page가 달려있고, struct page가 가리키는 실제 물리메모리 주소에 text section, data section이 존재하여 프로그램을 실행시킬수 있게되는것이겠죠.
-
유경환
2011.07.18 14:14
이럴것이다고 하고 혼자 시나리오를 짜서 코드를 보니, 제가 생각대로 코드마저도 보였나봅니다.
상세한 설명 정말 감사드립니다.
.
흐흐 제가 올려야 했던 내용인데.. 문화님께서 고맙게도 올려주셨네요.
어제 커널소스의 페이지 테이블쪽을 보다가 좌절하고 오늘 다시봐야지 했습니다.
일단 우선 분석한 내용은.
1. 커널 부팅시 메모리의 절대 물리주소의 특정영역에 가상주소(4G) 매핑을 위한 페이지테이블(not page directory)을 생성하고, 실제 가용한 물리적 메모리(128M or 256M ....)를 페이지 단위로 관리하기 위한 struct page 구조체 리스트가 생성된다.
* struct page list의 생성과, page table의 생성은 독립적!!
2. page directory(pgd)는 리눅스에서 태스크별로 할당되는 페이지 테이블이라고 보면된다.
3. 페이지 테이블의 PTE를 이용해 가상주소가 가리키는 struct page의 물리주소를 찾아내 struct page의 정보를 가져올수도 있고, struct page의 정보(offset 값)을 이용하여 해당 page의 물리주소를 얻을수 있다 ( = 4K* struct page의 offset + 물리 base 주소).
* PTE는 실제적으로는 물리메모리의 entry가 아니라 struct page의 entry point 임.
4. 결론 : 페이지테이블은 실제 물리페이지를 관리하는 struct page를 매핑하는 매핑테이블 이다. 가상주소는 페이지테이블에서 매핑된 물리페이지를 나타내는 struct page를 찾기위한 Id 정도로 생각하면된다.
아직 의문사항 :
1. 실제 코드에서 MMU 하드웨어를 이용하기 위한 어셈명령은 발견못해서, 가상주소를 물리주소로 변환하기 위해 실제로 MMU 하드웨어 로직이 쓰이는지에 대한 확신이 없음. 아는분 코드좀 찾아주세요.
2. 물리 base 주소(phy_base) 를 설정해 주는 부분을 아직 못찾았음. 부팅과정에서 안보이는 것으로 보아 링커에서 설정하는것으 로 추측 중임.
아시는분 설명 부탁드립니다.