블링블링 범블링

[OS 17장] 메모리 관리 - 페이징 본문

Technology/오퍼레이팅 시스템

[OS 17장] 메모리 관리 - 페이징

뻠스키 2018. 4. 17. 17:46


- 페이징(1) -

 

메모리의 낭비 공간인 hole을 최소한으로 만들기 위해 앞 장에서 많은 방법을 사용하였다최초 적합과 최적 적합을 통해 메모리의 공간에 적재하는 방식에 변화를 주었는데 이를 통해서도 메모리 공간의 1/3 정도가 낭비가 되었다이렇기 때문에 다른 방식인 Compaction이라는 방식을 사용하였으나 프로세스나 hole을 메모리 공간에서 이동시키기 위해서는 메모리 계산의 부담이 발생하기 때문에 힘들었다그래서 사용한 방식이 바로 페이징이다.


페이징은 프로세스를 일정 크기인 페이지로 잘라서 메모리에 적재하는 방식이다프로세스는 항상 연속해서 들어가야 한다는 생각을 통해 메모리 공간 활용에 있어서 앞장에서는 연속 메모리 할당에 초점을 맞추었다이런 생각부터 뒤집어서 프로세스를 일정한 단위로 잘라서 사용하자는 방식이 페이징이다. hole과 프로세스를 모두 특정 페이지 단위로 잘라서 메모리 공간을 관리한다하지만 프로세스를 자르게 되면 실행이 될까에 대한 궁금증이 생긴다그러면 프로세스를 자르게 되더라도 실행을 할 수 있게 하는 방식은 무엇이 있을까?


앞에서 설명한 방식을 한 번 떠올려보자메모리 공간을 할당할 때 코드에서 명명한 메모리 주소 위치와 다르게 임의로 프로세스를 메모리에 적재하였다이렇게 할 수 있었던 이유는 바로 MMU의 재배치 레지스터의 값을 바꾸어 CPU를 속일 수 있었기 때문이다그러면 이왕 속이게 되는 거 재배치 레지스터를 많이 두어 각각의 페이지 단위의 프로세스를 활용할 수 있게 속이는 것은 어떻게 생각하는가프로세스를 나눈 페이지마다 재배치 레지스터를 만들어 놓으면 CPU는 마치 프로세스가 연속된 메모리 공간에서 동작하고 있다고 생각하게 될 것이다왜냐하면 재배치 레지스터에서 메모리 적재 공간의 값을 더해주어 CPU를 속이기 때문이다.



프로세스를 자르는 단위는 페이지이다이에 동일한 크기로 메모리를 자른 것을 프레임이라고 한다같은 크기로 페이지와 프레임으로 잘라져 있기 때문에 페이지를 프레임에 할당하면 딱 맞아 떨어진다이 때 페이지를 관리하는 MMU는 페이지 테이블이 된다페이지 테이블 안에 있는 개수는 프로세스를 몇 등분하는가에 따라 결정된다.


CPU가 내는 주소는 논리 주소(Logical address)라고 한다. CPU에서 보낸 논리 주소는 MMU인 페이지 테이블을 통해 물리 주소(Physical address)로 바뀌어서 메모리에서 찾게 된다논리 주소는 2진수로 표현된 m개의 비트이다하위 n비트는 오프셋 또는 변위를 나타내고 상위의 m-n비트는 페이지 번호를 나타낸다. n비트는 페이지를 어떤 크기로 나누는 정도에 따라 다르게 된다예를 들어 16바이트로 페이지를 나눈다고 생각하면 n은 4비트가 된다. 2진수로 표현된 값이기 때문이다페이지 테이블에서 페이지 번호를 가져와서 해당하는 프레임 번호를 가져오게 된다페이지 번호는 페이지 테이블의 인덱스 값으로 인식한다페이지 번호에 해당하는 페이지 테이블의 값과 n비트의 값을 가진 물리 주소로 바뀌게 된다.



예를 들어 50번지라는 논리 주소를 물리 주소로 바꾸고 싶다고 한다고 가정해보자이때 페이지의 크기는 16바이트이다. 50번지를 2진수로 바꾸게 되면 110010이 된다이때 페이지의 크기가 16바이트이므로 하위 4비트는 n비트가 되고 앞의 두 비트가 페이지 번호를 나타내는 인덱스 값이 된다그러면 페이지 테이블에서 11에 해당하는 3의 값을 가진 페이지 번호로 가게 되어 페이지 테이블 값을 읽는다만약 이 때의 페이지 테이블 값이 8이라고 하면 8과 n비트를 합쳐서 물리 주소를 가지게 된다그 값은 10000010 이라는 메모리 공간의 주소로 가게 되는 것이다. 10진수로 바꾸게 되면 130번지가 된다다시 해석하게 되면 테이블 값의 8은 128번지를 의미하게 되고 여기서 하위 n비트의 변위 값에 의해 130번지에서 이 프로세스의 페이지가 동작하게 되는 것이다.







