개요
세그멘테이션(Segmentation)은 운영체제에서 메모리 관리를 수행하는 기법 중 하나로, 프로그램을 논리적으로 의미 있는 단위인 세그먼트(Segment)로 나누어 메모리에 할당하는 방식이다. 이 기법은 프로그램의 구조를 반영하여 메모리를 효율적으로 관리하고, 보호 및 공유 기능을 강화하는 데 목적이 있다. 세그멘테이션은 연속 메모리 할당 방식의 일종으로, 고정 분할(fixed partitioning)이나 가변 분할(variable partitioning)과 달리 프로그램의 논리적 구조를 기반으로 한다.
세그멘테이션은 1960년대 후반부터 본격적으로 연구되기 시작했으며, 특히 MULTICS(Multiplexed Information and Computing Service) 운영체제에서 처음으로 실용화되었다. 이후 일부 시스템에서 사용되었으나, 페이징(Paging) 기법에 비해 조각화(fragmentation) 문제와 주소 변환 오버헤드 등의 한계로 인해 현대 운영체제에서는 주로 페이징과 결합된 형태로 사용된다.
세그멘테이션의 원리
1. 세그먼트의 정의
세그멘테이션은 프로그램을 다음과 같은 논리적 단위로 분할한다:
- 코드 세그먼트(Text Segment): 실행 코드(명령어)를 포함.
- 데이터 세그먼트(Data Segment): 전역 변수 및 정적 변수 저장.
- 스택 세그먼트(Stack Segment): 함수 호출 시 지역 변수 및 반환 주소 저장.
- 힙 세그먼트(Heap Segment): 동적 메모리 할당(malloc, new 등)에 사용.
각 세그먼트는 독립적인 주소 공간을 가지며, 고유한 기저 주소(Base Address)와 길이(Limit)를 갖는다.
2. 논리 주소 구조
세그멘테이션에서는 논리 주소가 두 부분으로 구성된다:
예를 들어, 논리 주소 ⟨3, 50⟩는 세그먼트 3의 50번지 오프셋을 의미한다. 운영체제는 이 정보를 바탕으로 물리 주소를 계산한다.
3. 주소 변환 과정
주소 변환은 세그먼트 테이블(Segment Table)을 통해 이루어진다. 각 세그먼트는 테이블 내에 엔트리를 가지며, 다음 정보를 포함한다:
| 필드 |
설명 |
| 기저 주소 (Base) |
해당 세그먼트가 물리 메모리에 위치한 시작 주소 |
| 길이 (Limit) |
세그먼트의 크기 (바이트 단위) |
| 유효 비트 (Valid) |
세그먼트가 메모리에 존재하는지 여부 |
| 접근 권한 (Access Rights) |
읽기, 쓰기, 실행 권한 정보 |
주소 변환 절차:
1. CPU가 논리 주소 ⟨s, d⟩를 생성 (s: 세그먼트 번호, d: 오프셋).
2. 세그먼트 테이블에서 s번 엔트리를 참조.
3. 오프셋 d가 Limit보다 작은지 확인 (경계 검사).
4. 유효성 및 권한 검사 수행.
5. 물리 주소 = Base + d 계산.
이 과정에서 오프셋이 Limit를 초과하면 세그멘테이션 폴트(Segmentation Fault)가 발생한다.
세그멘테이션의 장점
1. 프로그램 구조 반영
세그멘테이션은 프로그램의 논리적 구조(함수, 배열, 스택 등)를 자연스럽게 반영하므로, 메모리 관리가 직관적이다.
2. 메모리 보호
각 세그먼트에 접근 권한을 설정함으로써 코드 세그먼트는 실행 전용, 데이터 세그먼트는 쓰기 전용 등으로 보호할 수 있다. 이는 버퍼 오버플로우 등 보안 취약점을 일부 완화한다.
3. 메모리 공유 용이
특정 세그먼트(예: 공용 라이브러리)를 여러 프로세스가 공유할 수 있다. 예를 들어, libc 코드 세그먼트를 여러 프로세스가 동시에 참조 가능.
세그멘테이션의 단점
1. 외부 조각화 (External Fragmentation)
세그먼트는 가변 크기로 할당되므로, 메모리 해제 후 남은 빈 공간이 연속되지 않아 큰 세그먼트를 할당할 수 없는 문제가 발생한다. 이는 메모리 압축(Compaction)으로 완화 가능하지만, 성능 저하를 유발한다.
2. 주소 변환 오버헤드
세그먼트 테이블 접근이 필요하므로, 매번 메모리 참조 시 추가적인 메모리 접근이 발생한다. 이를 완화하기 위해 세그먼트 테이블 캐시(TLB와 유사한 구조)를 사용할 수 있다.
3. 관리 복잡성
세그먼트의 크기, 위치, 생명 주기를 관리하는 것이 페이징에 비해 복잡하며, 운영체제 구현 난이도가 높다.
세그멘테이션과 페이징의 비교
| 항목 |
세그멘테이션 |
페이징 |
| 단위 |
논리적 단위 (의미 있음) |
고정 크기 블록 (의미 없음) |
| 조각화 |
외부 조각화 발생 |
내부 조각화 발생 |
| 주소 변환 |
세그먼트 테이블 사용 |
페이지 테이블 사용 |
| 보호 및 공유 |
용이 |
제한적 |
| 구현 복잡도 |
높음 |
상대적으로 낮음 |
현대 운영체제에서의 활용
순수한 세그멘테이션은 현대 운영체제에서 거의 사용되지 않지만, 세그멘테이션과 페이징의 하이브리드 방식은 여전히 중요하다. 예를 들어:
- x86 아키텍처는 하드웨어 수준에서 세그멘테이션을 지원하지만, 대부분의 현대 OS(리눅스, 윈도우)는 보호 모드에서 평면 주소 공간(Flat Memory Model)을 사용하며, 세그멘테이션은 최소한으로 활용한다.
- 일부 실시간 시스템이나 임베디드 시스템에서는 여전히 세그멘테이션 기반 메모리 관리가 적용되기도 한다.
참고 자료
- Silberschatz, A., Galvin, P. B., & Gagne, G. (2018). Operating System Concepts (10th ed.). Wiley.
- Tanenbaum, A. S., & Bos, H. (2015). Modern Operating Systems (4th ed.). Pearson.
- Intel 64 and IA-32 Architectures Software Developer’s Manual
관련 문서: 페이징, 가상 메모리, 메모리 보호, 조각화
# 세그멘테이션
## 개요
**세그멘테이션**(Segmentation)은 운영체제에서 메모리 관리를 수행하는 기법 중 하나로, 프로그램을 논리적으로 의미 있는 단위인 **세그먼트**(Segment)로 나누어 메모리에 할당하는 방식이다. 이 기법은 프로그램의 구조를 반영하여 메모리를 효율적으로 관리하고, 보호 및 공유 기능을 강화하는 데 목적이 있다. 세그멘테이션은 연속 메모리 할당 방식의 일종으로, 고정 분할(fixed partitioning)이나 가변 분할(variable partitioning)과 달리 프로그램의 논리적 구조를 기반으로 한다.
세그멘테이션은 1960년대 후반부터 본격적으로 연구되기 시작했으며, 특히 **MULTICS**(Multiplexed Information and Computing Service) 운영체제에서 처음으로 실용화되었다. 이후 일부 시스템에서 사용되었으나, 페이징(Paging) 기법에 비해 조각화(fragmentation) 문제와 주소 변환 오버헤드 등의 한계로 인해 현대 운영체제에서는 주로 페이징과 결합된 형태로 사용된다.
---
## 세그멘테이션의 원리
### 1. 세그먼트의 정의
세그멘테이션은 프로그램을 다음과 같은 논리적 단위로 분할한다:
- **코드 세그먼트**(Text Segment): 실행 코드(명령어)를 포함.
- **데이터 세그먼트**(Data Segment): 전역 변수 및 정적 변수 저장.
- **스택 세그먼트**(Stack Segment): 함수 호출 시 지역 변수 및 반환 주소 저장.
- **힙 세그먼트**(Heap Segment): 동적 메모리 할당(malloc, new 등)에 사용.
각 세그먼트는 독립적인 주소 공간을 가지며, 고유한 **기저 주소**(Base Address)와 **길이**(Limit)를 갖는다.
### 2. 논리 주소 구조
세그멘테이션에서는 논리 주소가 두 부분으로 구성된다:
- **세그먼트 번호**(Segment Number)
- **세그먼트 내 오프셋**(Offset)
예를 들어, 논리 주소 `⟨3, 50⟩`는 세그먼트 3의 50번지 오프셋을 의미한다. 운영체제는 이 정보를 바탕으로 물리 주소를 계산한다.
### 3. 주소 변환 과정
주소 변환은 **세그먼트 테이블**(Segment Table)을 통해 이루어진다. 각 세그먼트는 테이블 내에 엔트리를 가지며, 다음 정보를 포함한다:
| 필드 | 설명 |
|------|------|
| 기저 주소 (Base) | 해당 세그먼트가 물리 메모리에 위치한 시작 주소 |
| 길이 (Limit) | 세그먼트의 크기 (바이트 단위) |
| 유효 비트 (Valid) | 세그먼트가 메모리에 존재하는지 여부 |
| 접근 권한 (Access Rights) | 읽기, 쓰기, 실행 권한 정보 |
주소 변환 절차:
1. CPU가 논리 주소 `⟨s, d⟩`를 생성 (s: 세그먼트 번호, d: 오프셋).
2. 세그먼트 테이블에서 s번 엔트리를 참조.
3. 오프셋 d가 Limit보다 작은지 확인 (경계 검사).
4. 유효성 및 권한 검사 수행.
5. 물리 주소 = Base + d 계산.
이 과정에서 오프셋이 Limit를 초과하면 **세그멘테이션 폴트**(Segmentation Fault)가 발생한다.
---
## 세그멘테이션의 장점
### 1. 프로그램 구조 반영
세그멘테이션은 프로그램의 논리적 구조(함수, 배열, 스택 등)를 자연스럽게 반영하므로, 메모리 관리가 직관적이다.
### 2. 메모리 보호
각 세그먼트에 접근 권한을 설정함으로써 코드 세그먼트는 실행 전용, 데이터 세그먼트는 쓰기 전용 등으로 보호할 수 있다. 이는 버퍼 오버플로우 등 보안 취약점을 일부 완화한다.
### 3. 메모리 공유 용이
특정 세그먼트(예: 공용 라이브러리)를 여러 프로세스가 공유할 수 있다. 예를 들어, `libc` 코드 세그먼트를 여러 프로세스가 동시에 참조 가능.
---
## 세그멘테이션의 단점
### 1. 외부 조각화 (External Fragmentation)
세그먼트는 가변 크기로 할당되므로, 메모리 해제 후 남은 빈 공간이 연속되지 않아 큰 세그먼트를 할당할 수 없는 문제가 발생한다. 이는 **메모리 압축**(Compaction)으로 완화 가능하지만, 성능 저하를 유발한다.
### 2. 주소 변환 오버헤드
세그먼트 테이블 접근이 필요하므로, 매번 메모리 참조 시 추가적인 메모리 접근이 발생한다. 이를 완화하기 위해 **세그먼트 테이블 캐시**(TLB와 유사한 구조)를 사용할 수 있다.
### 3. 관리 복잡성
세그먼트의 크기, 위치, 생명 주기를 관리하는 것이 페이징에 비해 복잡하며, 운영체제 구현 난이도가 높다.
---
## 세그멘테이션과 페이징의 비교
| 항목 | 세그멘테이션 | 페이징 |
|------|---------------|--------|
| 단위 | 논리적 단위 (의미 있음) | 고정 크기 블록 (의미 없음) |
| 조각화 | 외부 조각화 발생 | 내부 조각화 발생 |
| 주소 변환 | 세그먼트 테이블 사용 | 페이지 테이블 사용 |
| 보호 및 공유 | 용이 | 제한적 |
| 구현 복잡도 | 높음 | 상대적으로 낮음 |
---
## 현대 운영체제에서의 활용
순수한 세그멘테이션은 현대 운영체제에서 거의 사용되지 않지만, **세그멘테이션과 페이징의 하이브리드 방식**은 여전히 중요하다. 예를 들어:
- **x86 아키텍처**는 하드웨어 수준에서 세그멘테이션을 지원하지만, 대부분의 현대 OS(리눅스, 윈도우)는 보호 모드에서 **평면 주소 공간**(Flat Memory Model)을 사용하며, 세그멘테이션은 최소한으로 활용한다.
- 일부 실시간 시스템이나 임베디드 시스템에서는 여전히 세그멘테이션 기반 메모리 관리가 적용되기도 한다.
---
## 참고 자료
- Silberschatz, A., Galvin, P. B., & Gagne, G. (2018). *Operating System Concepts* (10th ed.). Wiley.
- Tanenbaum, A. S., & Bos, H. (2015). *Modern Operating Systems* (4th ed.). Pearson.
- Intel 64 and IA-32 Architectures Software Developer’s Manual
> **관련 문서**: [페이징](/wiki/페이징), [가상 메모리](/wiki/가상_메모리), [메모리 보호](/wiki/메모리_보호), [조각화](/wiki/조각화)