linux 에서 context swiching이 일어 날때 TTB 값을 해당 프로세스의 page table로 변경하는 것으로 아는데요.
그런데 어떻게 커널영역의 page table은 공유가 되는건지 궁금합니다.
아무래도 커널영역(3~4G)구간은 따로 업데이트가 안 될것 같은데요...
고수님들의 도움 부탁 드립니다.
댓글 20
-
홍문화
2011.08.14 21:12
-
송원식
2011.08.16 18:21
추가로 확인해보고 있는데요.
MMU즉 page table entry에 특정 셋팅을 하면 해당 부분이 TLB에 의해서 clear되지 않아서 커널영역이 공유되는것 같은데요 ㅜㅜ
아직 지식이 부족해서 ARM서 해당부분 셋팅하는것을 찾지 못했습니다...
제가 아무래도 질문을 잘못 올린것 같습니다ㅜㅜ
도움 주셔서 감사합니다.
-
송원식
2011.08.16 18:11
제가 가지고 있는 소스에는 아래의 경로에 있는데요...
linux/arch/arm/mm/pgd.c
-
홍문화
2011.08.16 18:03
pgd.c 파일이 정확히 경로가 어떻게 되나요.
저는 3.0 소스로 보고 있는데 arch/arm/mm/pgd.c 에는 get_pgd_slow() 함수가 없고
arch/unicore32/mm/pgd.c 에 get_pgd_slow() 함수가 있네요.
unicore32는 무슨 프로세서지?켘
-
송원식
2011.08.22 10:54
도움 주셔서 감사합니다
댓글에 폭이 왜 자꾸 줄어드는 건지ㅜㅜ
무슨 옵션이 있는건가요 ^^
앞으로도 많은 가르침 부탁 드립니다~~
-
홍문화
2011.08.17 21:36
vmalloc에 대해 쓰신 글을 다시 읽어 보니
이미 원하시는 바를 달성 하신것 같습니다. ㅋ
저도 많은 공부가 되었습니다. 감사합니다. ^^;
그런데 댓글은 달면 달수록 가로 폭이 점점 좁아지네요. 켘
-
홍문화
2011.08.17 18:04
저는 "리눅스 커널의 이해" 2판을 가지고 있는데요.
345쪽에 원하시는 내용이 나오네요.
7장 메모리 관리입니다.
그럼 열공 하세요. ^^;
-
송원식
2011.08.17 17:49
제가 아직 많이 부족한것 같습니다.
좀더 공부해서 문의 드리겠습니다.
도움 주셔서 감사합니다~~
-
홍문화
2011.08.17 17:33
하찮은 지식으로 계속 답글을 달자니 점점 민망해지네요. ㅋㅋㅋ
vmalloc에 관해서는 "리눅스 커널의 이해"에서 ZONE_HIGHMEM 영역의
사용에 대해 읽어보시길 추천 드립니다. x86 기준으로 설명이 되어 있지만
arm도 기본적인 원리는 동일 할거라 생각합니다.
제 기억으로는 페이지 테이블이 수정 되지 페이지 디렉토리가 수정 되지는
않았던 것으로 기억합니다.
-
송원식
2011.08.17 17:23
계속적인 도움 감사드립니다.
그런데 user 영역에서가 아니라 system call 또는 인터럽트를 통해서 커널 영역에 진입해서 변경이 가능할 것 같습니다.
예로 인터럽트 발생후에 커널영역에서 vmalloc같은 함수를 호출하면 커널의 페이지 디렉토리가 변경 될 것 같은데요. 그러면 프로세스 사이에 커널영역의 페이지 디렉토리가 달라지는것 아닌가요??
추가로 vmalloc으로 메모리를 생성시 직접 페이지 테이블을 변경하는 것이 아니라, 일단은 마스터 커널 페이지 테이블에만 업데이트해서 실제로 해당 영역 접근시 fault가 발생해서 vmlloc_fault handler에서 이전에 설정한 마스터 커널 페이지 테이블 엔트리를 보고서 페이지 테이블을 수정 하는것으로 알고 있습니다. 즉 위와 같은 과정이 맞다면 vmalloc함수 실행 이전의 프로세스와 실행 이후에 생성된 프로세스의 커널영역 페이지 디렉토리가 틀린것 같은데요.(프로세스 생성시 커널영역 페이지 디렉토리는 마스터커널 페이지를 그대로 복사하기 때문에 vmalloc호출 이전의 프로세스와는 달라 질것 같습니다)
제가 잘못 이해하고 있는 부분이 있는것 같은데요
가르침 부탁 드립니다.
-
홍문화
2011.08.17 16:52
아... 무슨 말씀이신지 이제야 제대로 이해를 했습니다. ㅋ
커널의 페이지 디렉토리의1024개 엔트리 값을 유저 프로세스가 생길때마다 복사를
했는데 유저 프로세스 중 하나가 자기가 복사한 1024개의 엔트리 값을 변경하면
다른 유저 프로세스들이랑 값이 틀려지지 않냐는 말씀 이시죠?
간단히 답변 드리면 유저 프로세스는 페이지 디렉토리든 페이지 테이블이든
접근 할 수 없습니다. 커널만이 접근 할 수 있습니다.
그러므로 말씀 하시는 일은 일어날수도 없고 일어나서도 안됩니다.
혹시나 커널이 1024개 엔트리 값을 복사 해주고 자기만 엔트리 값을 수정하면
동일한 일관성 문제가 생기지 않나 라는 생각을 하실지도 모르겠습니다.
하지만 절대로 문제가 생기지 않습니다.
커널은 자기 자신을 페이징 하지 않으며 직접 매핑을 하기 때문입니다.
이거까지 설명하자니 좀 힘드네요. 켘
내년 스터디 꼭 참석하세요.
경험상 혼자서 공부할때 10의 노력으로 6의 결과를 얻는다면
같이 공부할때는 5의 노력으로 7의 결과를 얻을 수 있는것 같습니다. ^^;
-
송원식
2011.08.17 12:11
답변 주셔서 감사합니다.
위에서 말씀하신 내용대로면 커널쪽 모든 영역이 L1 entry를 L2 table의 page 디렉토리로 사용한다는 말씀이신가요??
만약에 L1 자체를 페이지 테이블로 사용하면 위에 말씀하신 내용과는 좀 다른 것 같습니다.
즉 프로세스가 가지고있는 L1테이블이 바뀌면 다른쪽은 변하지 않을것 같습니다.
가르침 부탁 드립니다~
-
홍문화
2011.08.16 19:43
버전이 달라서 그런지 함수 이름이 바뀐거 같네요.
pgd_t는 32비트 unsigned long 형 입니다.
new_pgd는 16KB 유저 프로세스 페이지 디렉토리의 시작 주소를 가리킬테구요.
init_pgd는 16KB 커널의 페이지 디렉토리의 시작 주소가 될거 같습니다.
FIRST_KERNEL_PGD_NR은 아마도 3072가 될거 같네요.
PTRS_PER_PGD는 4096이 될테구요.
memcpy를 해석하면 유저프로세스 페이지 디렉토리 [시작 주소 + (3072 *4)]에
커널 페이지 디렉토리 [시작 주소 + (3072*4)]부터 (1024*4)만큼 복사를 하라는 뜻이
되겠네요. 즉, 커널이 자기자신을 위해 사용하는 1024개의 페이지 디렉토리 엔트리를
유저 프로세스의 페이지 디렉토리에 그대로 복사를 하고 있습니다.
페이지 디렉토리 엔트리에 들어 있는 값은 커널이 자기 자신을 위해 사용하는
페이지 테이블의 물리 주소 입니다.
헷갈려 하는 원인이 아마도 32비트 페이지 디렉토리 엔트리에 무슨 내용이 들어가는지를
모르셔서 그런것 같습니다. 아래 링크를 참고 하시면 이해하시기 쉬울 것입니다. ^^;
-
송원식
2011.08.16 17:11
답변 감사드립니다~
실제 아래 코드처럼 프로세서에 페이지 테이블을 할당 하는 코드를 보면 같은 주소를 공유하는 것이 아니라 메모리를 할당 받아서 해당 부분에 커널영역 페이지 테이블을 복사하는것 같습니다. (포인터만 공유한다면 구지 16KB 메모리를 할당 받을 필요도 없을것 같습니다.) 그렇다면 위에서 말씀하신 내용이랑은 다른 경우 인것 같은데요(페이지 디렉토리의 주소를 공유하는것 같지는 않습니다).
제가 잘못 이해하는 부분이 있는것 같은데요
가르침 부탁 드립니다.
Pgd.c
pgd_t *get_pgd_slow(struct mm_struct *mm)
{
//생략new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2); //메모리 할당
if (!new_pgd)
goto no_pgd;memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
init_pgd = pgd_offset_k(0);
memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
(PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t)); //테이블 복사
//생략return new_pgd;
} -
홍문화
2011.08.16 15:31
ARM에서 Level 1 page table을 페이지 디렉토리라고 보시면 됩니다. 아마 master 라는 단어가
하나 더 들어 갈겁니다. ㅋ
프로세스에서는 다른 프로세스의 메모리 공간을 건드릴 수 없습니다.
하물며 커널 메모리 공간은 더욱 건드릴 수 없겠지요.
segment fault 애러 많이 보셨을 겁니다.
그림을 그릴 수 있으면 좋을텐데 이 코드가 도움이 될지 모르겠네요.
int *a, *b, c =100;
a = b = &c;
c에 저장된 값이 수정 된다고 해서 a, b에 저장된 c의 주소가 변경 되지는 않겠죠.
마찬가지로 프로세스들의 페이지 디렉토리의 256개 엔트리는 같은 주소를 공유하니 같은
값을 가지게 되겠죠.
-
송원식
2011.08.16 15:11
홍문화님 답변 감사드립니다.
여기서 말씀하신 페이지 디렉토리라는 부분이 ARM에서 Level 1 page table이랑 비슷한것 같은데요.
그러면 페이지 디렉토리는 부팅후 MMIU 셋팅후 변경되지 않는 부분인가요??
만약 프로세스에서 커널쪽 페이지 디렉토리를 변경시키면 프로세스별 커널 페이지 테이블이 틀릴것 같은데요
도움 주셔서 감사합니다.
-
홍문화
2011.08.16 14:54
프로세스의 페이지 디렉토리는 커널의 페이지 테이블의 주소를 가지지 값을 가지지 않습니다.
커널의 페이지 테이블의 내용이 수정이 되된다고 하더라도 주소로 참조를 하므로 송원식 님께서
생각하시는 일관성 문제는 발생하지 않습니다.
-
송원식
2011.08.16 14:48
답변 감사드립니다.
그런데 위에서 말씀하신데로 10개의 프로세스들 각자 다른 페이지 테이블을 가지고 있을때(10개의 페이지 테이블이 존재할때), 한개의 프로세스에서 자신이 가지고 있는 커널쪽 페이지 테이블을 변경할 경우, 다른 9개의 프로세스의 페이지 테이블은 갱신되지 않을 것 같습니다. 커널쪽 페이지 테이블이 공유 되려면 한개의 프로세스에서 커널의 페이지 테이블을 변경할 경우 다른 프로세스도 모두 동일하게 변경되어야 할 것 같은데요.
제가 공유되는 부분에 대해서 이해가 부족한것 같습니다ㅜㅜ
도움 부탁드립니다.
참고로 프로세스 생성하는 곳을 보면 ARM에서 페이지 디렉토리 사이즈를 16KB로 하는것 같습니다
(아직 초보라 정확하지는 않은데요^^)
-
홍문화
2011.08.16 14:26
아... 페이지 디렉토리가 저장하는 정보라는게 결국 페이지 테이블의 물리 베이스 주소 입니다.
예를 들어 프로세스 10개가 생성 되었다고 할 경우에 4KB 페이지 디렉토리도 10개가 생기겠죠.
10개의 페이지 디렉토리는 모두 1GB 커널 영역을 표현하는 256개의 엔트리를 가지고 있습니다.
이 256개의 엔트리에 커널이 자기 자신의 주소를 변환하기 위해 사용하는 256개의 페이지 테이블의
물리 주소를 넣으면 되겠죠.
arm의 페이지 디렉토리 사이즈는 16KB 입니다.
arm에서 프로세스마다 16KB의 페이지 디렉토리를 사용하는지 궁금하네요.
너무 큰거 같은데...
-
송원식
2011.08.16 14:16
답변 주셔서 감사합니다.
추가로 질문이 있는데요^^ 말씀하신 커널쪽 256개의 페이지 테이블을 프로세스들 사이에서 공유한다고 하셨는데,
개인적으로는 프로세스가 생성될때 프로세스의 전역 페이지 디렉토리가 마스터 커널 페이지를 기준으로
복사되어서 생성될것 같은데요.그러면 커널 페이지가 공유되지 않을것 같은데요.
어떻게 프로세스들 사이에서 커널 페이지 테이블이 공유되는지 궁금합니다.
(도저히 어떻게 공유되는지를 모르겠습니다ㅜㅜ)
도움부탁 드립니다.
.
x86 커널을 기준으로 답변 드려봅니다.
커널은 자기 자신의 주소 변환을 위해 고유의 페이지 디렉토리와 페이지 테이블을 가지고 있습니다.
커널은 1GB 가상 주소를 사용하므로 페이지 디렉토리 엔트리 256개만을 사용합니다.
또한 이 256개의 엔트리가 가리키는 256개의 페이지 테이블(256 * 4KB = 1MB 물리 메모리)을 사용합니다.
프로세스가 생성 될때마다 3~4G 가상주소 공간은 커널이 자신의 주소 변환을 위해서 사용하는 256개의
페이지 테이블을 공유 한다고 보시면 됩니다.
참고 : http://www.iamroot.org/xe/index.php?mid=QnA&document_srl=47152
arm은 현재 코드 분석 중이라 시간이 조금 더 지나야 확실히 이해를 할 수 있을것 같습니다.