리눅스 page table entry 에 대해서

declspec의 이미지

안녕하세요

리눅스 커널모듈상에서 페이지 테이블을 덤프해보려고 합니다

페이지 디렉토리를 덤프하는것은

CR3 레지스터에 있는 물리주소값에 __va 매크로등으로 0xC0000000 를 더하여

페이지 디렉토리의 시작을 가리키는 가상주소를 얻고

이것을 통해서 1024 바이트를 덤프를 하여 얻을수 있었습니다.

또는 task 구조체속의 mm 구조체속의 pgd 를 통해서도 얻을수 있고요,

그런데 PGD 의 내용을 보고 그 안에있는 특정 엔트리를 통해서

페이지 테이블의 내용을 덤프뜨고싶은데, 방법을 잘 모르겠습니다.

단순하게 PGD 에 있는 어떤 엔트리에 있는 페이지테이블의 물리주소에

똑같이 __va 매크로로 0xC0000000 를 더해서 가상주소를 얻고

이것에서 1024바이트를 덤프했는데 이렇게 하는게 맞는건지 모르겠네요

덤프뜬 결과 막

[ 1334.577126] [index 0C74][0xCFB04C74]
[ 1334.577128] [index 0C78][0xCFB04C74]
[ 1334.577131] [index 0C7C][0xDCCF8618]
[ 1334.577133] [index 0C80][0xCFB04980]
[ 1334.577135] [index 0CB0][0xFFFFFFFF]
[ 1334.577137] [index 0CB4][0xFFFFFFFF]
[ 1334.577140] [index 0CB8][0xFFFFFFFF]
[ 1334.577142] [index 0CBC][0xFFFFFFFF]
[ 1334.577144] [index 0CC0][0xFFFFFFFF]
[ 1334.577146] [index 0CC4][0xFFFFFFFF]
[ 1334.577149] [index 0CD4][0xCF841340]
[ 1334.577151] [index 0CDC][0xC076E5A0]
[ 1334.577153] [index 0CE0][0xD41EB180]
[ 1334.577156] [index 0CE4][0xCFB04C64]
[ 1334.577158] [index 0CE8][0xC016E8C0]
[ 1334.577160] [index 0D00][0xCFB04200]
[ 1334.577162] [index 0D04][0xC020B210]

이런 결과가 나오는데... (index 부분은 페이지 테이블상의 offset 입니다, 정확한 숫자는 아닙니다)

FFFFFFFF 이런게 나오는걸 보면, 저게 페이지테이블의 내용이 아닌거겠죠??

커널 메모리영역은

0xC0000000 ~ highmem 까지 선형 매핑되는 부분과

그렇지 않은 부분으로 나뉘는것으로 알고있습니다.

__pa, __va 같은 매크로는 이 선형매핑되는 부분에서만 유효한것으로 압니다

페이지 테이블들은 모두 이 선형매핑되는 부분에 들어가는건가요?

MMU 가 페이지 테이블을 참조해서 주소변환을 하는것은 이해가 가는데

OS 가 페이지 테이블의 내용들을 무슨기준으로 어떻게 채워넣는지 잘 모르겠습니다

특히, 페이지테이블의 내용을 OS 가 채우려면, 해당 페이지테이블에 Access 할수있는

가상주소가 있어야할텐데, 페이지 디렉토리에 있는 물리주소에 무조건 0xC0000000 만 더하면 되는걸까요?

어렵군요 ㅠㅠ

chadr의 이미지

제가 알기로는 CR3 레지스터에 있는 물리 주소에 va등 매크로를 이용해서 주소변환을 안해야하는걸로 알고 있습니다.
그냥 그 레지스터가 가르키는 물리주소를 덤프 해야하는 걸로 알고 있습니다.

왜냐하면 MMU가 변환테이블을 이용해서 가상주소를 변환하는데 테이블이 가르키는 값이 또 가상주소라면 무한루프에 빠지니까요.

MMU는 운영체제가 리눅스인지 윈도우인지 모르며 해당 운영체제가 메모리의 어느 위치부터 적재되어있는지 모릅니다.
따라서 리눅스에서 사용하는 0xC0000000 라는 커널이 시작되는 가상주소 또한 모든 운영체제에서 고정된 값이 아니므로 MMU가 이를 이용해서 CR3레지스터에 저장된 물리 메모리를 선형공간 가상주소로 변환하지 못합니다.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

gurugio의 이미지

그냥 0xc000 0000 더하고 빼는 것만 생각하시면 됩니다.
너무 복잡하게 생각하시는것 같습니다.
0xc~~로 시작하는 주소는 다 선형주소구요.

