가상 메모리에 관해 질문 있습니다!

kyj_kr의 이미지

안녕하세요. 가상메모리와 TLB, 페이지테이블에 관해 의문점이 생겨 질문 드립니다.

1. 32비트 기준으로 각 프로세스가 4GB의 독립적인 공간을 갖는 기법을 가상메모리 기법이라고 알고있습니다. 그에 따라 가상메모리에 올라온 프로그램을 수행하기 위해선 실제 메모리에 실행코드가 올라와야되는데, SWAP 파일에 있는 프로그램 코드들을 SWAP SPACE MANAGER라는 하드웨어를 통해 실제메모리에 올려줌과 동시에 페이지테이블 또한 작성해준다고 알고있는데 맞나요?

2. CPU가 가상메모리로 실제물리메모리에 접근하기 위해선, TLB와 페이지테이블을 이용하여 주소 변환을 해야하죠. 이 역할을 MMU라는 하드웨어가 수행하기 때문에 CPU에선 가상주소가 실제주소라고 생각하며 명령어를 실행한다고 알고있습니다. 여기서 궁금한점은 예를들어, CPU가 현재 수행하고 있는 프로세스가 있을것이고 수행하지 않고 Ready queue에 머무르고 있는 프로세스들이 있을겁니다. 이때 만약, 0x00001000이라는 가상주소에 접근하려하면 TLB와 페이지테이블을 참조하여 실제메모리 주소를 얻어와야하는데, 그렇다면 이 TLB와 페이지테이블이 어떻게 지금 실행중인 프로세스에 관한 매핑테이블이란걸 알 수 있는거지요???

감사합니다.

익명 사용자의 이미지

시험공부 하시는 건가요?

익명 사용자의 이미지

동일 익명인인데요... 님 글을 보면... 공부하면서 발생되는 일반적인 의문 같지는 않고,
어떤 숙제나, 과제, 논문.. 이런 거 준비하거나... 아니면 글을 검토하고 계시거나... 맞나요??

kyj_kr의 이미지

독학하고 있어요. 뭔가 희열감이 넘칩니다ㅎ!

익명 사용자의 이미지

스왑 매니저는 여기 보시면 되고요.. 그게 하드웨어적으로 구현이 되어야 하는지도 의문입니다.

https://m.blog.naver.com/PostView.nhn?blogId=jevida&logNo=140194288224&proxyReferer=https%3A%2F%2Fwww.google.com%2F

익명 사용자의 이미지

> 이때 만약, 0x00001000이라는 가상주소에 접근하려하면 TLB와 페이지테이블을 참조하여 실제메모리 주소를 얻어와야하는데, 그렇다면 이 TLB와 페이지테이블이 어떻게 지금 실행중인 프로세스에 관한 매핑테이블이란걸 알 수 있는거지요???

이 질문에 대해서는

https://blog.naver.com/sungeuns/50098147696

를 읽어보시면 되겠네요.

아니.. 그 정도로 의문이 많으면 그냥 책을 사보시는게 좋지 않나요? 저도 의문이네요.

kyj_kr의 이미지

덕분에 cpu cache에도 매핑테이블이 있다는 사실을 알게되었습니다!
cpu cache에서는 프로세스 별로 구분하기 위하여 cache 테이블의 태그에 pid를 입력한다는것도 알게되었구요. 헌데, TLB나 메모리에 상주하는 PAGE TABLE 같은 경우에는 대체 어떻게 프로세스를 구분할 수 있는거지요? 불현듯, 떠오르는 생각인데 Context-Switching 하면서 레지스터 정보에 페이지 테이블의 시작주소가 저장되어 실제 메모리에 상주중인 특정 프로세스의 페이지 테이블을 확실히 참조할 수 있는건가요?

kyj_kr의 이미지

cpu cache에 매핑테이블은 없네요.. 혼동했습니당

익명 사용자의 이미지

가상 주소, MMU 에 대한 좋은 글이 여기 또 있네요.

https://slenderankle.tistory.com/189

kyj_kr의 이미지

책을 읽으면서 공부하는중이에요.
헌데, 책에 있는 글을 읽고서 말뜻을 이해못하겠거나 질문사항이 생기면 구글에 찾아보고
여기다가 질문하는 형식으로 공부중이에요..!

익명 사용자의 이미지

아.. 그러시구나.. 괜히 제가 오해할 뻔 했네요..
저도 같이 공부하면서 아는거 있으면 답변드릴게요^^

bushi의 이미지

뭔가 엄청나게 오해한 사람이 글을 작성한 것 같습니다.

MMU 가 태어난 근본적인 이유는 이름 그대로 memory management 를 위한 것입니다.
1MiB 램을 가진, MMU 없는 기계에서 어플이 다음과 같은 코드를 수행해야 한다고 가정해 봅시다.

