Memory management

CPU가 접근 가능한 저장소는 CPU 내부의 Register그리고 Main memory이다.

CPU는 여기에서 commandload하여 processing 한다.

보통 CPU는 register1 clock cycle 내에 접근이 가능하다.

하지만 만약 commandMain memory에 있을 경우 1 clock이상의 시간이 소요되어 stall(지연)된다. 이러면 낭비가 심해지기 때문에 CPUMain memory 사이에 Cache를 두어 문제를 해결한다.

Program은 Binary execution file 형태로 디스크에 저장되어 있으며 실행되기 위해서는 Main memory로 올라와서 Process가 되어야 한다.

Process는 효율적인 실행을 위해 디스크와 Main memory 사이를 왔다갔다 하는데 이 때 Main memory에 올라오기 위해 대기하고 있는 Process들의 집합Input Queue라 부른다.

코드에서 사용하는 symbol 형태(ex. pointer, *a)는 Compiler에 의해 Relocatable address(재배치 가능 주소)binding되고 이는 linkage editor 또는 loader에 의해 Absolute address(절대 주소, 물리 주소)binding된다.

Binding은 시점에 따라 세 가지로 나눌 수 있다.

  • Compile time binding
    • Compile time에 Memory 내의 위치를 직접 알 수 있으면(process가 R번지부터 시작한다는 사실) Compiler는 Absolute code(절대 코드)를 생성할 수 있다. 하지만 이 위치가 변경되어야 한다면 이 코드는 다시 compile되어야 한다.
  • Load time binding
    • Compile time에 적재 장소를 알 수 없다면 CompilerBinary codeRelocatable code로 만들어야 한다. Relocatable code는 시작 주소가 변경되더라도 사용자 코드를 다시 reload만 하면 된다.
  • Excution binding
    • Process가 실행되는 중간에 memory 내의 한 segment에서 다른 segment로 옮겨질 수 있을 때 “바인딩이 실행 시간까지 허용되었다” 라고 이야기 하며, 이것이 가능하려면 특별한 Hardware를 이용해야 한다.

CPU가 생성하는 주소를 Logical address(논리 주소)라 하며, Memory가 다루는 주소를 Physical address(물리 주소)라 한다.

Compile time binding, Load time binding에서는 Logical addressPhysical address가 같지만 Excution binding에서는 서로 다르다. 이 때 사용하는 Logical address를 Virtual address라고 부른다.

Virtual address

프로그램 실행 중 Physical address로 바뀌어야 하는데 이 바꾸는 작업을 Mapping이라 하며 MMU (Memory Management Unit)에서 작업이 이루어진다.

Dynamic Loading(동적 적재)

Physical memory 크기의 제한때문에 큰 program의 경우 미리 memory에 모두 올라와있지 못한다. 이를 해결하지 위해 Dynamic Loading이 사용된다.

각 routine은 실제 호출되기 전까지는 memory에 올라오지 않고 relocatable 상태로 disk에 대기하고 있다가 Main program이 memory에 올라와 실행되고 이 routine이 다른 routine을 호출하게 되면 호출된 routine이 이미 memory에 laoding되어 있는지 확인한다. 없으면 Relocatable linking loader가 호출되어 요구된 routine을 memory로 가져오고 이러한 변화를 테이블에 기록해 둔다. 그 후 CPU 제어는 중단되었던 routine으로 보내진다.

Swapping

Process가 실행되기 위해서는 memory에 있어야 하지만 항상 점유하고 있을 수는 없다. 따라서 실행되는 도중에 임시로 Sub memory로 보내졌다가 다시 Main memory로 돌아올 수 있다.

Swapping을 변형하여 우선순위를 두어 처리하는 것을 Roll-in, Roll-out 이라고도 부른다.

Swapping system은 Context-switching time이 상당히 오래 걸린다.

Fragmentation

memory의 이곳 저곳을 점유하다보면 크기에 따라 중간중간 비는 공간이 나타나게 되고 이를 Fragmentation이라 부른다.

Fragmentation 문제를 해결하기 위해 두 가지 기법을 사용할 수 있다.

  • Paging
  • Segmentation

Paging

Physical memory는 frame이라는 같은 크기의 block들로 나누어져 있고 Logical memory는 page라는 같은 크기의 block들로 나누어져 있다.

