그렇다면 이러한 메모리 가상화의 이점은 무엇일까?
메모리 가상화 참 맛있다.
메모리에서 프로세서 하나만 실행되었다.
효율성이 참 별로였다.
컴퓨터는 시분할을 통해 여러 개의 프로세스를 동시에 실행할 수 있다. -> CPU 가상화
메모리 가상화 또한 실제로는 메모리가 한 개 뿐이지만 프로세스들은 마치 여러 개의 메모리가 있다고 착각하게 만드는 것이다.
메모리 가상화를 하게 되면 위의 사진과 같이 한 메모리에 여러 개의 프로세스를 로딩할 수 있다.
하나를 계속 실행하다가 운영체제가 호출(I/O 요청)되면 메모리에 있는 다른 프로세스로 교환한다.
이를 통해 CPU는 효율이 증대하게 된다. -> I/O 요청하고 기다릴 때, 다른 프로세스를 실행
그러나! 이렇게 여러 프로세스들을 한 번에 메모리에 존재하게 되면 보호 문제가 발생한다.
예를 들어 위 사진의 C프로세서가 B프로세서의 메모리 공간을 침입해서 데이터를 조작하게 되면 문제가 발생한다. Segmentation Fault
또한 물귀신 마냥 하나가 버그를 일으켰을 때 전체가 망가질 수 있고 그래서 나온 것이 메모리 가상화이다.
OS가 실제 물리 메모리를 추상화하여 프로세스들에게 나눠준다.
이렇게 추상화한 메모리를 주소 공간(address space)이라고 한다
각 프로세스는 자신의 주소 공간에만 접근해야 한다.
주소 공간 전부를 실행 중인 프로세스가 차지한다.
마치 전체를 나혼자 쓰는 기분?
주소 공간은 프로그램 코드, 힙, 스택 등으로 이뤄져 있다.
실행 중인 프로그램의 모든 주소는 가상주소이다.
메모리 할당 인터페이스로 malloc 이나 new 사용 시 일정한 메모리를 할당 받을 수 있다.
스택의 경우 스택 메모리 공간을 확보 후 함수의 호출이 끝나면 알아서 메모리에서 해제가 된다.
그러나 heap 영역을 할당받기 위해서는 개발자가 직접 메모리를 할당 해줘야 한다.
int *a = malloc(10 * sizeof(int));
malloc을 통해 할당을 받을 때 sizeof를 통해서 메모리 할당을 받았는데 이때 문제점이 있다.
32비트 컴퓨터와 64비트 컴퓨터에서 각각 다르게 작동하는 것이다.
이러한 문제는
int a[10];
이렇게 해결할 수 있는데, C에서는 문자열을 마지막에 항상 null을 가지게 되며 이 때문에 sizeof가 엉뚱한 값을 줄 수 있다.
메모리 할당 과정으로 스택에 로컬 변수 포인터 pi가 멀리 너머의 heap영역의 메모리를 할당 받는다.
free 과정이다. heap 영역이 늘어난다.
메모리를 할당과 해제에 관련하여 잘못 사용하면 문제가 되는 점이 몇가지 있다.
호출 전 메모리가 할당되지 않은 경우 복사할 변수에 메모리를 할당하지 않았기 때문에 세그멘테이션 폴트를 발생키기고 죽는다.
사용할 메모리보다 더 적은 메모리를 할당받게 되면 운이 좋다면 오동작 하지 않을 수 있지만 다른 메모리를 건들 수 있다. 넉넉히 할당!
메모리를 할당 받았는데 값을 쓰지 않고 읽기만 하면 안된다. heap 메모리에 이상한 데이터가 있을 수 있기 때문에 할당 하면 써라!
메모리를 할당만 받고 해제하지 않으면 그만큼 낭비가 되고 메모리에 공간이 부족하면 프로세서가 종료된다. 메모리 누수!!
사용이 끝나기 전에 메모리 해제한 경우, 프로그램이 사용중이 아닌 메모리에 도달할 수있다. 접근 오류!!
반복적으로 메모리 해제한 경우 하지마라!
운영체제가 내부 자료구조를 사용하는데 프로그래머가 사용하면 충돌이 날 수 있어 아예 쓰면 안된다.
운영체제의 개입은 오버헤드가 일어나며 공짜가 아니다
따라서 모든 것을 운영체제게 담당하면 느려지며 하드웨어를 사용해야 한다
그래서 주소변환 같은 거를 하드웨어가 담당한다.
운영체제는 어디서부터 어디까지 무엇을 하는지 관리, 어떻게 변환해야 하는지 등
재배치 : 멀티 프로그래밍으로 인해 주소가 여기저기 있다.