이 글은 공부를 하면서 알게 된 내용들을 기록하는 글 입니다. 오류나 고쳐야 할 사항들이 있다면 지적 부탁드립니다!
✅ 프로세스 주소 공간이란?
이전 포스팅에서 프로세스에 대해 소개하면서, 우리는 프로세스에 대해 1) 실행 중인 프로그램, 2) 운영체제가 자원을 할당하는 단위 라고 이야기했다.
프로그램이 실행되면 메모리를 할당받는데, 프로세스는 이 할당받은 메모리를 관리하기 위해 특정 구조를 만든다.
이것을 프로세스 주소 공간(Process Address Space)이라고 한다.
✅ 프로세스 주소 공간
프로세스 주소 공간은 크게 네 가지의 영역으로 나눌 수 있다.
1️⃣ Text(Code) Segment
프로그램 실행에 필요한 코드들이 CPU가 해석할 수 있는 기계어로 저장되어 있는 공간을 말한다.
프로그램 실행에 필요한 코드들이 있기 때문에 메모리에 한 번 올라가면 수정이 불가능하다.
Read-only 상태로 저장되어 있다. 즉, 정적인(static) 공간이다.
Read-only이기 때문에 다른 process들과도 공유할 수 있다.
같은 프로그램의 프로세스인 경우, 이 Code segment를 공유하여 메모리 사용량을 줄일 수 있다.
2️⃣ Data Segment
- 전역 변수(Global variables)나 Static 변수와 같이 프로그램이 사용할 수 있는 데이터를 저장하는 공간을 말한다.
- 프로그램에 전역/Static 변수를 참조하는 코드가 있다면, 프로그램 컴파일 이후에 이 Data segment를 참조한다.
- 프로그램 시작과 함께 할당되며, 프로그램이 종료되면 소멸한다.
- Data segment에는 .data, .rodata, .bbs 영역으로 나누어진다.
- .data: 전역 변수 또는 Static 변수와 같이 프로그램에 사용되는 데이터를 저장하는 영역
- .rodata: const 같은 상수 키워드로 선언된 변수 혹은 문자열 상수를 저장하는 영역
- .bbs: 초기화되지 않은 변수
3️⃣ Heap Segment
- Runtime 내에 크기가 동적으로 변하는 영역 = 동적으로 할당(dynamically allocated)되는 데이터들을 위한 공간
- 사용자에 의해 메모리 공간이 동적으로 할당되고 해제
- 메모리의 낮은 주소에서 높은 주소의 방향으로 할당
- 프로세스가 실행되는 동안 크기가 변한다. 즉, 크기가 동적이다
4️⃣ Stack Segment
- 함수의 호출과 관계 있는 데이터(ex: 지역 변수, 매개 변수)가 저장되는 영역
- Stack 영역의 값은 함수의 호출과 함께 할당되고, 함수의 호출이 완료되면 함께 없어진다.
즉, 함수의 호출 정보를 저장하는 것인데, 이를 스택 프레임(stack frame)이라고 한다. - 메모리의 높은 주소에서 낮은 주소 방향으로 할당
- Compile time에 Stack 영역이 가질 수 있는 최대 크기가 결정되기 때문에 → 재귀 함수가 너무 깊게 호출되거나, 지역 변수를 너무 많이 가지고 있어 stack 영역을 초과하면 stack overflow 에러가 발생한다.
- Stack 영역이 가질 수 있는 최대 크기는 Compile time에 결정
Stack 영역 내에서 사용하는 크기는 Runtime에 동적으로 변화
runtime 내 내용 변화 | runtime 내 크기 변화 | Thread 공유 여부 | |
Code(Text) segment | X | X | O |
Data segment | X | X | O |
Heap segment | O | O | X |
Stack segment | O | O | X |
✅ Stack과 Heap의 메모리 증가 방향
위의 설명에서 Stack은 메모리의 높은 주소에서 낮은 주소 방향으로 할당하고, Heap은 메모리의 낮은 주소 방향에서 높은 주소 방향으로 할당한다고 이야기 했다.
(다른 아키텍쳐에서 스택의 값을 낮은 주소로 할당하는 경우도 있지만, 대체로 위와 같은 방식을 사용한다.)
왜 이렇게 동작하는걸까?
프로그램을 실행하기 위해서 일정 메모리를 할당받는데, 프로세스는 할당받은 메모리를 최대의 효율로 사용해야 한다.
Stack은 Compile time에 크기가 결정되므로 사용할 수 있는 최대 메모리에서부터 낮은 주소 방향으로 할당하게 하고,
Heap은 Runtime동안 계속해서 크기가 변동되므로, 높은 주소 방향으로 할당하게 한다면 충분한 주소 공간을 확보할 수 있다.
Text(Code) segment와 Data segment는 메모리에 올라갈 때 애초에 크기가 정해져 있으므로, 위와 같은 방식을 사용하면
Heap 영역 + Stack 영역의 공간을 최대로 사용할 수 있을 것이다.
✅ 참고 자료 & 링크
- Memory 구조 (code, data, stack, heap) - velog
- https://velog.io/@klm03025/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%A3%BC%EC%86%8C-%EA%B3%B5%EA%B0%84
- https://inpa.tistory.com/entry/%F0%9F%91%A9%E2%80%8D%F0%9F%92%BB-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%E2%9A%94%EF%B8%8F-%EC%93%B0%EB%A0%88%EB%93%9C-%EC%B0%A8%EC%9D%B4#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98_%EC%9E%90%EC%9B%90_%EA%B5%AC%EC%A1%B0