- 페이징(2) -

 

다중 프로그래밍 환경으로 바뀌면서 다양한 프로그램들이 메인 메모리 공간에 올라가서 프로세스로 되어 동작하기 시작했다프로그램들은 필요할 때 메인 메모리로 적재되고 사용이 다 되면 다시 하드디스크로 돌아가게 된다이런 작동이 반복되면서 메모리 공간에는 hole이라고 하는 빈 공간이 만들어지게 된다이런 빈 공간이 흩어져 있게 되어 총 합으로는 충분한 공간의 빈 메모리 공간이 있을지라도 사용할 수 없는 공간이 되어버린다왜냐하면 프로세스는 연속된 공간에서 존재해야 동작했기 때문이다이러한 문제를 외부 단편화라고 했다그리고 외부 단편화를 해결하고자 노력을 많이 하였다연속 메모리 할당을 하는 방식에 차이를 두기도 하고 compaction 기법을 사용하기도 하였다하지만 여전히 메모리 공간이 낭비가 되고 그렇지 않으면 고비용이 들게 되었다그래서 나온 해결 방법이 바로 페이징이다.


페이징은 프로세스가 연속된 메모리 공간에 할당되어야 한다는 이론을 부셔버린 개념이다프로세스를 무조건 메모리 공간에 연속해서 적재하는 것이 아니라 프로세스를 일정한 단위인 페이지로 쪼개어 적재를 하는 것이다물론 메모리의 영역도 프레임으로 쪼개어 준비를 시켜놓는다프레임과 페이지는 같은 크기를 가지게 한다그러면 어떠한 프레임 공간에 페이지를 넣었는지 기억을 하게 되면 메모리 공간을 다 활용할 수 있게 되는 것이다.



CPU가 동작을 할 때 메인 메모리에 주소를 요구한다모든 계산의 기반은 주소를 통해서 진행되기 때문이다그래서 프로세스가 코딩이 되는 과정에서 각각의 프로세스는 주소 기반으로 작성이 되어 지게 된다몇 번지의 메모리 공간 주소에 적재될 것인지 그 이후의 명령어들은 몇 번지에 들어가는지가 이미 지정이 되어 있다. CPU는 이를 이용하여 메모리 공간에 들어가서 찾게 된다하지만 메모리 공간은 항상 특정 프로세스를 위해 공간을 비워놓지 않는다만약 비워 놓게 된다면 메모리 공간의 크기보다 프로그램들의 크기들의 합이 크기 때문에 프로그램을 사용할 수 없을 것이다따라서 임의로 메모리 공간에 적재를 하고 MMU라는 도구를 사용하여 메모리 공간의 위치를 조절한다.


MMU는 CPU와 메인 메모리 사이에서 존재하는데 재배치 레지스터를 가지고 있다이는 논리 주소와 물리 주소의 변환을 주관한다논리 주소는 CPU가 요구하는 주소 값이고 물리 주소는 메인 메모리가 인식하여 찾는 주소 값이다메인 메모리는 임의의 공간에 프로그램의 적재하고 이 메모리 주소 값에 맞게 재배치 레지스터 값을 설정하여 CPU가 이 프로세스에 대한 논리 주소를 요구할 때 물리 주소로 바꾸어 맞는 메모리 공간 주소를 지칭하게 해준다.


페이징은 재배치 레지스터를 페이지의 수만큼 만드는 것이다프로세스를 페이지 단위로 자른 후 이에 해당하는 페이지마다 재배치 레지스터를 통해 적절한 위치에 있도록 만든다그러면 CPU가 논리 주소를 요구할 때 논리 주소를 분석해서 적절한 물리 주소로 갈 수 있게 해준다프로세스가 메인 메모리에서 페이지 단위로 나뉘어 있지만 CPU는 항상 같은 논리 주소를 요구하므로 프로세스가 연속된 것처럼 보이게 된다이 과정에서 MMU는 페이지 테이블을 가지게 된다.



