주소 변환

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

운영체제

목록 보기
6/10
post-thumbnail

📌효율적인 메모리 가상화

CPU 가상화에서 제한적 직접 실행이란 프로그램을 하드웨어에서 직접 실행하도록 하는데 특정 시점(시스템 콜, 타이머 인터럽트)에 OS가 프로그램의 실행에 관여하는 방식이라고 설명하였다.
이는 OS의 관리를 통해 CPU를 효율적으로 제어할 수 있는 가상화 방법이었다.
메모리 가상화 또한 마찬가지로 하드웨어의 지원을 받으며 OS가 제어하는 방법으로 구현이 가능하다
이러한 LDE방식에 메모리 가상화를 도입할 수 있는 방법은 주소 변환이다.
주소 변환을 통해 하드웨어는 가상 주소를 물리 주소로 변환해준다
-> 속도가 생명이기에 SW로는 불가능하고 하드웨어로 할 수 있다.
여기서 OS의 역할은 프로그램이 자신에게 할당 받은 메모리만 접근하도록 제어한다.
즉 어떻게 HW에게 변환할지, 어떻게 메모리를 관리해야할지를 수행한다.


주소 변환의 예시

  • 프로그램은 메모리 공간을 연속적으로 사용한다고 가정하자
    즉 메모리가 여기저기 있는 것이 아닌 시작과 끝까지 모두 연속적으로 배치되어 있는 것이다.
  • 프로세스가 필요한 메모리가 실제 메모리보다 항상 작다고 가정하자
  • 모든 프로세서가 같은 크기의 메모리를 사용한다고 가정하자


다음 그림과 같은 프로세스가 있다고 할때, 위 그림은 프로그램이 자신이 갖고 있다고 착각하는 가상 주소 공간이다.
0~2KB의 코드 부분은 다음과 같다.


컴파일러로 변환하여 어셈블리어로 표현된 것이며
어셈블리어 부분을 보면

  • 변수 x의 주소가 ebx레지스터에 있다고 가정할 때,
  • Load : ebx 주소의 메모리 값을 eax 레지스터에 복사한다.
  • Add : eax 레지스터에 3을 더한다.
  • store : eax의 값을 메모리에 다시 복사한다.

이러한 과정을 메모리 관점에서 보면 x라는 변수가 스택에 저장되며 스택에 있는 x의 값을 3 증가시키는 과정을 살펴보자

  • 주소 128의 명령어를 반입(fetch)
  • 명령어 실행(15KB 주소에서 복사)
  • 주소 132의 명령어 반입
  • 명령어 실행(메모리 접근 없음)
  • 주소 135의 명령어 반입
  • 명령어 실행(15KB에 주소 복사)

이렇게 총 5번의 메모리 접근이 있었다.


📌주소 공간 재배치

아까 그림에서 주소 공간의 크기는 16KB였으며 실제 메모리에서는 이 주소를 사용하는 것이 아니라 적절히 변환해줘야 한다.
-> OS는 프로세스를 0번 주소가 아닌 다른 주소에 위치시켜야 한다.
-> 메모리의 크기가 가변적이므로
-> 그러나 컴파일러는 0번 주소에 프로그램을 위치시킨다.
-> 실제 위치를 알 수 없어 컴퓨터마다 OS버전마다 메모리 크기, 위치가 다르다
-> 따라서 재배치가 필요하다

위 그림은 하나의 재배치된 프로세스이다.
0~16KB의 주소 공간을 사용하는 프로세스가 아름답게 실제 물리주소에 쇽 하고 들어간다.


📌동적(하드웨어-기반) 재배치

  • base-bound라는 아이디어를 사용한 단순한 기술이다.
  • HW의 도움이 없는 재배치는 어렵다
    명령어의 모든 주소를 바꿔야 하기 때문
    포인터 변수의 값도 바꿔야 한다(거의 불가능 - 컴파일러의 도움이 필요, 프로그램 실행 전에만 가능)
  • HW의 지원
    실시간 가상 주소 변환
    잘못된 주소 검출(에러 -> 오류 인터럽트)
    MMU 필요


