Memory Virtualization: Address Space

­3zu·2022년 5월 1일
0

운영체제

목록 보기
9/20
post-thumbnail

Memory Virtualization

OS는 자신의 physical memory를 가상화하고 각 process가 전체 memory space를 소유하고 있다는 illusion을 심어준다.
또한 OS는 각 process가 서로의 영역에 errant access를 하지 않도록 보장해준다.

memory virtualization으로 인해 우리는 코딩을 할 때 이 프로그램이 memory의 어디에 allocate되는지, 어떤 physical memory에 access하고 allocate하는지 전혀 고려하지 않아도 된다.

초기 system의 OS에서는 memory에 하나의 process만 load되었다.
OS가 memory space의 bottom에 존재하고 memory space에 하나의 프로그램을 load해서 prepare하고 CPU에서 run하도록 했다.

이것은 매우 안좋은 poor utilization과 efficiency 문제를 초래했다.
memory 공간은 큰데 거기에 작은 프로그램 딱 하나밖에 안돌리는 등의 문제가 있었기 때문이다. 사용할 수 있는 자원이 있음에도 사용하지 않는걸 이 바닥에서는 정말 극혐한다.

시간이 흐르면서 memory에 여러 process를 load할 수 있게 되었다.
한 process를 잠시 실행했다가 다른 process로 switch하는.. utilization과 efficiency가 증가하였다.

하지만 protection issue가 생기게 되었다.
각 process가 switch하면서 잘못된 memory region에 접근할 수 있기 때문이다.

Address Space

OS는 physical memory에 대한 abstraction을 만들었다.

이것은 OS가 physical memory를 process에게 direct하게 주지 않음을 의미한다.
adress space를 통해 abstraction을 하면 process는 자신이 0부터 시작하는 physical memory를 온전히 소유하고 있다는 illusion에 빠진다.
이로 인해 많은 process가 같은 주소에 접근하려고 하는 conflict가 발생하므로 OS가 이를 잘 manage해주어야 한다.
따라서 OS는 address space에서 사용하는 0부터 시작해 특정 범위까지 주어지는 virtual address를 physical address로 잘 translate해주어야 한다.

OS는 process에게 illusion을 주면서 address translation을 해야한다는 오버헤드가 생기지만 한편으로는 address translation을 정확하게 할 수만 있다면 잘못된 영역에 다른 프로세스가 접근하지 못하도록 할 수 있다.

Memory APIs

Dangling Pointer

memory의 사용이 끝나기 전에 memory가 free되는 것이다.
여러 process가 같은 memory region을 가리키고 있었는데 그 중 하나가 그 memory region을 free한다면 다른 process들은 free가 된 region을 가리키게 된다.
free가 된 공간을 가리키는 포인터를 dangling pointer라고 한다. 이는 잘못된 영역을 가리키고 있는 것이다.

realloc()

#include <stdlib.h>

void *realloc(void *ptr, size_t size)

memory block의 size를 바꾸고 싶을 때 호출한다.
기본적으로는 memory의 size를 늘릴 때 사용하는데 heap의 memory size에 따라 new area를 allocate할 수도 있고 기존에 있던 공간의 크기를 늘릴 수도 있다.

따라서 realloc을 통해 return되는 pointer는 ptr과 동일할 수도 있고 다를 수도 있다.

System Calls

#include <unistd.h>

int brk(void *addr)
void *sbrk(intptr_t increment);

procss가 memory space를 할당받고 싶다면 OS의 도움이 필요하다.
그래서 user program이 memory space를 할당하려고 할 때 모든 경우 brksbrk를 호출한다.

mallocbrk system call을 호출한다.

brk는 program의 break(the location of the end of the heap in address space)를 expand할 때 호출한다.
sbrkbrk와 비슷한 additional call이다.

프로그래머는 절대 direct하게 brksbrk를 호출해서는 안된다.
시스템 자원을 관리하는 것은 오로지 OS의 권한이기 때문이다.

#include <sys/mman.h>

void *mmap(void *ptr, size_t length, int port, int flags, int fd, off_t offset)

mmap은 memory를 create하고 file의 storage를 memory에 map한다.
disk의 file content를 memory에 map하고 싶을 때 mmap을 사용하면 memory operation을 통해 file의 내용에 access할 수 있다.
file operation을 사용하지 않아도 된다는 의미.

Address Translation

memory virtualization은 efficiency와 control을 위해 limited direct execution(LDE)와 비슷한 전략을 취한다.

memory virtualization에서 efficiency와 control은 hardware support를 통해 얻어진다 (registerm TLBs, page-table).

다음과 같은 가정을 해보자.

  1. user의 address space는 physical memory에 연속적으로 존재해야 한다 (memory region 사이에 hole이 없음).
  2. address space의 size는 physical memory의 size보다 작다.
  3. 각 address space는 같은 크기를 가지고 있다.

