리눅스의 각 프로세스는 4GB를 차지한다.
프로세스를 실행하기 위해서는 코드가 반드시 메모리에 있어야 하는데,
어떻게 하면 한정된 메모리에서 여러 프로세스를 실행시킬 수 있도록 메모리 구조를 가져갈 수 있을까?
이때 활용하는 것이 가상 메모리
이다.
가상 메모리를 통해 프로세스간 공간을 분리하면, 프로세스 이슈가 전체 시스템에 영향을 주지 않을 수 있다.
가상 메모리를 통해 메모리 용량 부족
및 프로세스 메모리 영역 간 침범
이슈를 해결할 수 있다.
가상 메모리의 기본 아이디어는, 프로세스는 가상 주소를 사용하고, 데이터를 사용(읽기/쓰기)할 때 물리 주소로 변환해주는 것이다.
가상 주소(virtual address)
프로세스가 참조하는 주소물리 주소(physical address)
실제 메모리 주소그리고 특정 가상 주소가 어느 물리 주소에 매핑 되어있는지 알 수 있어야 한다. 이때 필요한 것이 MMU
이다.
MMU(Memory Management Unit)
CPU에 코드 실행시, 가상 주소 메모리에 접근할 때, 해당 주소를 물리 주소값으로 변환해주는 하드웨어 장치Text(Code) 영역
Data 영역
BSS (Block Started by Symbol) 영역
Data 영역과 BSS 영역을 구분하는 이유
- 초기화된 전역변수는 Data 영역에 저장되어 비휘발성 메모리인 ROM에 저장되는데, 이 부분은 비용이 많이 들어 RAM에 저장될 것과 ROM에 저장될 것을 구분하기 위해, Data 영역과 BSS 영역을 나누어 사용합니다.
Heap
Stack
함수 원형.
void *malloc(size_t size)
기능. 메모리 동적할당
헤더.<stdlib.h>
매개변수.size_t size
메모리의 크기
리턴값.
성공 할당한 메모리의 첫번째 주소
실패 NULLint *arr; arr = (int *)malloc(sizeof(int) * 5); //배열 5개. 총 20바이트로 할당함
함수 원형.
void *calloc(size_t count, size_t size)
기능. malloc과 다른 점은, 할당된 공간의 값을 모두 0으로 초기화 시켜준다.
헤더.<stdlib.h>
매개변수1.size_t count
메모리의 갯수
매개변수2.size_t size
메모리의 크기
리턴값.
성공 할당한 메모리의 첫번째 주소
실패 NULLint *arr; arr = (int *)calloc(5, sizeof(int));
함수 원형.
void *realloc(void *ptr, size_t newsize)
기능. 이미 할당된 메모리의 크기를 변경함
헤더.<stdlib.h>
매개변수1.void *ptr
이미 할당된 포인터 변수
매개변수2.size_t newsize
바꾸고 싶은 메모리의 크기
리턴값.realloc(arr, sizeof(int) * 10); //arr의 메모리를 40바이트로 재할당함
함수 원형.
void free(void *ptr)
기능. 메모리 해제
메모리를 동적할당하면 힙에 공간이 생기는데, 이 공간은 프로그램이 종료될 때까지 존재한다.
따라서 메모리를 할당만 하고 해제를 하지 않으면 사용하지는 않는데 메모리 사용량만 계속 증가해서 메모리 누수가 발생한다.
(회수하지 않으면 프로그램이 실행되는 동안 그 공간은 계속해서 살아있고 이는 메모리의 낭비를 초래하여 성능 부하를 일으킬 수 있음. 따라서 꼭 free를 통해 회수해야함)
헤더.<stdlib.h>
매개변수.void *ptr
해제하고자 하는 메모리의 포인터