프로세스와 컨텍스트 스위칭
- 스케줄러에 의해 어떤 프로세스에서 다른 프로세스로 바뀌는 과정을 컨텍스트 스위칭이라고 한다.
- 이 컨텍스트 스위칭을 이해하기 위해서는 프로세스의 구조에 대한 이해가 바탕이 되어야 한다.
- 지금부터 프로세스의 구조에 대해서 알아보겠다.
1. 프로세스 구조
- 먼저 다음과 같은 프로그램 코드가 있다고 해보자.
def func(a, b):
return print(a+b)
c = 0
c = func(1,2)
print(c)
- 이 코드가 실행되면 컴파일이라는 단계를 거친다.
- 컴파일은 기계어 또는 바이너리라는 0과 1로 된 언어로써, 컴퓨터가 이해할 수 있도록 번역되는 과정을 의미한다.
- 프로세스가 실행된다는 것은 코드가 컴파일 되는 과정을 포함한다.
- 그렇다면 컴파일된 코드는 어디로 가는걸까? 프로세스 메모리로 가게 된다.
2. 프로세스 구조 / 프로세스 메모리 구조
- 프로세스에는 크게 4가지(Code, Data, Stack, Heap)의 메모리 공간이 존재한다.
a) Code 영역(=text 영역)
- 개발자가 작성한 소스코드가 들아가는 부분이다.
- 텍스트(Text) 영역이라고 부르기도 한다.
- 실행 파일을 구성하는 명령어(함수, 제어문, 상수 등)가 올라가는 메모리 영역이다.
b) Data 영역
- 전역변수와 static 변수가 할당되는 영역이다.
- 프로그램의 시작과 동시에 할당되고, 프로그램이 종료되어야 메모리가 소멸되는 영역이다
c) Stack 영역
- 프로그램이 자동으로 사용하는 임시 메모리 영역이다.
- 함수 호출 시 생성되는 지역변수와 매개변수가 저장되는 영역이다.
- 함수 호출이 완료되면 자동으로 소멸된다.
d) Heap 영역
- 프로그래머가 직접 할당/해제하는 메모리 영역이다.
- Java에서는 가비지 컬렉터가 자동으로 해제하는 영역이다.
- Heap 영역의 메모리를 할당하는 것을 동적 할당(Dynamic Memory Allocation)이라고 부른다.
- C 언어에서는 malloc() 이라는 함수를 사용하여 동적 할당을 할 수 있다.
3. 프로세스 메모리 할당 예시(파이썬)
- 위에서 보았던 파이썬 코드가 메모리에는 어떻게 할당되는지 알아보자.
def func(a, b):
return print(a+b)
c = 0
c = func(1,2)
print(c)
프로세스 |
|
Stack (함수호출, 임시메모리) |
0050h (return address) |
a = 1 | |
b = 2 | |
Heap (프로그래머가 할당) | |
Data (전역/static변수) | c = 0 |
Code |
def func(a, b): |
return print(a+b) | |
c = 0 | |
c = func(1,2) *리턴 어드레스 반환 | |
print(c) | |
추가설명 | * 각 함수들은 실행이 완료되면 return address라는 것을 반환한다. 여기서는 임의로 005h라는 return address를 반환한다고 하자. |
1) Code 영역에 소스코드가 올라간다.
2) 소스코드를 읽기 시작한다.
3) 전역변수(c = 0)가 Data영역에 저장된다.
4) 함수 실행이 완료되면 return address(005h)를 반환하고, 이를 Stack 영역에 저장한다.
5) 함수의 인자 또는 매개변수(a = 1, b = 2)를 Stack 영역에 저장한다.
6) 함수 실행이 완료되면, return address를 기반으로 코드영역으로 돌아가서 다음 실행할 코드를 확인한다.
7) print(c)를 실행한다.
4. 프로세스 메모리 할당 예시( C언어)
- 예시 코드는 다음과 같다.
void meaningless (int data)
{
int temp;
temp = data;
}
int main (int argc, char **argv)
{
meaningless (1);
return 0;
}
- C언어로 작성된 예시 코드는 메모리가 어떻게 할당 될까?
프로세스 |
||
Stack (함수호출, 임시메모리) |
return address: 0006h | |
argc | ||
argv | ||
reuturn address: 0005h | ||
return address: 0004h | ||
data = 1 | ||
temp = 1 | ||
Heap (프로그래머가 할당) | 동적할당 없음 | |
Data (전역/static변수) | 전역변수 없음 | |
Code |
void meaningless (int data) |
0000h |
{ | ||
int temp; | 0001h | |
temp = data; | 0002h | |
} | ||
int main (int argc, char **argv) | 0003h | |
{ | ||
meaningless (1); | 0004h | |
return 0; | 0005h | |
} | ||
main 함수 종료 후 처리과정 | 0006h |
- 위의 표를 통해 메모리가 할당과정을 부분적으로 표현했다.
- 여기서 한가지 특징이 발견되는데, 바로 스택 메모리는 return address의 값이 낮을수록 아래쪽에 높을수록 위쪽에 위치한다는 것이다. 이유가 무엇일까? 스택 메모리는 Stack 자료구조를 사용하기 때문이다.
- 반대로, Heap은 return address의 값이 낮은것이 위쪽으로 높은것이 아래쪽에 위치하게 된다.
'컴퓨터공학기초 개념 > 운영체제' 카테고리의 다른 글
15. 프로세스 구조(3) - Heap (0) | 2021.04.14 |
---|---|
14. 프로세스 구조(2) - Stack (0) | 2021.04.13 |
12. 인터럽트 동작방식 (0) | 2021.04.08 |
11. 인터럽트의 종류 (0) | 2021.04.07 |
10. 인터럽트란? (0) | 2021.04.06 |
댓글