커널 공부를 하는데... 소스에서 이해가 안가는 부분이 있어서 올립니다.
무턱대고 물어봐서 죄송합니다. ㅎㅎㅎ
------------------------------------------------------------------------------------------------
pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte;
pgd = pgd_offset_k((unsigned long)주소);
pud = pud_offset(pgd, (unsigned long)주소);
pmd = pmd_offset(pud, (unsigned long)주소);
if(pmd_large(*pmd))
pte = (pte_t *)pmd;
else
pte = pte_offset_kernel(pmd, (unsigned long)주소);
------------------------------------------------------------------------------------------------
그 주소에 해당하는 페이지 테이블까지 찾아가는 소스인데 오픈 소스입니다.
리눅스는 원래 3단계(pgd, pmd, pte)를 하는데 pmd가 pgd에 포함 되어 있다고 하더라구요.
64비트와 호환을 두기 위해서 라고 하던데
커널 2.6.x버전부터 바껴서 4단계로 넘어왔다고 합니다.
재미있는건 32비트이면 다 if가 참일줄 알았는데 유독 페도라7만 else가 참이더라구요
페도라8은 또 if가 참이고
이부분에 대해서 알고 계시면 설명좀 부탁드립니다. ^^
그리구 페이지 테이블 속성중에 8번째 비트에 대해서 아시는거 있으면 이것도 설명 부탁드립니다.
즐거운 하루되세요~
무턱대고 물어봐서 죄송합니다. ㅎㅎㅎ
------------------------------------------------------------------------------------------------
pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t *pte;
pgd = pgd_offset_k((unsigned long)주소);
pud = pud_offset(pgd, (unsigned long)주소);
pmd = pmd_offset(pud, (unsigned long)주소);
if(pmd_large(*pmd))
pte = (pte_t *)pmd;
else
pte = pte_offset_kernel(pmd, (unsigned long)주소);
------------------------------------------------------------------------------------------------
그 주소에 해당하는 페이지 테이블까지 찾아가는 소스인데 오픈 소스입니다.
리눅스는 원래 3단계(pgd, pmd, pte)를 하는데 pmd가 pgd에 포함 되어 있다고 하더라구요.
64비트와 호환을 두기 위해서 라고 하던데
커널 2.6.x버전부터 바껴서 4단계로 넘어왔다고 합니다.
재미있는건 32비트이면 다 if가 참일줄 알았는데 유독 페도라7만 else가 참이더라구요
페도라8은 또 if가 참이고
이부분에 대해서 알고 계시면 설명좀 부탁드립니다. ^^
그리구 페이지 테이블 속성중에 8번째 비트에 대해서 아시는거 있으면 이것도 설명 부탁드립니다.
즐거운 하루되세요~
댓글 3
.
x86 아키텍처에서는 주로 2단계 페이징을 하기 때문에 pud와 pmd를 사용하지 않습니다.( PAE 사용 여부와 페이지 크기에 따라 페이징 단계가 달라집니다.)
분석하시는 아키텍처가 x86이라고 가정하겠습니다.
커널 버전 2.6.23.8의 pmd_large() 코드 입니다. 2.6.24부터는 page_large() 함수가 삭제 되었더군요.
< include/asm-i386/pgtable.h >
389 #define pmd_large(pmd)
390 ((pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT))
pmd의 필드중에 P bit와 Page Size를 나타내는 필드를 확인 하는군요. P bit는 현재 페이지 테이블이 물리 메모리 상에 존재하는지 나타내는 필드이고, _PAGE_PSE의 값은 페이지의 크기가 4Kb인지 혹은 4Mb(or 2Mb) 나타내는 bit 입니다. 1로 set 되어있으면, 페이지 크기가 4Mb(2Mb) 입니다. 말그대로 페이지가 큰지 작은지 확인하는 루틴이군요.
AMD64 Architecture Programmer's Manual 볼륨 2의 챕터 5장을 보시면 해당 내용을 자세히 나와있네요. 물론 Intel Architecture Software Developer's Manual을 보셔도 같은 내용이 있습니다.
해당 문서를 보시면 아시겠지만 페이지 크기(4kb, 4Mb)에 따라 페이징 단계가 다릅니다. 그리고 PAE 사용 여부에 따라 페이징 단계가 다르구요.
결국 저런 작업을 하는 이유가 페이지 크기가 크면 페이지 테이블을 하나 줄이는 작업을 하기 위해서 하는것 입니다.
페도라 버전에 따라 왜 다른지는 해당 배포판의 커널코드를 보지 않아서 모르겠네요. 제 생각에는 배포판에 따라 달라지기 보다는 커널 컴파일시에 옵션에 따라 달라질것 같네요.