본문 바로가기
운영체제

운영체제 20장 - 메모리 관리(7) : 세그멘테이션(Segmentation) -

by ChocoPeanut 2017. 5. 5.

운영체제 20

- 세그멘테이션(Segmentation) -

 

앞선 장들에서 페이징을 배우면서 프로세스를 일정 크기인 페이지 단위로 잘라서 메모리에 적재하는 방법을 알았다. 페이지는 정확하게 일정한 간격으로 자르는 단위였다. 하지만 프로세스를 물리적인 단위인 페이지 말고 논리적 내용 단위인 세그먼트로 자를 수 있는 세그먼테이션 방법이 있다. 예를 들면 우리가 돼지를 잡아서 보관을 한다고 생각해보자. 페이징의 방법을 사용하면 돼지를 모두 같은 단위로 잘라서 보관을 하는 것이다. 반면에 세그먼테이션은 부위별로 다른 크기로 잘라서 보관하는 것이다.


세그멘테이션은 프로세스를 세그먼트의 집합으로 생각한다. 사실 하나의 프로세스가 동작하려면 기본적으로 코드, 데이터, 스택 세 가지의 세그먼트는 항상 가지고 있다. 그리고 더 들어가 보면 코드에서도 main 함수가 있을 수 있고, 다른 함수들이 있을 수도 있고, 다른 루틴이 있을 수도 있다. 데이터를 보아도 어떤 구조체가 있을 수도 있고 배열도 있을 수 있다. 그래서 세그먼테이션은 물리적인 크기의 단위가 아닌 논리적 내용의 단위(의미가 같은)로 자르기 때문에 세그먼트들의 크기는 일반적으로 같지 않다.


프로세스를 어떻게 자르는가에 대한 방법 빼고 메모리에 할당하는 방법에 대해서는 페이징과 방법이 같다. MMU 내의 재배치 레지스터를 이용하여 논리 주소를 물리 주소로 바꾸어 주는 방식을 취한다. MMU는 세그먼트 테이블로 CPU에서 할당한 논리 주소에 해당하는 물리 주소의 위치를 가지고 있다. 이 방법을 이용하면 CPU는 프로세스가 연속된 메모리 공간에 위치한다고 착각을 하게 된다.



주소를 변환하는 방법 역시 같다. 하지만 논리 주소에서 보내는 주소 값에서 하위 변위 비트를 제외한 앞의 비트들은 페이징 번호가 아니라 세그먼트 번호가 되는 것이다. 따라서 논리 주소는 세그먼트 번호와 변위 비트로 이루어져 있게 된다. 세그먼트 테이블에 논리 주소 값이 들어가게 되면 세그먼트 번호는 세그먼트 테이블의 인덱스 값으로 인식을 하게 된다. 세그먼트 번호를 토대로 테이블 내용으로 들어가 시작 위치 및 한계 값을 파악한다. 물리 주소는 세그먼트 테이블에 있는 시작 위치와 변위 값을 합하여 구할 수 있다. 그런데 이런 주소 값이 한계(각 세그먼트의 크기)를 넘어서면 segment violation 예외 상황 처리를 하게 된다. 이런 경우는 변위가 한계보다 크면 발생한다.


세그먼테이션의 경우에도 보호와 공유의 기능을 수행하고 있다. 모든 논리 주소들은 세그먼테이션 테이블을 경우하게 되므로 세그먼트 테이블 엔트리마다 r, w, x 비트를 만들어 해당 세그먼트에 대한 접근 제어를 가능하게 해준다. 또한 같은 프로그램을 사용하는 복수 개의 프로세스가 있다면 메모리에 하나만 적재하여 프로세서의 세그먼트 테이블 코드 영역이 같은 곳을 가리키게 만든다. 그런데 위와 같은 기능이 페이징의 기법보다 더 좋다고 할 수 있다. 간단하게 생각을 해보아도 그렇다는 것을 알 수 있다. 페이징은 프로세스를 같은 단위로 자르게 되므로 중요한 부분과 중요하지 않은 부분이 같은 페이지 안으로 잘라질 수 있다. 또한 코드 영역 또한 같은 단위로 잘리므로 애매하게 잘려질 확률이 있다. 하지만 세그먼테이션의 방법으로 자르게 되면 코드 영역은 코드 영역으로 잘리게 되고 중요한 세그먼트, 중요하지 않은 세그먼트를 논리적인 내용 측면으로 자를 수 있다. 그렇게 되면 보호와 공유의 기능을 수행하기 쉬워지는 것이다. 내용적인 측면으로 다 나누어 졌기 때문이다.


그러면 세그먼테이션만 사용하면 될 것 같지만 이 또한 단점을 가지고 있다. 세그먼트는 크기가 고정되어 있지 않고 가변적이다. 크기가 다른 각 세그먼트를 메모리에 두려면 동적 메모리 할당을 해야 한다. 앞에서 말한 외부 단편화가 발생할 수 있다. 외부 단편화는 메모리 낭비를 매우 크게 발생시킨다. 세그먼테이션을 사용하기 힘든 것이다. 따라서 우리는 세그먼테이션과 페이징의 기법을 모두 사용하고자 한다. 두 방식 모두 장단점을 가지고 있으니 장점만을 가져오게 되면 좋은 방법이 될 수 있기 때문이다. 세그먼테이션은 보호와 공유 면에서 효과적이고 페이징은 외부 단편화 문제 해결에 효과적이므로 두 가지 모두를 사용할 수 있으면 좋을 것이다. 따라서 세그먼트를 페이징 하는 방법을 취한다.



프로세스를 처음에 세그먼트 단위로 자른다. 의미 있는 단위로 나누게 되면 보호와 공유를 하는 측면에 이점을 가질 수 있게 된다. 하지만 앞서 말했듯 외부 단편화가 발생할 수 있다. 그래서 우리는 잘라진 세그먼트를 다시 일정 간격인 페이지 단위로 자르는 페이징 방법을 취한다. 그래서 메모리에 적재하면 페이징의 일정 단위로 다시 잘렸기 때문에 외부 단편화가 발생하지 않는다. 하지만 이와 같은 경우에는 테이블을 두 가지를 모두 거쳐야 하므로 속도 면에서 조금 떨어질 수 있다.