[운영체제/OS] 메모리 관리 - 세그멘테이션(Segmentation)과 페이징 기법

kindof

·

2021. 6. 14. 20:46

💡 0. 들어가면서

지난 글에서는 메모리 관리 기법 중 페이징 기법에 대해 공부했습니다.

 

페이징 기법은 논리적 메모리를 페이지 단위로 쪼개고, 물리적 메모리를 프레임 단위로 쪼개서 이를 대응하는 방식으로 연속적이지 않은 주소 공간의 매핑이 가능했습니다.

 

하지만 페이징 기법에서는 메모리 접근에 대한 오버헤드 문제와 커다란 페이지 테이블을 관리하는 메모리 이슈가 존재했고, 이를 해결하기 위한 TLB 레지스터와 Multi-level paging 등의 개념에 대해서 다루게 되었습니다.

 

 

[운영체제/OS] 메모리 관리 - 페이징(Paging) 기법

📖 0. 들어가면서 지난 포스팅에서 공부한 Partitioning, Buddy system 등의 메모리 관리 기법은 프로세스의 논리적인 메모리 주소를 물리적인 메인 메모리에 연속적인 Mapping을 전제했습니다. [운영체

studyandwrite.tistory.com

 

이번 글에서는 세그멘테이션(Segmentation)이라는 방법을 통해 메모리를 관리하는 기법에 대해 알아보고 페이징 기법과 세그멘테이션 기법을 비교, 혼합해서 사용하는 방식에 대해 알아보겠습니다.


📒 1. 세그멘테이션(Segmentation) 기법?

프로세스는 이미지로 구성되어 있고, 이미지는 해당 이미지의 내용에 따라 다른 특징을 가지고 있습니다. 그리고 이러한 이미지의 내용을 특징에 따라서 모아둔 것을 세그먼트(segment)라고 하며, 프로세스는 세그먼트들로 이루어진 집합이라고 재정의할 수 있습니다.

세그먼트

* ubuntu에서 readelf -l 명령을 사용하면 위와 같은 세그먼트 집합을 볼 수 있습니다.

 

이전에 배운 페이징 기법에서는 선형적인 주소 공간을 페이지 단위로 쪼갠 뒤 프레임에 할당하는 방식으로 세그먼트라는 개념이 존재하지 않았는데요. 세그멘테이션 기법은 프로세스의 이미지 영역들을 페이지가 아닌 세그먼트 단위로 쪼개서 물리적 메모리에 저장하는 기법입니다.

 

세그먼트


 

📖 2. 세그멘테이션 기법의 매핑

세그멘테이션을 이용한 메모리 관리는 페이징 기법과 유사합니다.

프로세스의 논리적인 주소는 이제 <# of Segment, offset>으로 표현됩니다.

 

세그먼트 테이블은 각 세그먼트가 저장된 물리적 메모리의 주소를 표현하기 위해 "Base", "Limit" 두 가지 변수를 사용하는데 Base는 세그먼트가 저장된 물리적 메모리의 시작 주소를 의미하며, Limit는 세그먼트의 길이를 나타냅니다.

 

따라서 물리적 주소 공간에서 세그먼트가 저장된 공간은 [Base, Base+Limit]가 될 것입니다. 페이징 기법에서와 거의 유사하죠?

 

👀 3. 세그멘테이션 기법의 특징 & 페이징 기법과의 비교

1) Protection, Sharing

페이징 기법에서는 code + data + stack 영역이 있을 때 이를 일정한 크기로 나누기 때문에 여러 영역이 섞이는 문제가 발생할 수 있었습니다. 하지만 세그멘테이션 기법에서는 r, w, x 비트들을 테이블에 추가할 수 있고, 이틀 통해 Protection에서 이점이 있습니다.

 

또한 페이징에서는 연속된 주소 공간을 페이지 단위로 끊기 때문에 속성이 다른 이미지들이 같이 묶일 수 있었는데 세그멘테이션 기법에서는 같은 세그먼트들이 묶이게 되고, 이 세그먼트가 특정 물리 메모리 주소에 매핑됨으로써 프로세스 간 동일한 세그먼트에 대한 공유가 쉬워집니다.

 