buf_a=malloc(256KiB);
buf_b=malloc(256KiB);
buf_c=malloc(256KiB);
buf_d=malloc(256KiB);
free(buf_b);
free(buf_d);
buf_e=malloc(512KiB);

buf_e 를 위한 메모리 할당은 실패합니다.
램에 512KiB 의 여유가 있지만 불연속이고, 따라서 memset(buf_e, 0, 512KiB) 같은 것이 불가능하기 때문에 malloc 은 반드시 실패해야 합니다.
MMU 는 이 문제, 쉽게 말해... 물리적으로 램 용량이 충분한데도 쓰지 못하는 문제를 해결하기 위해 만들어졌습니다.

어플이 가상 주소 공간 상에서 512KiB 만큼 연속된 만큼의 주소 공간을 할당받고,
이 가상 주소를 사용해서 메모리 접근을 시도할 때 MMU 가 중간에 끼어들어서 즉각적으로 램의 물리 주소로 번역해준다면,
물리적인 램 공간이 불연속이어도 어플은 마치 연속된 램 공간을 사용하는 것 마냥 아무 문제없이 사용할 수 있게 되겠죠.

매핑의 단위인 페이지 크기는 매핑 테이블의 크기와 관련되어 있습니다.
매핑 테이블도 램에 둬야 하는데, 매핑 단위를 너무 작게 하면 램 용량의 많은 부분을 테이블이 쳐묵쳐묵 할 테니까요.

매핑 테이블이 1차원 배열 구조가 아니라 트리 형태인 이유 역시 매핑 테이블의 크기와 관련되어 있습니다.
MMU 그 자신이 참조해야 하기 때문에 테이블은 반드시 물리적으로 연속인 램 공간에 있어야 합니다.
1차원 배열 구조라면, 테이블을 통째로 물리적으로 연속인 램공간에 둬야하는데 테이블 크기가 커지면 부담스럽죠.
이미 페이지 단위로는 물리적으로 연속인 것을 약속했으므로, 테이블 한개의 최대 크기를 페이지 크기로 삼아서 테이블 여러개를 트리 형태로 엮는 방식을 사용합니다.

프로세스 별로 MMU 매핑 테이블을 따로 운영하는 것은 보안(보호?) 문제가 가장 큰 이유입니다. (그래서 매핑 같은 고급 기능은 전혀 없고 보호 기능 정도만 제공하는 MPU 도 널리 쓰입니다)
아무튼, 이런 운용을 하는 OS 들 때문에 MMU 도 더 복잡해집니다.
번역할 때 마다 램의 매핑 테이블을 접근하는 것 보다 매핑 테이블 전용의 캐시를 MMU 가 따로 가지고 있는 편이 성능측면에서 말도 안되게 이득인데,
프로세스 context switch 할 때 마다 매핑 테이블이 바뀐다면 MMU 가 가지고있는 매핑 테이블 캐시도 그때마다 싹 비워야하니 엄청난 손해를 보게 될 게 뻔하고,
그래서 매핑 캐이블 캐시를 싹 비워버리는 대신 캐시에 담을 때 뭔가 id 같은 것을 붙여서 같이 담아두고 나중에 번역할 때 이 id 을 참조해서 캐시에 있는 것을 쓸 것인지 테이블에서 새로 참조할 것인지 판단하게 만드는게 보통입니다.
이 기능을 쓸지 말지는 OS 의 선택이고.

ondemand alloc(copy on write 포함), disk swap 같은 것들은 MMU 가 CPU 에 제공하는 exception(page fault) 을 이용한 트릭들입니다.
둘 모두 page fault 시점에서 물리적인 램을 할당하고 fault 가 발생한 가상 주소를 기반으로 페이지 테이블 찾아서 물리 주소 부분을 수정해서 다음번 부터 fault 없이 번역이 제대로 되도록 만드는, MMU 입장에서 봤을 땐 단순하고 간단하지만, OS 입장에서 봤을 땐 페이지 별로 어떤 handler function 이 실행될 것인지 미리 다 정해놓아야 하는 등 꽤 지저분한 일거리고요.

bushi의 이미지

글 수정이 안되어 댓글답니다.

게시된 글을 제가 설렁설렁 읽었나봅니다.
쉽게 오해 할 수 있는 부분이 있어서 노파심에 조언하자면,
가상메모리(virtual memory) 와 가상주소(virtual address)가 헷갈리지 않도록 계속 되새기며 글을 읽어야하고,
글에 설명된 순서와는 반대로 virtual address 부분을 먼저 이해하고 virtual memory 부분을 읽는 것이 덜 헷갈립니다.

kyj_kr의 이미지

이해하기 쉽게 정말 글을 잘 적어주셨어요.. 감사합니다 !

그런데도 궁금한점이 남아있습니다..