제가 만약 제 커널을 0x100000 지점에 로드했다면
페이징을 켜고 난 다음에는 0xc010 0000 을 읽으면 제 커널의 시작 지점이 읽어지는 거구요.
제가 데이터를 0x200000 에 저장했으면요
페이지 테이블에 0x200000 에 해당하는 엔트리와 0xc020 0000 에 해당하는 엔트리에 0x200000 을 써주는 거지요.

만약 이정도로 이해가 안되시면 좀더 자세하게 설명하는 책들을 다시한번 보시는게 좋을것 같습니다.
얼마전에 64비트 운영체제 만들기에 대한 책이 출판된걸로 아는데 그 책 보시면서
한번 따라서 만들어보세요. 도움이 많이 됩니다.

declspec의 이미지

답변감사합니다~

그런데 궁금한것이

어느 영역까지가 0xc0000000 를 더하고빼기만 하면 되는 선형주소 영역이고

어느 영역부터가 페이징을 거쳐야하는 영역인지 그 구분을 어떻게 하나요?

커널영역의 메모리주소 0xC0000000 ~ 0xFFFFFFFF 까지의 모든 영역이

물리메모리에 선형매핑되는건 아니지안나요?

자기실력이 좋다고 느껴지는건 공부를 안하고 있다는 신호.

gurugio의 이미지


리눅스 커널은 부팅할때 물리 메모리 전체를 선형매핑하는걸로 알고있습니다.
그림을 그리면 설명이 쉬운데 글로 쓰려니까 몇번을 썼다지우네요.

예를 들어 물리 메모리 0xF0 0000 지점이 빈 영역일때를 보면요
커널은 이 지점을 0xc0f0 0000 으로 접근하구요
선형 메모리 0xa010 0000 에 해당하는 페이지 테이블에다가 0xF0 0000 지점을 가르키도록 설정하구요
그런다음에 유저 프로세스에게 할당해줍니다.
그럼 유저 프로세스는 물리 주소가 어딘지 전혀 모르는 상태에서 자신의 메모리 영역 0xa010 0000 ~ 0xaFFF 0000 을 사용하는거지요.

커널은 어떤 주소든지 물리 메모리로 어디인지 알 수 있구요
알아야만 페이지 테이블을 만들겠지요.
또 그러다보면 모든 물리 메모리는 페이지 테이블에서 2번 이상 나타나겠구요.

제 글쓰기 능력이 짧아서 도움이 되실지 모르겠습니다.. ;-)

declspec의 이미지

많은 도움이 되는것 같습니다~

계속 테스트하고 알아본결과 일단 페이지 테이블들은 물리메모리에 선형으로 매핑되는것을 알았습니다
따라서 페이지테이블의 PFN 을 얻은경우 여기에 단지 0xC0000000 만 더하면 다시 페이지테이블을 따라갈수 있는
가상주소가 되는것이죠.

그런데 제가 실험을 해본 결과 우분투 10.04에서
특정 프로세스의 페이지테이블을 덤프를 뜬다음에
해당 페이지테이블의 엔트리에 있는 PFN 에 대해서ㅏ갸ㅔ새ㅜ

0xc0000000 + PFN

이렇게 계산한 주소를 커널모듈상에서 다시 덤프를 뜨니까
실제로 해당 프로세스가 가지고있는 메모리 내용이 덤프가 되더군요...

그런데 페이지테이블은 메모리상의 커널영역에 선형매핑 될 것이므로
페이지테이블의 시작주소를 가리키는 PFN 에 0xC0000000 만 더하면
MMU 로 따라갈수있는 가상주소가 된다는게 이해가 되는데요

페이지테이블의 특정 엔트리에 있는 PFN 에 대해서도 이렇게 된다는게 이해가 안가네요...?

예를들어 process A 의 페이지테이블의 특정 엔트리에 0x1230000 이라는 PFN 이 있다고 가정합니다.
이때 커널상에서 0xC1230000 이라는 가상주소를 참조해서 4096바이트의 process A 의 데이터를 가지고 오는게 원래 말이되나요?

한마디로 MMU의 입장에서는 PFN 1000번 이라는 정보만 있으면, 물리주소 1000번지의 데이터를 가져올수 있는데
리눅스 커널에서는 PFN 을 알았을때 무조건 여기에 0xC0000000 만 더하게 되면 실제 물리주소 1000번지의 데이터를 언제나 가져올수 있는건가요??

만약 그렇다고 한다면 커널이 0xC0000000 를 더해서 PFN 을 가상주소로 바꾸는 과정때문에, 메모리 addressing 이 1GB 로 제한될텐데
어떻게된건지 모르겠네요.. ㅠ.ㅠ

자기실력이 좋다고 느껴지는건 공부를 안하고 있다는 신호.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.