2) External Fragmentation

페이징 기법에서는 논리적 영역의 메모리를 같은 크기의 페이지로 쪼개고 이를 물리적 주소 공간의 프레임에 매핑했기 때문에 Internal Fragmentation 문제가 존재했습니다.

 

그런데 이 문제는 세그멘테이션 기법에서도 비슷하게 발생할 수밖에 없습니다. 세그먼트 자체가 컨텍스트의 특징에 따라 각기 다른 크기로 정의되고 이로 인해 다양한 크기의 hole이 발생하여 External Fragmentation 문제를 유발하기 때문입니다.


🗒 4. 세그멘테이션 + 페이징 기법?

위에서 살펴본 것처럼 세그멘테이션 기법은 Protection, Sharing 측면에서 장점이 있었고, 페이징 기법은 페이지와 프레임의 사이즈가 똑같기 때문에 External Fragmentation 문제를 없앨 수 있었습니다. 

 

그래서 두 가지 기법의 장단점을 생각하다 보니, "세그먼트를 페이징 기법으로 나누는 방식은 어떨까?"에 대한 방법이 등장했는데요.

 

이 방식의 핵심은 하나의 세그먼트를 내부적으로는 여러 개의 페이지로 나누고, 이 페이지를 물리적 메모리에 매핑하는 것입니다. 그러면 세그먼트의 특징을 보존하면서 Sharing, Protection의 이점을 살릴 수 있고, 세그먼트 단위가 아닌 더 작은 페이지 단위로 메모리를 다룸으로써 External Fragmentation 문제를 해결할 수 있는 것이죠.

 

Segmentation + Paging

개별적인 세그먼트는 물리적 주소의 어느 공간에 저장되어 있는지 알기 위해 세 가지 정보가 필요합니다.

 

1) 몇 번째 세그먼트인가?

2) 이 세그먼트는 어느 페이지에 속했는가?

3) 이 페이지의 offset은 얼마인가?

 

풀어서 이야기하면 세그먼트의 단위가 페이지보다 크기 때문에 1) 일단 몇 번째 세그먼트인지를 찾고, 2)해당 세그먼트 내에서 페이지 단위로 쪼개졌을텐데, 지금 저장하고자 하는 메모리가 어느 페이지인지 찾고 3) 그 페이지 내에서도 offset을 구해서 진짜 물리적 메모리에 저장하겠다는 것입니다.

위 그림에서 세그멘트 테이블을 보면 세그먼트 테이블의 인덱스는 세그먼트의 번호가 됩니다. 세그먼트 번호를 얻어서 세그먼트 테이블의 엔트리를 얻으면, 그 안에 페이지 테이블에 대한 정보가 들어있는 것이죠. 그리고 페이지 테이블의 인덱스는 마찬가지로 페이지 번호가 되고, 해당 페이지의 엔트리를 보면 페이지가 어느 물리적 메모리에 매핑됐는지에 대한 프레임 번호를 얻을 수 있습니다.


세그멘테이션과 페이징 기법을 혼합한 방식은 메모리 공간의 fragmentation 문제를 줄이면서도 세그먼트의 특징을 살려서 bit 정보를 통한 Protection과 Sharing을 용이하게 하는 이점이 있었습니다.

 

하지만, 위에서 본 것처럼 논리적 메모리가 물리적 메모리의 어느 부분에 매핑됐는지 찾기 위해서는 세그먼트 테이블 -> 페이지 테이블 순서로 두 번 접근해야 하기 때문에, 메모리 접근에 대한 성능 이슈가 남게 됩니다.

 


📊 5. 나가면서

이번에는 세그멘테이션 기법을 통한 메모리 관리 기법에 대해 공부하고, 이 기법을 페이징 기법과 비교해보았습니다. 그리고 두 가지 기법을 섞은 방식에 대해서도 알아보았는데요.

 

항상 모든 방식에는 장점과 단점이 있는 것 같습니다. 단순히 페이징 기법이 무엇이고, 세그멘테이션 기법이 무엇인지를 아는 것보다 이런 장단점과 각 기법의 필요성에 대해 한 번 고민해보면 좋을 것 같습니다.