-
(3) 프로세스 주소 공간CS 지식/○ OS(Operating System) 2021. 6. 13. 22:54
1. 프로세스 주소란?
1-1) 정의
프로그램이 CPU에 의해 실행되고 난 후
프로세스가 생성되고 메모리에 프로세스 주소 공간이 할당됨
> 프로세스 메모리 공간은 다음과 같이 이루어져 있음
1-2) 메모리 구성
- 코드 Segment : 프로그램 소스 코드 저장
- 데이터 Segment : 전역변수 저장
- 전역변수, static(Java/C) 로 할당되는 영역, 어디서든 접근 가능
- 프로그램 시작과 동시에 할당, 프로그램 종료되어야 메모리에서 소멸
- [예시▼]
더보기#include <stdio.h> int a = 10; // 데이터 영역에 할당 int b = 20; // 데이터 영역에 할당 int main() { ... return 0; }
위와 같은 코드에서 int형 변수 a, b는 프로그램 실행시
main 함수가 호출되기 전에 데이터 영역에 할당된다.그렇기 때문에 프로그램이 종료될 때까지 메모리상에 존재
(전역변수가 프로그램이 종료될 때 까지 존재하는 이유)
출처: https://dsnight.tistory.com/50 [Development Assemble] - 스택 Segment : 함수, 지역변수 저장
- 함수 / block 이용시 생성(이용)되는 지역변수, 매개변수, 함수 리턴값 등이 저장되는 영역
- 후입 선출 구조로 release되며 함수 호출 완료시 스택에서 제거
- [예시▼]더보기#include <stdio.h> void fct1(int); void fct2(int); int a = 10; // 데이터 영역에 할당 int b = 20; // 데이터 영역에 할당 int main() { int i = 100; // 지역변수 i가 스택 영역에 할당 fct1(i); fct2(i); return 0; } void fct1(int c) { int d = 30; // 매개변수 c와 지역변수 d가 스택영역에 할당 } void fct2(int e) { int f = 40; // 매개변수 e와 지역변수 f가 스택영역에 할당 }
main함수와 fct1, fct2라는 함수를 추가하였다.
a, b를 데이터 영역에 할당한 뒤에 main함수를 호출하면서 int형 변수 i는 지역변수로서 스택영역에 할당된다.
그 뒤에 fct1()이라는 함수를 호출하면서 fct1함수의 매개변수인 c와 d가 스택영역에 할당된다.
fct1()이라는 함수호출이 끝나면 c와 d는 스택영역에서 삭제되며,
그 뒤 fct2()라는 함수를 호출하면서 매개변수 e와 지역변수 f가 스택영역에 할당된다.
스택영역은 그 이름그대로 스택의 성질을 띄고있다.
출처: https://dsnight.tistory.com/50 [Development Assemble] - 힙 Segment : 동적변수 (+전역변수)
- 어떤 상황이던 동적으로 메모리 할당이 필요한 경우
※ 컴파일시 init되지 않은 "변수" 등에 의한 의존적인 코드인 경우 메모리가 동적으로 필요해질 수 있기 때문에
heap 영역에 메모리를 할당할 필요성이 있음
- [예시▼]더보기/* CASE 1 */ int main() { // 정상적인 배열선언 int arr[10]; // 비 정상적인 배열선언 // input from user int i = 0; scanf("%d", &i); int arr[i]; return 0; } /* CASE 2 */ int main() { int i = 10; int arr[i]; return 0; }
1) Case 1
배열의 길이를 사용자가 입력한 숫자로 잡아주는 것은 비 정상적인 배열선언이다. 왜 비 정상적일까?
메모리 구조에 대해서 잘 파악하고 있다면 당연한 이야기다.
제일 첫번째 그림을 다시보자, 스택 영역에 할당될 메모리의 크기는 컴파일 타임(컴파일 하는 동안)에 결정된다고 되어있다.
정상적인 배열 선언의 경우 arr이라는 배열의 크기가 40바이트 라는것을 알 수 있다.
하지만 비 정상적인 배열선언의 경우 i의 크기가 4바이트 라는 것을 알 수 는 있으나, arr이라는 배열의 크기는 알 수 없다.
2) Case 2i 라는 변수가 10이기 때문에 arr이라는 배열의 크기가 10이라는 것을 알 수 있지 않을까?
결과는 아니다.
컴파일을 하는 동안 i가 4바이트의 크기라는 것을 알 수는 있으나, 그 값이 10으로 초기화 되었다는 사실은 무시하고 넘어간다. 값이 10으로 초기화 되었다는 사실은 실행되는 동안, 즉 런타임에 결정된다.
그렇기 때문에 컴파일러는 arr의 크기가 40바이트가 된다는 사실을 알 수 없다.
사용자의 요구에 맞게 메모리를 할당해 주기 위해서는(런타임에 메모리 크기를 결정하고 싶을 때) 메모리 동적 할당을 통해 힙 영역에 메모리를 할당해야 한다.
힙 영역 : 할당해야 할 메모리의 크기를 프로그램이 실행되는 동안 결정해야 하는 경우(런 타임때) 유용하게 사용되는 공간
출처: https://dsnight.tistory.com/50 [Development Assemble]
※ 이전 글 비교
https://korshika.tistory.com/132- Code : 코드 자체를 담고 있는 메모리 영역(프로그램 명령)
- Data : 전역변수, 정적변수, 배열 등 (초기화 된 데이터)
- Heap : 동적 할당시 사용 (new(), mallock())
- Stack : 지역변수, 매개변수, 리턴 값 (임시 메모리 영역)
1-3) 메모리 구성 이유
위와 같이 구역을 나눈 이유는 공유 메모리 영역을 늘려 메모리 사용량을 줄이기 위함.
- Code는 어느 시점에서 참조하여도 Process 내부에서는 항상 같은 내용이기 때문에 따로 관리함
- Stack / Data의 분리는 스택 구조의 특성 + 전역 변수의 활용성을 위한 것
또한, 모든 공통적으로 사용되는 함수 등은 따로 data 영역에 포함되도록 전역함수로 설정해주면 메모리를 아낄 수 있음
ex) 함수 블록 안에 다른곳에서 "reuse"될 수 있는 함수의 중복 선언 등은 메모리 낭비
참조
https://gyoogle.dev/blog/computer-science/operating-system/Process%20Address%20Space.html
https://dsnight.tistory.com/50
반응형'CS 지식 > ○ OS(Operating System)' 카테고리의 다른 글
(6) PCB & Context Switching (0) 2021.06.16 (5) System Call (0) 2021.06.15 (4) 인터럽트 (0) 2021.06.15 (2) 프로세스 & 스레드 (0) 2021.06.12 (1) 운영체제란? (0) 2021.06.10