CPU에서 나오는 모든 주소는 Page number(p)Offset(d)로 구성된다. Page numberPage table에 access할 때 사용되며 Page table은 Main memory에서 각 page가 점유하는 주소를 가지고 있다. 이 주소에 Offset을 더하면 원하는 Physical address가 된다.

paging hardware{:class=”img-responsive”}

Frame 및 Page의 크기는 Hardware에 의해 정의되며 Page의 크기는 일반적으로 512 byte ~ 16 MB 사이이며 2의 제곱으로 증가한다.

Logical address의 크기가 2^m 이고 page가 2^n의 크기를 갖는다면 Logical address의 상위 m-n 비트는 page number를 나타내고, 하위 n 비트는 page offset을 나타낸다.

paging model{:class=”img-responsive”}

Segmentation

사용자는 하나의 Program을 subroutine, procedure, function 또는 module들을 가지고 있는 것으로 생각하고, Table, Array, Stack 등의 다양한 변수를 사용한다.

이러한 사용자가 바라보는 Memory의 관점을 그대로 지원하는 Memory Management 기법이다.

쉬운 구현을 위해 Segment name 대신 Segment number가 System에 의해 매겨지고 Segment는 number로 불리운다. 때문에 Logical address는 <segment-number, offset>으로 구성된다.

segment example{:class=”img-responsive”}

Virtual Memory

Process 전체가 Memory에 올라오지 않더라도 실행이 가능하게 하는 기법이다. Physical memory로부터 사용자 관점의 Logical memory를 분리시켜 Main memory를 균일한 크기의 저장 공간으로 구성된 엄청나게 큰 배열로 추상화시켜 준다.

  • 장점
    • (Physical) Memory size의 제약으로부터 자유로워진다.
    • File의 공유를 쉽게 해주고 Shared memory 구현을 가능케 한다.
    • Process 생성을 효율적으로 처리할 수 있는 Mechanism을 제공한다.
    • 많은 program을 동시에 수행 가능하고 이에 따라 응답 시간(response time, turnaround time)은 늘어나지 않으면서도 CPU 이용률(utilization)과 처리율(throughput)이 높아진다.
    • swap하는데 필요한 입/출력 횟수가 줄어들어 program들이 상대적으로 빠르게 실행된다.
  • 단점

    • 구현하기 어렵다.
    • 잘못 사용하면 성능이 크게 저하된다.

    앞에서 본 Memory management 기법 중 Dynamic loading은 process 전체를 memory에 올려야 한다는 제약을 어느정도 막아주긴 하지만 프로그래머가 추가적인 작업을 해야한다.

    앞서 본 것처럼 page frame들로 인해 Physical memory는 연속적인 공간이 아닐 수 있다. MMU(Memory Management Unit)는 Physical memory를 Logical memory로 mapping한다.

    Virtual Memory의 각 area는 다음과 같이 사용된다.

  • Stack

    • main() 함수, Callback 함수의 주소, 지역변수, 파라미터, return value가 저장되는 영역이다.
  • Sparse
    • 빈 공간을 포함한 Stack과 Heap 사이의 영역이다.
  • Heap
    • 동적 메모리 할당 영역이다.
  • Data
    • 전역변수, 정적변수(static), 배열, 구조체, 상수가 저장되는 영역이다.
    • Data 영역은 두 가지 영역으로 구분할 수 있다.
      • Data
        • 초기값이 있는 경우
      • BSS (Block Started by Symbol)
        • 초기값이 없는 경우우
  • Code
    • 작성한 Code가 저장되는 영역이다.

virtual memory{:class=”img-responsive”}

  • Code, Data, Stack 영역은 Compiler가 Memory의 크기를 결정한다.
  • Heap 영역의 크기는 개발자에 의해 프로그램 동작 시 결정된다.
  • Stack의 지역변수는 사용 후 소멸하므로 데이터 용량이 불확실하다. 따라서 밑에서부터 올라가면서 값이 채워진다.
  • Heap overflow
    • Heap 영역이 Stack 영역을 침범한 경우
  • Stack overflow
    • Stack 영역이 Heap 영역을 침범한 경우

아래 그림은 wikipedia에서 설명하고 있는 동적 할당에 대한 그림이다.

Memory map{:class=”img-responsive”}


출처

아래의 글들을 교재삼아 작성하였습니다.

Share