이 기술을 위해서는 2개의 하드웨어 레지스터 필요하다.
하나는 base 다른 하나는 bound이다.
이 2개의 레지스터를 이용하면 실제 메모리의 원하는 위치에 가상 주소 공간을 배치할 수 있고 프로세스가 자신의 주소 공간에만 접근하도록 한다.
위 그림을 보면 base레지스터는 가상 주소 공간이 실제 메모리에 재배치 되었을 경우 주소 공간의 시작 부분을 의미한다.
따라서 32KB에 위치하는 것이 base 레지스터이다.
그다음 bound레지스터는 가상 주소 공간의 크기를 나타내며 위의 그림과 같이 16KB이다.
따라서 base레지스터로 실제 메모리 주소를 나타내기 위해서는

실제 메모리 주소 = 가상 주소 + base 레지스터

이렇게 나타낼 수 있다.
따라서 128의 실제 주소는 128 + 32KB를 의미한다.
그러나 우리는 bound를 사용하지 않고 있다.
왜일까? 바로 bound는 가상 주소 공간의 크기를 나타내므로 16KB이다.
이 bound는 자기보다 작은 값을 변환할 때에는 제한을 주지 않고 변환을 한다.
그렇다면 만약 가상 주소가 16KB을 넘어 17KB가 된다면 어떻게 될까?
-> 오류를 발생 시킨다.
이처럼 bound레지스터는 프로세스가 다른 프로세스의 메모리에 접근하지 않도록 보호해준다.
따라서 모든 가상주소는 0보다 크고 bound값보다 작아야한다.

여기서 아래의 명령어를 실행시키면
주소 128의 명령어를 반입하기 위해 실제 주소 128 + 32KB(BASE)를 통하여 32896의 물리 주소를 얻어 접근한다.
이를 통해 주소 128의 명령어를 반입하고 명령어를 실행하기 위해 15KB의 주소에서 복사하기 위해 15KB + 32KB를 통하여 실제 주소 47KB에 접근한다.

이렇게 base, bound 레지스터는 CPU에 존재하는 하드웨어이고 주소 변환을 돕는 프로세서 부분을 MMU(메모리 관리 장치)라고 부른다.


📌OS 에서의 메모리 가상화

베이스 바운드 기법에서 OS가 할 일

    1. 프로세스가 시작할 때 : 물리 메모리에서 필요한 공간 찾기
      빈 공간을 찾아 넣어야 함
    1. 프로세스가 종료할 때 : 다음 사용자를 위해 메모리 회수
      재사용 해야함
    1. 문맥교환이 일어날 때 : 베이스 바운드 레지스터 값 저장, PCB에 저장, 프로세스의 위치 변경 가능(몽땅 복사해야함)
      두개의 프로세스는 바운드, 베이스가 다르기 때문

더 자세히 살펴보자


프로세스 시작 시


OS는 새 주소 공간이 차지할 자리를 찾아야 한다.

  • 프리 리스트 : 사용하지 않는 물리 메모리 공간의 위치를 기록한 리스트이다.

프로세스 종료 시


OS는 할당된 메모리를 프리리스트에 반환해야 한다.
중간 삽입 삭제가 자유로워야 하므로 리스트를 사용한다.


문맥 교환 발생 시

OS는 베이스와 바운드 레지스터 쌍을 반드시 저장하고 복원해야 한다.
PCB에 저장한다.


📌베이스 바운드의 문제

당연히 베이스 바운드도 문제가 있다.

  • 메모리 낭비 : 내부 공간이 낭비된다. Heap과 Stack사이의 공간
    -> 내부 단편화

이처럼 프로세서가 사용하는 가상 공간 속 운영체제가 사용할 수 없는 공간이다.
또한 왜 16KB의 주소 공간으로 맞춰져 있을까?
-> 프로세스가 메모리를 얼마나 사용할지 모른다. 따라서 미리 여유있게 할당을 해야한다.
요약하여 베이스 바운드는 스택과 힙 사이에 사용되지 않는 공간이 엄청 크고 이는 곧 메모리 낭비이며 이를 해결할 수 있는 방법이 대망의
Segmentation이다.

profile
코딩 초보 승호입니다.

0개의 댓글