일단, MMU가 가지고 있는 매핑 테이블 캐시 부분에서는 프로세스 id 태그를 하나 더 붙여놓아
어떤 프로세스의 가상메모리주소 <-> 물리메모리주소 매핑인지 파악할 수 있다는걸 새롭게 알게되었습니다!
헌데, 실제 메모리에 상주하는 매핑 테이블 즉, 페이지 테이블은 프로세스 별로 있을텐테 그렇다면, 이 페이지 테이블은 어떤 방식으로 자신이 특정 프로세스의 매핑 테이블이다! 라고 어필(?)할 수 있는거죠?

그리고 이 페이지 테이블들은 실제 메모리 부분의 커널영역에 속해있는게 맞나요?

덧붙여, 말씀하신 내용중에 "ondemand alloc(copy on write 포함), disk swap 같은 것들은 MMU 가 CPU 에 제공하는 exception(page fault) 을 이용한 트릭들입니다." 라고 달아주셨는데 이 부분의 순서를 제 생각으로 한번 나열해보겠습니다. 엄한 지적 부탁드립니다.

cpu는 가상주소 0x00001234를 참조하려 하면서 메모리에 읽기제어신호를 보냅니다. 물론 cpu는 이 주소가 가상주소인지 물리주소인지 조차 신경을 안쓰겠죠. 여기서 MMU가 H/W적 메커니즘으로 cpu가 보내온 가상주소를 자신의 TLB cache 부분에 있는지 확인 후 있으면 TLB hit를 치며 주소버스로 실제메모리주소를 변환하여 주소버스에 태워 메모리로 보냅니다. 그리고 메모리에서는 읽기제어신호를 받았고, 읽고자 하는 메모리 주소 또한 받았으니 cpu에 그 데이터 값을 데이터버스에 태워 보내겠지요.

위와 같은 전개에서는 MMU가 하는 역할이라고는, 주소버스에서 주소를 받으면 그 주소를 실제 메모리 주소로 변환 후 메모리로 보내는 것뿐이죠.

다른 경우를 생각해보겠습니다. 이전과는 상황이 동일하고 TLB cache에서 변환하고자 하는 가상주소를 찾을 수 없다면, TLB miss를 치고 메모리의 페이지 테이블을 참조하겠지요. 이때 페이지 테이블의 시작주소가 MMU의 특정 레지스터에 저장되어있다고 합시다.(위에 제가 질문드린내용.. 잘모르겠지만 상황을 이끌어내기위해 가정하겠습니다.) 그럼 페이지테이블에 접근할 수 있게되었고 이 페이지 테이블의 인덱스로 찾아가보니 valid bit가 0인겁니다. 그러면 disk에서 인덱스가 가리키는 페이지를 실제메모리에 할당하기 위해서 말씀하신 exception(page fault)을 cpu에 보냅니다. 그러면 cpu가 디스크 장치에서 물리메모리로 page-in을 해주고, TLB cache도 업데이트 해줍니다. 그리고 MMU는 TLB를 다시 참조하여 hit를 치고 주소버스에 태워 메모리로 보내겠지요. 그 다음은 첫번째 상황과 동일하게 흘러가겠구요.

위와 같은 전개에서는 MMU가 직접 메모리를 참조하여 페이지테이블을 확인하는데, 이걸 MMU가 하는지 정확히 모르겠습니다. 또한, cpu가 디스크 장치에서 물리메모리로 page-in해주고, TLB cache마저 업데이트 해준다고 생각하는데 이게 맞는건지도 잘모르겠습니다..

글을 적다보니, 저는 지금 CPU와 MMU의 역할의 구분이 너무 애매하게 개념이 잡혀있는거 같습니다..
시스템 버스를 타고 신호를 보내는과정까지 다 알고싶은데 혹시 설명해주실 수 있을까요?

bushi의 이미지

MMU 는 RAM (혹은 ROM, 메모리 컨트롤러를 통해 random access 가 가능한 모든 장치)을 직접 접근해서 매핑 테이블을 참조합니다.

주소 변환이 되지 않을 때 MMU 는 CPU 에게 exception 을 줍니다.
CPU 는 exception 이 발생했을 때 등록된 벡터로 jump(혹은 call) 합니다.
위의 두가지 외에 상상하시는 모든 것은 OS(operating software)가 합니다.
매핑 테이블을 만들고 관리하는 것도 OS 이고,
MMU 에게 만들어진 테이블의 물리 주소를 알려주는 것도 OS 이고,
MMU 를 켜거나 끄는 것도 OS 가 해야하고,
CPU exception 발생에 대비한 준비를 미리 해 놓는 것도 OS 이고,
CPU exception 이 발생했을 때 미리 준비해 놨던 걸 이용해 적절히 대응하는 것도 OS 입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.