연속 메모리 할당 방식은 크고 작은 빈 공간 때문에 메모리의 효율성이 떨어졌다. (빈 공간을 합치는 방법이 있지만 오버해드 발생 때문에 효율이 떨어진다) 이러한 문제를 해결하기 위해 나온 방식이 페이징(Paging)이다.
페이징(Paging)은 비연속 메모리 할당 방식으로 하나의 프로세스를 일정한 크기로 작게 나누어 메모리에 할당하는 방식이다. (hole 크기 또한 작게 나뉜 프로세스 크기와 동일)
프로세스를 일정한 크기로 나뉜것을 "페이지(page)"라 부르며 빈 공간(hole)에 어떤 페이지든 적재할 수 있기 때문에 메모리를 효율적으로 사용할 수 있다. 메모리를 일정한 크기로 나눈것을 "프레임(frame)"이라 부르며 페이지와 크기가 같다.
한 프로세스를 여러 분산 위치에 적재하기 때문에 운영체제의 관리 부담이 크다는 단점이 있다. 또한 마지막 페이지에 할당된 프레임이 완전히 차지 않을 경우 단편화가 발생한다.
위 그림은 프로세스를 4개의 페이지로 나누어 프레임에 할당하는 그림이다. CPU는 프로그램의 설정 때문에 각 페이지에게 연속적인 주솟값을 할당해 주려고 하지만, MMU의 재배치 레지스터(Relocation register)에 의해 주소가 변한다. (CPU는 프로세스가 연속된 메모리 공간에 적재되었다고 생각하지만, 사실 주소가 변경되어 사용되고 있다)
이렇게 메모리의 효율성을 높이기 위해 논리적 주솟값을 MMU장치를 통해 물리적 주솟값으로 변경하여 재배치한 레지스터를 페이지 테이블(Page Table)이라 한다.
내부 단편화(Internal Fragmentation)란 프로세스가 사용하는 메모리 공간 중 남는 부분이 발생하는 현상이다.
프로세스 크기가 페이지 크기의 배수가 아닌 경우, 마지막 페이지는 한 프레임을 다 채울 수 없기 때문에 남는 공간이 발생한다. (남은 공간 = 메모리 낭비)
페이징 방법에서 발생하는 내부 단편화는 해결할 방법이 없지만, 남는 공간이 매우 작기 때문에 무시하면서 사용된다.
페이지 테이블은 MMU의 위치에 따라 여러가지 방법으로 만들수 있다.
첫 번째 방법으론 MMU의 위치를 CPU 내부로 이동하여 만드는 방법이다. CPU 안에 있는 기억장치인 레지스터들을 활용하여 페이지 테이블을 만든다. 장점으로는 주소 변환 속도가 빠르다는 장점이 있다. 하지만 CPU 안의 레지스터 수는 한정되어 있다는 단점이 있다.
두 번째 방법으론 MMU의 위치를 메모리 내부로 이동하여 만드는 방법이다. 메모리 내부에 만들어진 페이지 테이블의 장/단점은 CPU 방법과 반대이다. 페이지 테이블의 크기 제한이 없다는 장점을 가지고 있지만, 단점으로는 접근 속도가 느리다는 단점이 있다.
세 번째 방법으론 페이지 테이블을 별도의 칩으로 만들어 CPU와 메모리 사이로 위치시켜 작동하는 방식이다. 이러한 페이지 테이블을 TLB(Translation Look-aside Buffer)라 부르며, 위 두 가지 방법의 단점을 해결하기 위해 만들어진 방법이다.
보호(Protection): 해킹 등 방지
모든 주소는 페이지 테이블을 경유하므로, 페이지 테이블 엔트리마다 r(read), w(write), x(execute) 비트를 두어 해당 페이지에 대한 접근을 제어하는 방법으로 보호한다.
(리눅스의 권한 부여 기능과 비슷)
공유(Sharing): 메모리 낭비 방지
같은 프로그램을 쓰는 복수 개의 프로세스가 있다면, 해당 프로그램의 code+data+stack에서 code 부분은 공유하여 메모리 낭비를 최소화하는 방법이다. 단, 프로그램의 code가 변하지 않는 프로그램 한에서만 가능하다. 변하지 않는 code를 non-self-modifying code = reentrant code(재진입가능 코드) = pure code라 부른다.