예시를 통해 주소 변환을 하는 과정을 살펴보자자세한 계산 방법은 앞 장을 참고하면 좋을 것이다.(운영체제 17페이지 사이즈가 4바이트이고 페이지 테이블에 페이지 번호 당 5, 6, 1, 2를 가진다고 한다그러면 페이지 번호가 0번이면 5로 1번이면 6으로 가는 것으로 인식하면 된다. CPU가 논리 주소로 13번지를 요구한다면 메인 메모리의 어디의 물리 주소 위치로 가야하는가? 13을 이진수로 표현하면 1101이 된다이 주소 값에서 페이지 사이즈가 4바이트이므로 변위는 하위 2비트가 된다그러므로 나머지 상위 2비트는 페이지 번호가 된다페이지 번호가 11이므로 3이 된다그러므로 3에 해당하는 2라는 물리 주소 값으로 가게 된다. 2는 이진수로 10이고 하위 비트 01을 붙여 물리 주소가 1001로 바뀌게 된다따라서 9번지에 실제 프로세스의 페이지가 위치하게 되는 것이다.


하지만 페이징 과정을 진행하면 내부 단편화가 발생할 수 있다페이징은 프로세스를 특정 단위인 페이지 단위로 나누어 주고 된다하지만 프로세스의 크기가 페이지 크기의 배수가 아니라면 마지막 프로세스의 페이지는 한 프레임을 다 채울 수 없다따라서 이런 공간이 메모리 안에서 빈 공간으로 남아 낭비되게 된다이런 문제를 내부 단편화라고 한다예를 들어 프로세스가 15바이트인데 페이지를 4바이트 단위로 나눈다고 생각해보자그러면 3묶음의 4바이트 페이지가 나오지만 마지막 페이지는 3바이트의 크기가 만들어 진다프레임은 4바이트 크기인데 3바이트 크기의 페이지가 들어오면 1바이트의 메모리 낭비가 생기게 되는 것이다하지만 외부 단편화에 비해 낭비되는 내부 단편화의 메모리 공간이 매우 미비하다.







- 페이징(3) -

 

모든 프로그램들은 실행되기 전에 하드디스크에 보관된다그리고 사용을 하고자 하는 프로그램들이 메인 메모리에 적재되어서 CPU를 할당받아 기능을 수행하게 된다처음에 메인 메모리에 프로세스의 적재를 배울 때에는 프로세스들이 연속적으로 하나씩 메모리에 적재되는 것으로 알고 있었다하지만 이런 방법은 메모리의 공간을 매우 낭비시켜 효율을 떨어뜨린다는 것을 배웠다이를 해결하기 위해 프로세스를 페이지라는 단위로 나누어서 메모리에 적재하는 방법인 페이징 기법을 사용하였다재배치 레지스터를 사용하여 페이지 테이블에 맞는 주소로 논리 주소를 물리 주소로 변환시켜 프로세스의 메모리 주소 위치를 파악하는 방법이다.


운영체제는 프로세스 관리와 메모리 관리 외에도 다양한 일을 수행한다그 중에서 보호라는 기능도 수행을 하는데 해킹 등을 방지하는 것을 말한다그런데 메모리 관리를 하면서 왜 보호에 대해서 이야기를 하는가모든 프로세스는 CPU에서 요구하는 논리 주소에 의해 기능을 수행한다다른 말로 모든 주소는 페이지 테이블을 경유해서 메인 메모리로 들어가게 된다따라서 페이지 테이블에서 메모리에 대한 해킹을 할 수 없도록 장치를 만들어 놓으면 보호의 기능이 매우 높아질 것이다이렇게 하는 방법이 바로 페이지 테이블 엔트리마다 r, w, x 비트를 두는 방식이다. 3개의 비트를 통해서 해당 페이지에 대한 접근 제어를 가능하게 만들어 준다특정 비트를 가지면 내용을 읽을 수만 있고 다른 비트를 가지만 내용을 읽고 쓰는 것을 모두 가능하게 한다따라서 해커가 읽을 수만 있는 비트를 가진 프로세스에 접근해서 내용을 수정하려고하면 바로 프로세스를 종료하도록 만들어 보호의 기능을 수행하는 것이다.


메모리를 활용하면 공유의 기능을 수행할 수 있다다중 프로그래밍을 지원하는 환경에서 메인 메모리에는 다양한 프로세스들이 동시에 올라와서 동작을 할 수 있다그런데 같은 프로그램을 지원하는 여러 가지 프로세스들이 올라오면 어떻게 될까예를 들면 한글 오피스를 3개의 파일을 실행시킨다고 생각해보자같은 프로그램인데 각각 다른 작업을 수행하기 위해 복수 개의 프로세스가 올라올 수 있다하지만 같은 프로그램이기 때문에 복수 개의 프로세스는 공통된 기능을 지원받을 수 있을 것이다그런데 메인 메모리에 적재될 때 각각 따로 프로그램이 지원하는 기능을 메모리에 올린다면 메모리의 낭비가 될 것이다이런 경우를 위해 운영체제는 code의 영역에는 공유가 가능하게 만들었다. code 영역은 읽는 것만 가능하고 수정하는 것이 불가능하다따라서 임계구역 문제가 발생하지 않는다페이징 기법을 통해 프로세스의 부분이 페이지의 단위로 나뉘어져 있으므로 code를 이용하는 페이지를 따로 공통으로 사용하는 메모리 주소에 넣는 방법을 수행한다만약 같은 프로그램의 복수 개의 프로세스가 올라올 경우 공통으로 사용하는 코드부분을 특정 메모리에 하나만 적재시킨다그리고 프로세스의 페이지 테이블에서 코드 영역으로 가는 부분을 같은 곳을 가리키게 하여 각각 따로 사용을 하지만 메모리에는 하나의 공간만 차지하게 만드는 것이다물론 CPU는 프로세스들이 연속된 환경에서 움직이고 있다고 생각할 것이다.




Comments