메모리 가상화

코승호딩·2022년 10월 19일
0

운영체제

목록 보기
5/10
post-thumbnail
  • OS는 물리 메모리를 가상화한다.
  • OS는 모든 프로세스들에게 별도의 가상의 주소 공간을 제공한다.
  • 각각의 프로세스들은 자기가 전체 메모리를 다 사용하고 있는 것처럼 보인다.
    물리 메모리 만큼의 용량을 사용한다.
    다른 프로세스가 사용하는 공간이 존재하지 않는다.

그렇다면 이러한 메모리 가상화의 이점은 무엇일까?

  • 이점 1 : 프로그래밍이 간단해진다.
  • 이점 2 : 시간과 공간 측면에서의 메모리 효율성
  • 이점 3 : OS뿐만 아니라 다른 프로세스도 분리
    다른 프로세서의 잘못된 접근으로부터 보호 -> 한 프로세서가 에러가 났을 때 동반자살하지 않는다.

메모리 가상화 참 맛있다.


📌초기 운영체제


메모리에서 프로세서 하나만 실행되었다.
효율성이 참 별로였다.


📌멀티 프로그래밍과 시분할

컴퓨터는 시분할을 통해 여러 개의 프로세스를 동시에 실행할 수 있다. -> CPU 가상화
메모리 가상화 또한 실제로는 메모리가 한 개 뿐이지만 프로세스들은 마치 여러 개의 메모리가 있다고 착각하게 만드는 것이다.

메모리 가상화를 하게 되면 위의 사진과 같이 한 메모리에 여러 개의 프로세스를 로딩할 수 있다.
하나를 계속 실행하다가 운영체제가 호출(I/O 요청)되면 메모리에 있는 다른 프로세스로 교환한다.
이를 통해 CPU는 효율이 증대하게 된다. -> I/O 요청하고 기다릴 때, 다른 프로세스를 실행

그러나! 이렇게 여러 프로세스들을 한 번에 메모리에 존재하게 되면 보호 문제가 발생한다.
예를 들어 위 사진의 C프로세서가 B프로세서의 메모리 공간을 침입해서 데이터를 조작하게 되면 문제가 발생한다. Segmentation Fault
또한 물귀신 마냥 하나가 버그를 일으켰을 때 전체가 망가질 수 있고 그래서 나온 것이 메모리 가상화이다.


📌주소 공간

OS가 실제 물리 메모리를 추상화하여 프로세스들에게 나눠준다.
이렇게 추상화한 메모리를 주소 공간(address space)이라고 한다
각 프로세스는 자신의 주소 공간에만 접근해야 한다.

주소 공간 전부를 실행 중인 프로세스가 차지한다.
마치 전체를 나혼자 쓰는 기분?
주소 공간은 프로그램 코드, 힙, 스택 등으로 이뤄져 있다.

  • Code : 명령어가 있는 곳
  • Heap : 동적 할당 메모리 영역
  • Stack : 복귀 주소와 매개 변수, 리턴 값 저장, 실행 중인 함수의 지역 변수 포함

실행 중인 프로그램의 모든 주소는 가상주소이다.


📌메모리 가상화의 목표

  • 투명성
    프로그램 작성 시 가상 메모리를 신경쓰지 않고 자유롭게 작성 가능
  • 효율성
    시간 : 빠른 할당과 해제, 하드웨어의 빠른 가상주소 변환
    공간 : 메모리 공간의 낭비(fragmentation) 방지
    HW 도움 필요 : TLB, 가상 메모리 테이블
  • 보호
    다른 프로세스의 주소 공간에 접근 하는 경우 방지
    고립을 사용하여 옆 메모리가 안보이도록

📌메모리 API

메모리 할당 인터페이스로 malloc 이나 new 사용 시 일정한 메모리를 할당 받을 수 있다.
스택의 경우 스택 메모리 공간을 확보 후 함수의 호출이 끝나면 알아서 메모리에서 해제가 된다.
그러나 heap 영역을 할당받기 위해서는 개발자가 직접 메모리를 할당 해줘야 한다.

  • malloc()
    heap에 요구되는 메모리 크기를 주면 해당 메모리 포인터를 반환한다.
    만약 실패한다면 널 포인터를 반환하게 된다.
int *a = malloc(10 * sizeof(int));

malloc을 통해 할당을 받을 때 sizeof를 통해서 메모리 할당을 받았는데 이때 문제점이 있다.
32비트 컴퓨터와 64비트 컴퓨터에서 각각 다르게 작동하는 것이다.
이러한 문제는

int a[10];

이렇게 해결할 수 있는데, C에서는 문자열을 마지막에 항상 null을 가지게 되며 이 때문에 sizeof가 엉뚱한 값을 줄 수 있다.

메모리 할당 과정으로 스택에 로컬 변수 포인터 pi가 멀리 너머의 heap영역의 메모리를 할당 받는다.


  • free()
    할당 받은 메모리를 해제하는 함수이다.


free 과정이다. heap 영역이 늘어난다.


📌메모리 할당 관련 문제

메모리를 할당과 해제에 관련하여 잘못 사용하면 문제가 되는 점이 몇가지 있다.

메모리 할당 잊어버리기

호출 전 메모리가 할당되지 않은 경우 복사할 변수에 메모리를 할당하지 않았기 때문에 세그멘테이션 폴트를 발생키기고 죽는다.

메모리를 부족하게 할당 받기

사용할 메모리보다 더 적은 메모리를 할당받게 되면 운이 좋다면 오동작 하지 않을 수 있지만 다른 메모리를 건들 수 있다. 넉넉히 할당!

할당받은 메모리 초기화하지 않기

메모리를 할당 받았는데 값을 쓰지 않고 읽기만 하면 안된다. heap 메모리에 이상한 데이터가 있을 수 있기 때문에 할당 하면 써라!

메모리 해제하지 않기

메모리를 할당만 받고 해제하지 않으면 그만큼 낭비가 되고 메모리에 공간이 부족하면 프로세서가 종료된다. 메모리 누수!!

Dangling Pointer

사용이 끝나기 전에 메모리 해제한 경우, 프로그램이 사용중이 아닌 메모리에 도달할 수있다. 접근 오류!!

Double Free

반복적으로 메모리 해제한 경우 하지마라!


📌추가 API

  • calloc()
    힙에서 메모리를 할당하고 0으로 초기화 한다.
    -> 할당 받고 메모리를 안쓴 경우 오류를 막을 수 있지만 cpu를 사용하여 공짜가 아니다. 따라서 속도가 저하되고 잘 안쓴다.
  • realloc()
    현재 할당된 부분보다 더 큰 부분을 할당받고 싶을 때 사용한다. 운에 맞겨야 해서 잘 안쓴다.

📌실제 시스템 콜

운영체제가 내부 자료구조를 사용하는데 프로그래머가 사용하면 충돌이 날 수 있어 아예 쓰면 안된다.

운영체제의 개입은 오버헤드가 일어나며 공짜가 아니다
따라서 모든 것을 운영체제게 담당하면 느려지며 하드웨어를 사용해야 한다
그래서 주소변환 같은 거를 하드웨어가 담당한다.

운영체제는 어디서부터 어디까지 무엇을 하는지 관리, 어떻게 변환해야 하는지 등
재배치 : 멀티 프로그래밍으로 인해 주소가 여기저기 있다.

profile
코딩 초보 승호입니다.

0개의 댓글