운영체제

10. 세그멘테이션(Segmentation)

ggomjiu 2025. 1. 23. 10:32

Segmentaion

: 가상 주소 공간을 세그먼트 단위로 실제 메모리 주소 공간에 독립적으로 각각 매핑하는 방식

1. 정의

Motivation

- 기존 가상 주소 공간에서는 Heap과 Stack 사이의 사용하지 않는 공간도 할당되므로 비효율성이 발생

  • 사용하지 않는 크기가 발생하므로 메모리 공간이 낭비됨
  • 16KB이상의 메모리가 큰 주소 공간에는 프로세스를 지원할 수 없음
  • Code 공간에 여러 코드가 들어가서 중복이 발생할 수 있음
Effect

- 이로 인해 Heap과 Stack 사이의 사용하지 않는 비효율성인 문제를 해결

  • 더 이상 메모리 공간이 낭비되지 않음
  • 이전보다 훨씬 더 많은 주소 공간을 지원할 수 있음
  • 세그먼트는 주소 공간 간에 Code 공간을 공유하면서 메모리를 절약할 수 있음
세그먼트(Segment)

: 메모리에서 일정 부분을 의미

- 일반적인 주소 공간은 4개의 세그먼트로 구성

-> Code, Data, Stack, Heap

- OS는 3개의 세그먼트를 메모리에 배치하여 Heap과 Stack 사이의 공간을 낭비하지 않도록 하는 것

 

2. 구현

- 가상 주소는 segment id + offset으로 구할 수 있음

  • segment id는 상위 2개의 비트로 구분할 수 있음
  • offset은 하위 12개의 비트로 계산할 수 있음

1) Heap

- EXAMPLE)

  1. Segment ID가 01인 Heap 영역에 가서 Base 값을 찾음 (Base = 26K)
  2. Offset을 계산 (16진수 Hex -> 10진수 Decimal) -> 0x68 = (16^1X6) + (16^0X8) = 104
  3. segmentation fault가 발생했는지 확인 -> Offset값과 Bound 값을 비교 -> Offset < Bound
  4. segmentation fault : 프로그램이 허용되지 않은 메모리 영역에 접근을 시도하거나, 허용되지 않은 방법으로 메모리 영역에 접근을 시도할 경우 발생
  5. Phycal memory 주소를 찾음 -> base + offset -> Segment ID가 01인 Heap 영역에서 Base값과 Offset 값을 더함 -> 26KB + 104

2) Stack

- Stack은 Code, Heap 부분과 다르게 거꾸로 확장되기 때문에 주소 변환을 다르게 해야 함

-> Code, Heap은 sign이 Positive인 반면에 Stack은 sign이 Negative

- Stack 세그먼트의 base 레지스터는 가장 높은 주소에서 시작

  1. Segment ID가 10인 Stack 영역에서 Base 값을 찾음 (Base = 36K)
  2. Offset을 계산 (16진수 Hex -> 10진수 Decimal) -> 0xA00 = (16^2X10) + (16^1X0) + (16^0X0) = 2560Segmentation
  3. fault가 발생하는지 확인 -> Offset값과 Bound 값을 비교 -> Offset < Bound
  4. physical memory 주소를 찾음 -> base - offset -> 36KB - 2560

3) Code Sharing

- 세그먼트는 추가적인 하드웨어 지원을 통해 주소 공간 사이에서 공유될 수 있음

- So, 다중 프로세스는 Code 세그먼트를 공유할 수 있는데, 읽고 실행은 가능하지만 값을 변경할 수는 없음

- 코드가 지정된 영역은 접근 가능하지만, 값을 바꿀 수는 없음

 

3. 문제

1) Context Switching에 대해서는 OS가 어떻게 처리하는가 ?

- 세그먼트 레지스터의 값들을 저장하고 복원해주는 방식으로 처리

 

2) 세그먼트의 수가 증가하거나 감소할 때 OS와 어떻게 상호작용하는가 ?

- 상황) Heap 공간이 부족해서 malloc()에 의해 Heap공간을 늘려야 하는 경우

- 해결 방안) 공간을 늘리기 위해 sbrk() system call을 사용 -> sbrk()는 힙을 늘리거나 줄이는 함수

 

3) physical memory에 여유 공간을 어떻게 관리할 것인가 ?

- 프로세스마다 크기가 모두 다르기 때문에 각 세그먼트의 크기도 모두 다름 

-> 외부 단편화(external gragmentation) 문제 발생

- 외부 단편화 : 외부가 잘게 쪼개진 형태

- 상황) 왼쪽 메모리에서 20KB 크기를 갖는 세그먼트를 할당하려고 함, But, 전체로 보면 24KB 여유 공간이 있지만 16KB, 4KB, 4KB로 인접하지 않은 세그먼트로 20KB 크기를 갖는 공간을 할당받을 수 없음

- 해결 방안) OS는 가운데 그림처럼 Compaction이라는 방법으로 실제 메모리에 있는 기존의 세그먼트를 재배치함

-> 비용이 발생하여 성능이 떨어지는 문제점이 존재

- So, 오른 쪽의 그림처럼 페이징(Paging)이라는 기법을 통해 고정적인 크기의 세그먼트로 외부 단편화를 제거하여 여유 공간을 관리할 수 있음

- But, 페이징 기법 역시 내부 단편화 문제가 존재

- 내부 단편화 : 15KB 요청이 오면 8KB * 2번으로 16KB를 주게 되면 1KB의 안쓰는 공간이 생김 -> 1KB가 내부 단편화의 문제점