[C] 프로세스와 메모리할당

2021. 1. 8. 16:35프로그래밍 공부/C 공부

프로세스란?

실행파일(.exe)에 있는 명령어를 CPU가 직접 실행할 수 없음. CPU가 이 명령어를 실행하려면 운영체제가 실행파일의 명령어를 읽어서 메모리에 재구성하게됨, 이것을 메모리에 프로세스가 구성된다고 한다.

 

프로세스가 구성되면 CPU는 프로세스에 저장된 명령어를 실행할 수 있음. 

 

프로세스의 구성

프로세스는 코드 세그먼트, 데이터 세그먼트, 스택 세그먼트로 나눠서 구성됩니다.

 

코드 세그먼트 데이터 세그먼트 스택 세그먼트
기계어 명령문 문자열 상수 목록 동적 메모리 할당(Heap)
전역 변수(0으로 초기화) 지역 변수 (Stack)
static 전역 변수 (초기화 x)

 

(1) 코드 세그먼트 : 실행파일이 실행되면 기계어 명령들이 코드 세그먼트에 복사되어 프로그램을 실행

(2) 데이터 세그먼트 : 프로그램의 시작부터 끝까지 사용되는 변수가 보관되는 메모리 영역

(3) 스택 세그먼트 : 프로그램 실행중 임시로 필요한 데이터를 저장하는데 사용되는 메모리 영역

 

메모리 할당 방식 : 정적 메모리 할당

C 소스코드의 변수 선언부분을 기계어로 번역할 때, 데이터 세그먼트나 스택 세그먼트에 해당 변수를 저장할 메모리 공간을 할당하는 것을 말함. 

컴파일 과정에서 정해지기 때문에 정적 메모리 할당된 메모리 크기나 개수에 변화를 주기 위해서는 C 소스코드를 변경하고 다시 컴파일 해야함.

 

정적으로 할당된 메모리 관리법

전역변수는 프로그램 실행시 한번 메모리 주소가 할당되면 변하지 않기 때문에 전역변수의 메모리 위치를 기억하는 공간이 따로 필요하지 않다. 하지만 지역변수는 함수 호출에 따라 메모리 할당과 해제가 반복되기 때문에 지역변수의 현재 주소를 기억하기 위한 추가 메모리가 필요하다. 이는 메모리 낭비를 초래한다.

 

하나의 함수 안에서 변수들을 메모리 그룹으로 관리할 수 있는데

void main()
{
    int a, b, c, d ;
    a = 5 ; b = 3;
    
}

func함수는 총 16바이트의 지역변수를 선언하고, 이들을 각각 기억하기 위해서는 또 16바이트의 메모리가 필요할 것이다.

하지만 만약 a를 시작점으로 하여  a+0, a+4, a+8, a+12 식으로 주소를 기억한다면 지역변수의 주소를 기억하기 위한 메모리 용량이 크게 줄지 않을까? 즉, 지역변수의 시작점과 끝점만 알고 있으면 된다는 것이다.

 

스택

이러한 메모리 관리에서 시작점을 base pointer(BP) , 끝점을 stack pointer(SP) 라고 한다면, 함수가 호출됐을때 그 지역변수를 쌓는식으로 저장된다고 이해할 수 있을 것이다. BP부터 시작해서 SP로 변수가 할당되고, 새로운 변수가 들어온다면 SP위에 쌓이는 식이다. 

변수 주소
d SP(BP-12)
c BP-8
b BP-4
a BP

이러한 스택의 구조는 컴파일 과정에서 결정이 되는데, 이를 통해 정적 메모리 할당이라는 것을 알 수 있다. 

 

스택 방식은 BP를 기준으로 -4, -8 이동하는 식으로 지역변수를 호출, 변경할 수 있기 때문에 효율적이다. 그렇지 않다면 변수 b를 변경하기 위해서는 a,b,c,d 쌓인 스택에서 d,c를 레지스터로 옮겼다가 b를 변경하고 다시 c,d 순으로 스택에 쌓는 작업을 반복해야한다. 

 

여러 함수가 호출되는 과정은 스택에서 어떻게 보일까?

#include <stdio.h>

void func1(int var1,int var2);
void func2(int var1,int var2);

void main ()
{
	int a,b,c,d;
	func1(a,b);
	func2(c,d);
}

void func1(int var1,int var2)
{
	int e,f
	e += var1;
    f += var2;
    func2(e,f);
}

void func2(int var1,int var2)
{
	int g,h,result ;
	g += var1;
    h += var2;
    result = g + h;
	return result;
}

위의 경우 아래와 같은 스택이 구성된다.

변수 영역
result func2 SP
h  
g BP
&func1 BP

func1

func1 IP
f
e
&main BP

manin

main IP
d
c
b
a

IP : instruction pointer, 현재 실행위치를 기억하는 포인터다.

 

(1) main의 지역변수는 main의 메모리 영역에 스택된다.

(2) func1이 호출된 뒤 다시 값을 main에 반환해야하는데, 만약 main의 IP와 BP주소가 없다면 반환되지 않을 것이다. 따라서 main의 스택 끝부분에는 IP와 BP가 쌓이고 그 다음 func1의 BP가 시작된다. 

(3) func1도 같은 식으로 IP와 &BP로 마무리된다.

(4) func2가 실행되고 종료될때에는 func2의 BP아래(func2 BP +4)가 실행되고, func1로 돌아온다.

(5) 다시 func1이 실행되고 종료될때 같은 방식으로 main으로 돌아오고, main 실행이 완료되면 모든 메모리가 비워진다.

 

 

'프로그래밍 공부 > C 공부' 카테고리의 다른 글

[C] 동적메모리 사용하기  (0) 2021.01.10
[C] 동적 메모리 할당 및 해제  (0) 2021.01.08
[C] 배열과 포인터 2  (0) 2021.01.08
[C] 배열과 포인터  (0) 2021.01.07
[C] scanf 함수 2  (0) 2021.01.07