2 minute read

MMU안에 오직 하나의 베이스와 바운드 쌍만 존재하는 방식에서는 
스탭과  사이의 공간은 사용되지 않더라도
물리 메모리를 차지하게 된다는 단점이 있다.

Screen Shot 2023-01-09 at 9 25 06 AM

세그먼테이션: 베이스(base)/바운드(bound)의 일반화

  • MMU안에 주소 공간의 논리적인 세그먼트(segment)마다 베이스와 바운드 쌍이 존재한다.
  • 세그먼트는 특정 길이를 가지는 연속적인 주소 공간이다.
  • 이는 운영체제가 각 세그먼트를 물리 메모리의 각기 다른 위치에 배치할 수 있어 사용되지 않는 가상 주소 공간이 물리 메모리를 차지하는 것을 방지할 수 있다.
  • 세그먼트 테이블을 만들어 매우 많은 세그먼트를 유동성있게 만들 수 있으나, 코드, 스택, 힙만을 지원하는 세그먼트로 작동 방법을 파악해보자.

세그먼트 종류 파악

  • 하드웨어는 주소 변환을 위해 세그먼트 레지스터를 사용한다.
  • 하드웨어는 가상 주소를 보고, 어떤 세그먼트를 참조하는지, 그리고 그 안에서 오프셋이 어떻게 되는지를 알 수 있어야 한다.

1. 가상 주소의 최상위 비트 기준

Screen Shot 2023-01-09 at 11 25 13 AM

  • 3개의 세그먼트를 표현하기 위해서는 2비트가 필요하다.
  • 최상위 비트가 00이면 코드, 최상위 비트가 01이면 힙, 최상위 비트가 11이면 스택 영역을 가리킨다.
    • 여기서는 최상위 비트가 10이 사용되지 않기에 전체 주소 공간의 1/4가 낭비된다. 코드와 힙을 하나의 세그먼트로 저장하여 최상위 1비트만 사용할 수 있다.
#define SEG_MASK      0b11000000000000    // 14 bit VA중 상위 2bit를 얻어옴
#define SEG_SHIFT     12
#define OFFSET_MASK   0b00111111111111    // 14 bit VA중 offset을 얻어옴

segment = (VirtualAddress % SEG_MASK) >> SEG_SHIFT
Offset = VirtualAddress * OFFSET_MASK
if (Offset >= Bounds[Segment])
	RaiseException(PROTECTION_FAULT)
else
	PhysAddr = Base[Segment] + Offset
	Register = AccessMemory[PhysAddr]

2. 묵시적(implicit) 접근 방식

  • 주소가 어떻게 형성되었는가를 관찰하여 세그먼트를 결정한다.
    • 주소가 프로그램 카운터에서 생성되었다면(즉, 명령어 반입) 주소는 코드 세그먼트 내에 있을 것이다. 주소가 스택 또는 베이스 포인터에 기반을 둔다면 주소는 스택 세그먼트 내에 있다. 다른 주소는 모두 힙에 있어야 한다.

세그먼트 주소변환

Screen Shot 2023-01-09 at 11 24 56 AM

1. 코드 영역

  • 코드 세그먼트는 물리 주소 32KB에 배치되고, 크기는 2KB.
  • 코드 영역에 있는 가상 주소 100번지를 참조한다고 해보자.
    • 하드웨어는 베이스 값에 오프셋을 더해 물리 주소를 구한다.
    • 따라서 물리주소 32KB + 100, 32868을 읽는다.

2. 힙 영역

  • 힙 세그먼트는 물리 주소 34KB에 배치되고, 크기는 2KB
  • 힙 영역에 있는 가상 주소 4200번지를 참조한다고 해보자.
    • 코드 영역처럼 가상 주소가 0에서부터 시작하지 않기 때문에 오프셋부터 구해야 한다.
    • 오프셋은 힙의 가상 주소 시작부분에서 참조하는 부분을 빼서 구한다.
    • 힙의 시작부분(4KB)에서 시작하므로, 오프셋은 4200 - 4096(4KB), 104가 된다.
    • 따라서 물리주소 34KB + 104, 34920을 읽는다.

3. 스택 영역

  • 스택 세그먼트는 물리 주소 물리 주소 28KB에 배치되고, 크기는 2KB.
  • 반대 방향으로 확장하므로, 하드웨어는 세그먼트가 어느 방향으로 확장하는지도 알아야 한다. (1bit가 필요하다)
  • 스택 영역에 있는 가상 주소 15360(15KB)번지를 참조한다고 해보자.
    • 이 가상주소를 이진 형태는 0b11 1100 0000 0000이고, offset은 4KB - 3KB을 하면 1KB가 된다.
    • 가상 주소의 시작 부분(0b11 1111 1111 1111)에서 (0b11 1100 0000 0000)빼면 offset(0b00 0011 1111 1111, 1KB)가 된다. (주소가 반대로 확장되기에 시작 주소에서 오프셋을 더하는 방식이 아님)
    • 따라서 시작주소 28KB - 1KB, 27KB를 읽는다.

공유 지원 가능

  • 메모리를 절약하기 위해, 특정 메모리 세그먼트를 공유하는 것이 유용하다. 일반적으로 코드영역을 공유한다.
  • 공유를 지원하기 위에, 하드웨어에 protection bit의 추카가 필요하다.
    • 이는 세그먼트를 읽거나 쓸 수 있는지 혹은 코드를 실행시킬 수 있는지를 나타낸다.
  • 가상 주소가 범위 내에 있는지 확인(limit register)외에도 특정 권한이 있는지를 확인해야 한다.

Screen Shot 2023-01-09 at 11 25 36 AM

세그먼테이션 기법의 문제

전체 주소 공간이 하나의 베이스-바운드 쌍이 가지는
간단한 방식에 비해 물리 메모리를 엄청나게 절약할  있다.
구체적으로, 스택과  사이의 사용하지 않는 공간에
물리 메모리를 할당할 필요가 없다.

1. 외부 단편화(external fragmentation)

  • 물리 메모리가 빠르게 작은 크기의 빈 공간들로 채워진다는 것이다.
  • 기존 세그먼트를 정리하여 물리 메모리를 압축할 수 있겠지만, 세그먼트 복사는 메모리 부하가 굉장히 큰 연산이다.

Screen Shot 2023-01-09 at 11 25 53 AM

  • 빈 공간 리스트를 관리하는 알고리즘을 사용한다.
    • 1. 최적 적합(best-fit): 빈 공간 리스트에서 요청된 크기와 가장 비슷한 크기의 공간을 할당한다.
    • 2. 최초 적합(worst-fit): 빈 공간 리스트에서 요청된 크기를 할당할 수 있다면 바로 할당한다.
    • 3. 버디 알고리즘(buddy algorithm): 가능한 최소의 2의 거듭제곱 크기의 만큼으로 할당한다.

2. 드문드문 사용되는 주소 공간(sparse address area)

  • 세그먼테이션 기법은 크기가 매우 크지만 드문드문 사용되는 주소 공간을 지원할 만큼 유연하지가 않다. 이 힙에 접근하기 위해서는 힙 전체가 물리 메모리에 존재하여야 한다.