CPU역할 : 실행할 명령어와 명령어 처리에 필요한 데이터를 메모리에서 읽고 ISA(Instruction Set Architecture, 명령어 집합 구조)에 따라 이를 처리합니다.
그리고 연산의 결과를 다시 메모리에 적재한다.
CPU의 동작과 메모리는 밀접한 관계를 가지는것을 알수있다.
리눅스에서는 프로세스의 메모리르 크게 5가지로 나눈다.
(코드세그먼트, 데이터 세그먼트, BSS 세그먼트, 힙 세그먼트, 스택 세그먼트)
운영체제가 메모리를 용도 별로 나누면 각 용도에 맞게 적절한 권한을 부여할수있다는 장점이 있다. 권한은 읽기, 쓰기, 실행이 존재 CPU는 메모리에 대해 권한이 부여된 행위만 할 수 있다.
코드세그먼트(텍스트세그먼트)는 실행 가능한 기계코드가 위치하는 영역이라고도 불립니다.
프로그램을 동작하려면 코드를 실행할수있어야 하므로 코드 세그먼트에는 읽기권한과 실행권한이 주어진다. 쓰기 권한이 있을경우 공격자가 악의적인 코드를 삽입하기 쉬워지므로 대부분의 현대 운영체제에서는 쓰기권한을 제거한다.
함수가 컴파일 되면 기계 코드로 변환되는데 기계 코드가 코드 세드먼트에 위치하게된다.
함수 : int main() { return 31337; } -> 기계코드 554889e5b8697a00005dc3
데이터 세그먼트에는 컴파일 시점에 값이 정해진 전역변수 및 전역 상수들이 위치합니다. CPU가 이 세그먼트의 데이터를 읽을 수 있어야 하기 때문에 읽기 권한이 부여된다.
데이터 세그먼트
전역변수와 같이 프로그램이 실행되면서 값이 변할수있는 데이터들이 위치하는 세그먼트
로데이터(read-only data) 세그먼트
프로그램이 실행되면서 값이 변하면 안되는 데이터들이 위치하는 세그먼트
int data_num = 31337; // data
char data_rwstr[] = "writable_data"; // data
const char data_rostr[] = "readonly_data"; // rodata
char *str_ptr = "readonly"; // str_ptr은 data, 문자열은 rodata
BSS세그먼트는 컴파일 시점에 값이 정해지지않은 전역변수들이 위치하는 메모리 영역
개발자가 선언만 하고 초기화하지 않은 전역변수 등이 포함.
이세그먼트의 메모리 영역은 프로그램이 시작될 때 모두 0으로 값이 초기화 된다.
읽기, 쓰기 권한이 부여된다.
int bss_data; -> 초기화 되지 않은 변수 BSS세그먼트에 위치한다.
int main() {
printf("%d\n", bss_data); // 0
return 0;
}
스택 세그먼트는 프로세스의 스택이 위치하는 영역
함수의 인자나 지역변수와 같은 임시 변수들이 실행중에 여기에 저장된다.
스택 세그먼트는 스택 프레임이라는 단위로 사용된다.
스택 프레임은 함수가 호출될때 생성되고 반환될때 해제된다.
여기서 우리는 얼마만큼의 스택 프레임이 사용될지 미리 계산하는건 일반적으로 불가능하다. 그래서 운영체제는 프로세스를 시작할때 작은 크기의 스택 세그먼트를 먼저 할당해주고 부족해질때마다 이를 확장해준다. 스택에 대헤서 '아래로 자란다'라는 표현을 종종 사용하는데, 이는 스택이 확장될때, 기존 주소보다 낮은 주소로 확장되기 때문이다.
읽기, 쓰기 권한이 부여된다.
void func() {
int choice = 0;
scanf("%d", &choice);
if (choice)
call_true();
else
call_false();
return 0;
}-> 이 코드에서 지역변수 choice가 스택에 저장된다.
힙 세그먼트는 힙 데이터가 위치하는 세그먼트다
스택과 마찬가지로 실행중에 동적으로 할당될수 있으며, 리눅스에서는 스택 세그먼트와 반대 방향으로 자랍니다.
C언어에서 malloc(), calloc() 등을 호출해서 할당받는 메모리가 이 세그먼트에 위치하게 되며, 일반적으로 읽기와 쓰기권한이 부여된다.
int main() {
int heap_data_ptr =
malloc(sizeof(heap_data_ptr)); // 동적 할당한 힙 영역의 주소를 가리킴
heap_data_ptr = 31337; // 힙 영역에 값을 씀
printf("%d\n", heap_data_ptr); // 힙 영역의 값을 사용함
return 0;
}
요약
ISA : 소프트웨어에서 하드웨어를 중재해주는 역할, 최하위 레벨의 프로그래밍 인터페이스로, 프로세스가 실행할 수 있는 모든 명령어들을 포함한다.(CPU에 존재)
본문의 대부분의 내용은 dreamhack.io에서 공부하실 수 있습니다.