현실적인 memory virtualization을 위해 위의 가정을 하나씩 relax할 것이다.

virtual address를 physical address로 transform해주는 것은 hardware이다.
virtual address를 physical address로 translate하는 것은 너무 여러 번 일어나기 때문에 그 과정을 가속화하기 위해 hardware의 support가 필요하다.

다음과 같은 코드가 있다고 생각해보자.

int x;
x = x + 3;

x = x + 3;을 실행할 때 value(x)를 memory로부터 load해서 3만큼 증가시키고 다시 memory에 저장하는 과정이 필요하다.

이를 어셈블리로 표현하면 다음과 같다:
xebx레지스터에 들어있다고 가정하면

128 : movl 0x0(%ebx), %eax
132 : addl $0x03, %eax
135 : movl %eax, 0x0(%ebx)

그리고 address space가 다음과 같다고 하자.

위의 instruction을 실행하기 위해 다음과 같은 과정을 거치게 된다.

  1. instruction을 128에서 fetch한다.
  2. fetch한 instruction을 실행한다.
    이 과정에서 15KB에 있는 x를 load해야한다.
  3. instruction을 132에서 fetch한다.
  4. fetch한 instruction을 실행한다.
    addl에서는 단순히 3을 더하기 때문에 memory reference를 하지 않는다.
  5. instruction을 135에서 fetch한다.
  6. fetch한 instruction을 실행한다.
    이 과정에서 15KB에 값을 저장해야 한다.

memory reference가 일어날 때마다 virtual address를 physical address로 translate하는 과정을 거쳐야 하는데 memory reference는 memory로부터 instruction을 fetch할 때와 memory operation을 할 때 모두 발생하므로 위의 6개의 과정 중 4를 제외한 5개의 과정에서 memory access를 한다.

이처럼 어떤 프로그램을 실행하면 그 실행의 대부분이 memory access와 연관되어 있다.
memory access를 할 때마다 OS가 개입해야하면 프로그램 실행이 너무 느려진다.
address translation을 할 때마다 process로부터 control을 뺏어와야한다면, 그 때마다 mode switch를 해야하기 때문이다. 그래서 hardward의 support가 반드시 필요하다.

Relocation Address Space

OS는 process를 address 0이 아닌 physical memory의 어딘가에 위치시키고 싶어한다.
하지만 process의 address space는 그 process가 physical memory의 어디에 위치하든 관계없이 address 0부터 시작된다.
base register는 relocated address의 starting point를 가리키고 있다.

bound register는 memory access가 올바른지 알려준다.
address space가 항상 0부터 특정 범위까지이기 때문에 base address에 virtual address를 더해서 쉽게 physical address를 구할 수 있다.

(physical adsdress) = (virtual address) + (base)
0 <= (virtual address) < bounds

base에 virtual address를 더하기 전에 그 virtual address가 유효한 범위 내에 있는지 bound register로 확인한 후 더하게 된다.

아래의 address space에서 다음의 instruction을 실행해보자:

128 : movl 0x0(%ebx), %eax

  • instruction을 128에서 fetch한다.
32896 = 128 + 32KB(base) = 128 + 32 * 1024 = 128 + 32768
  • fetch한 instruction을 실행한다.
    이 과정에서 15KB에 있는 x를 load해야한다.
    address translation하면 47KBx를 load하게 된다.
47KB = 15KB + 32KB(base)

dynamic relocation을 위해 필요한 hardware 중 중요한 것은 base/bound registers이다. base register와 bound register는 pair로 존재하며 이 register들이 없으면 아무도 base와 bound를 보장해주지 않고 자기 멋대로 아무데나 접근할 가능성이 있다.

OS Issues for Memory Virtualizing

When a Process Starts Running

OS는 새로운 address space를 위한 공간을 physical memory에서 찾아야 한다.

이 때 free list를 이용한다.
free list는 physical memory에서 사용되지 않는 공간의 범위가 연결된 list이다.

OS는 free list를 lookup해서 process를 할당할 위치를 정하고 process table과 process가 사용할 memory를 할당한 뒤 base/bound register를 set해야 새로운 process를 실행할 수 있다.

When a Process Is Terminated

OS가 process가 사용했던 memory를 다시 free list에 넣는다.

When Context Switch Occurs

OS는 base/bound pair를 반드시 save해 두었다가 나중에 restore해야한다.
base/bound register는 process structure나 process control block(PCB)에 저장된다.

현재는 base/bound register를 PCB에 저장한다.
사실 base/bound register의 값이 변하지 않을 것이라는 보장이 있다면 굳이 저장하지 않아도 되겠지만 어떤 경우에는 address space의 크기가 변할 수 있고 그 때에는 base/bound register의 값이 변할 것이기 때문에 저장한다.

0개의 댓글