[운영체제(OS)] 14. 세그멘테이션

SungBum Park·2020년 2월 4일
2

지금까지 살펴본 페이징은 프로세스를 물리적으로 일정한 크기로 나눠서 메모리에 할당하였다. 반면에 세그먼테이션은 프로세스를 논리적 내용을 기반으로 나눠서 메모리에 배치하는 것을 말한다.

세그먼테이션은 프로세스를 세그먼트(segment)의 집합으로 만들고, 각 세그먼트의 크기는 일반적으로 같지 않다. 프로세스를 code + data + stack 으로 나누는 것 역시 세그먼테이션의 모습이다. 물론 code, data, stack 각각 내부에서 더 작은 세그먼트로 나눌 수도 있다.

세그먼트를 메모리에 할당할 때는 페이지를 할당하는 것과 동일하다. 하지만 테이블은 조금 다른데, 세그먼테이션을 위한 테이블은 세그먼트 테이블이라고한다. 그리고 세그먼트 테이블은 세그먼트 번호와 시작 주소(base), 세그먼트 크기(limit)를 엔트리로 갖는다.

세그먼트에서 주소변환 역시, 페이징과 유사하다. 한 가지 주의할 점은 세그먼트의 크기는 일정하지 않기 때문에, 테이블에 limit 정보가 주어진다. 그리고 CPU에서 해당 세그먼트의 크기를 넘어서는 주소가 들어오면 인터럽트가 발생해서 해당 프로세스를 강제로 종료시킨다. 그러면 세그먼트 주소변환 예제를 하나 살펴보자.

OS14-1

위 그림은 세그먼트 테이블과 프로세스가 할당된 메모리의 모습이다. 페이징 주소변환과 동일하게 d는 논리주소와 물리주소가 동일하다. 물리주소 a는 base[s] + d 로 계산된다.

  • 논리주소 (2, 100) => 물리주소 4400번지
  • 논리주소 (1, 500) => 인터럽트로 인해 프로세스 강제 종료(범위를 벗어남)

1. 세그먼테이션에서 보호와 공유

먼저, 결론부터 말하면 페이징보다 세그먼테이션에서의 보호와 공유는 더 효율적이다.

보호에서는 세그먼테이션 역시 r, w, x 비트를 테이블에 추가하는데, 세그먼테이션은 논리적으로 나누기 때문에 해당 비트를 설정하기 매우 간단하고 안전하다. 페이징은 code + data + stack 영역이 있을 때 이를 일정한 크기로 나누므로 두 가지 영역이 섞일 수가 있다. 그러면 비트를 설정하기가 매우 까다롭다.

공유에서도 마찬가지다. 페이징에서는 code 영역을 나눈다해도 다른 영역이 포함될 확률이 매우 높다. 하지만 세그먼테이션은 정확히 code 영역만 나누기 때문에 더 효율적으로 공유를 수행할 수 있다.

2. 세그먼테이션과 페이징

세그먼테이션은 페이징과 유사하고 보호와 공유에서는 더 나은 성능을 보여주었지만, 현재 대부분은 페이징 기법을 사용한다. 그 이유는 세그먼테이션에는 치명적인 단점이 있기 때문이다.

메모리 할당을 처음 시작할 때 다중 프로그래밍에서의 문제는 크기가 서로 다른 프로세스로 인해 여러 크기의 hole이 발생한다. 이로 인해 어느 hole에 프로세스를 할당하는 것에 대한 최적화 알고리즘이 존재하지 않고, 외부 단편화로 인해 메모리 낭비가 크다고 했었다.

세그먼테이션도 똑같은 문제점이 발생한다. 왜냐하면 세그먼테이션은 논리적인 단위로 나누기 때문에 세그먼트의 크기가 다양하다. 이로 인해 다양한 크기의 hole이 발생하므로 같은 문제가 발생한다.

결론적으로 세그먼테이션은 보호와 공유에서 효율적이고, 페이징은 외부 단편화 문제를 해결할 수 있다. 그러므로 두 가지를 합쳐서 사용하는 방법이 나왔다. 두 장점을 합치기 위해서는 세그먼트를 페이징 기법으로 나누는 것이다.(Paged segmentation)

하지만 이 역시 단점이 존재한다. 세그먼트와 페이지가 동시에 존재하기 때문에 주소 변환도 두 번해야한다. 즉 CPU에서 세그먼트 테이블에서 주소 변환을 하고, 그 다음 페이지 테이블에서 또 주소 변환을 해야한다.

Reference

profile
https://parker1609.github.io/ 블로그 이전

0개의 댓글