메모리 관리 전략

sun202x·2023년 2월 10일
0

운영체제

목록 보기
21/23
post-thumbnail

해당 게시글은 kocw에서 제공하는 금오공과대학교 최태영 교수님의 무료 강의를 공부하고 정리하기 위해서 만들어졌습니다.

Memory Management

  • 운영체제는 메모리의 남은 영역(인터럽트 벡터, 인터럽트 핸들러, 쉘을 제외한 나머지)을 관리하고 할당해주어야 한다.
  • 메모리 프로텍션과 효율적인 메모리 할당 방법을 제공해 주어야 한다.
  • 메모리 상단에는 운영체제가 존재하고 이후 아래 영역에는 각각의 프로세스가 올라와서 실행된다.
  • 이러한 프로세스들은 각각의 영역을 침범하지 않게 해주어야 하는데, 그렇게 처리하기 위해 울타리를 둔다.
  • 뿐만 아니라 이것을 처리하기 위해 하드웨어(레지스터)가 필요하며, 프로세스의 시작 위치와 프로세스의 길이를 기록한다.
    • base register: 시작 위치
    • limit register: 프로세스 길이
  • cpu가 프로세스를 수행하면 메모리 주소를 가지고 접근하게 되고 이것을 base register와 비교하게 된다.
  • base register보다 현재 메모리 주소가 작다면 잘못된 접근이다.
    • 잘못된 접근은 trap을 걸어서 프로세스를 죽이게 된다.
  • 또한 base register와 limit register를 합친 값보다 큰 경우도 메모리 영역을 벗어났기 때문에 trap을 걸어 프로세스를 죽여버린다.

Binding of Instructions and Data to Memory

  • Compile Time Address Biding
    • msdos 같은 경우 하나의 프로세스만 실행하기 때문에, 프로세스 내에서 사용하는 변수들의 메모리 주소 값을 정해진 주소 부터 사용할 수 있도록 제공해 준다.
    • 하나의 프로세스 밖에 실행하지 못하기 때문에 멀티 프로그래밍을 할 수 없다는 단점이 있다.
  • Load Time Address Binding
    • 실행파일의 주소로 변수의 위치가 정해져 있을 때, 해당 파일을 실행하여 프로세스를 메모리에 올리면 변수들의 주소를 실제 메모리 주소로 변환시켜서 사용하는 방식이다.
  • Execution Time Address Binding
    • 메모리에 올라온 프로세스를 경우에 따라서 메모리 위치를 조정하는 방식이다.
    • 해당 방식을 사용하면 변수에 할당된 메모리 주소가 실제 메모리 주소가 아닐 수 있다는 말이다.
    • 매번 메모리 위치가 변경될 때마다 변수 주소 값을 변경시켜야 하기 때문이다.
    • 메모리 위치에 따라서 변수 값을 변경시켜주는 하드웨어가 필요하다.
    • 이런 식으로 매번 위치가 변경되지만 cpu는 항상 동일한 주소라고 생각하고 접근하는줄 알게 되는데,
    • 이런 식의 메모리 주소를 logical address, virtual address라고 한다.
    • 그리고 실제 메모리 주소를 Physical address라고 한다.
    • logical address같은 경우 계산하기 쉽게 하기 위해서 항상 0번재 부터 메모리 주소가 시작된다.
    • cpu나 프로세스 입장에서는 항상 logical space로 접근하게 된다.
    • 따라서 주소를 변환시켜주는 장치가 필요하다.

MMU(Memory Management Unit)

  • logical address와 physical address를 관리하기 위한 장치를 MMU라고 한다.
  • 하드웨어마다 하나씩 존재하며, cpu 마다 하나씩 존재한다.
    • 하지만 보통 cpu는 core 마다 mmu가 존재한다고 한다.
    • 내부에서 logical address를 쓰면 그것을 관리하는 것들이 있어야 해서 복잡해지기 때문이다.
  • 앞서 살펴본 base register가 relocation register이다.
  • 변경된 메모리 시작 주소가 relocation register의 값이 된다.
    • 시작 주소가 400,000 번이면 레지스터의 값도 400,000이 된다.
  • Dynamic Reloading, Dynamic Linking
    • 메모리가 부족한 시절에 효율적으로 관리하기 위한 기술

Swapping

  • 메모리가 부족한 시점에 현재 실행중인 프로세스 하나를 골라서 하드웨어에 덤핑 시킨다.
    • 그러한 하드웨어를 가리키는게 Backing store이다.
  • 우선순위가 낮은 프로세스를 쫓아 내는 것을 Roll Out이라고 한다.
  • 쫓겨난 프로세스 중에서 가장 우선순위가 높은 것을 불러오는 과정을 Roll In이라고 한다.
  • Swapping을 하다보면 문제가 발생하게 되는데, 기존 I/O 요청을 처리한 프로세스가 swap out 당하고 다른 프로세스가 쫓겨난 프로세스의 기존 메모리 영역위로 올라올 때,
  • I/O 처리가 끝난 후 쫓겨난 프로세스의 기존 메모리 영역에 엉뚱한 값을 덮어쓰는 문제가 발생한다.
    • 새로 들어온 프로세스는 본인의 작업 영역에 전혀 상관없는 값을 보게 되는 것이다.
  • 이것을 해결하기 위한 몇가지 해결책이 있다.
    1. I/O가 끝나지 않은 프로세스들은 스왑하지 않는다.
    • 이것을 Pinning 이라고 한다.
    • 메모리에 계속 남아 있게 하는 것
    1. 항상 I/O 작업이 끝나면 유저 공간이 아닌 커널 공간에 결과를 저장하게 한다.
    • 이렇게 되면 커널은 기존 프로세스가 스왑 아웃 됐는지 스왑 인 됐는지 확인하기가 쉬워서
    • 스왑 인 됐을 때 데이터를 전달해준다.
    • 그렇지만 그만큼 두 번의 카피가 발생하여, 메모리의 카피 오버헤드가 높아지게 된다.
  • 스왑하는 중 컨텍스트 스위칭이 발생하게 되면, 스왑 오버헤드가 늘어나게 된다.
  • 따라서 메모리가 적은 시스템에서는 이러한 스와핑으로 인해 굉장히 느려지게 된다.

Swapping on Mobile System

  • 모바일은 PC와 환경이 다르기 때문에 PC처럼 스와핑을 할 수 없다.
  • 기기 자체의 크기와 전력 소모량 같은 것들을 고려해야 하기 때문이다.
  • 그렇기 때문에 flash memory를 사용해야 한다.
  • 그러나 flash memory는 쓰기 횟수에 제한이 있어, 더이상 쓰지 못하는 상황이 발생한다.
  • 따라서 되도록 write는 줄이고 read를 많이 써야 한다.
  • 모바일 디바이스는 이러한 점 때문에 스왑을 쓰지 않는다.
  • IOS 같은 경우
    • foreground 프로세스가 아닌 경우 메모리를 포기하도록 한다.
    • 바뀌지 않는 프로세스의 코드 부분들은 메모리에 올리지 않는다.
    • 이러한 코드 부분은 flash memory에서 직접 읽어온다.
    • 이렇게 해도 메모리 여유가 확보되지 않으면, 프로세스를 죽이게 된다.
    • 그래서 가끔 죽는 프로세스들이 생기는 것이다.
  • 안드로이드 같은 경우
    • IOS와 비슷하며, 사용할 수 있는 메모리 영역이 부족한 경우, 수행되고 있는 background 프로세스를 강제로 죽이고,
    • 각 어플리케이션 마다 PCB같은 상태를 기록하고 있다가 다시 복원시켜서 사용한다.

Contiguous Allocation

  • 전체 메모리 공간에서 프로세스를 할당하기 위해
    1. 프로세스가 한 덩어리이기 때문에 프로세스가 충분히 들어갈 공간을 찾아서 넣어주는 방법
    1. 프로세스를 구성하는 heap, 가변공간, stack, global variables, code 들을 빈 영역에 조각조각 잘라서 넣어주는 방법
  • 위 두가지 방법이 있다.
  • Contiguous Allocation은 첫 번째 방법에 해당된다.
  • 커널 파티션과 유저 파티션을 쪼개서 빈 부분을 관리한다.
  • 프로세스를 빈공간에 배치 시키고 이 빈 공간을 hole이라는 이름으로 관리한다.
  • 새 프로세스가 들어올 경우 남아있는 홀과 크기를 비교하여 적절한 위치에 배치시킨다.

Dynamic Storage-Allocation Problem

  • Contiguous Allocation 방식을 사용하면 몇가지 문제가 발생하게 된다.
  • 프로세스들이 들어갔다 나오기 때문에 빈 공간이 랜덤하게 발생하게 되는데
  • 이 때 다음 프로세스의 크기에 따라 홀의 위치를 정해주어야 한다는 문제가 발생한다.
  • First-fit
    • hole은 연결리스트로 관리되며, 첫 번째 항목에 해당되는 홀에 프로세스를 배치시키는 전략이다.
    • 시간이 제일 적게 걸린다는 장점이 있다.
  • Best-fit
    • 프로세스가 들어갔을 때 제일 적은 여백을 남기는 홀에 프로세스를 배치시키는 전략이다.
    • 성능이 제일 좋다는 장점이 있다.
  • Worst-fit
    • 제일 많은 여백을 남기는 홀에 프로세스를 배치시키는 전략이다.
    • 성능이 제일 안 좋다는 단점이 있다.

Fragmentation

  • External Fragmentation
    • hole의 크기가 너무 작아서 다 합치면 프로세스를 실행시킬 공간이 나오나, 흩어져 있는 메모리 하나하나는 작아서 프로세스를 실행시키지 못하는 것을 의미한다.
    • Contiguous Allocation의 큰 문제점이다.
  • Internal Fragmentation
    • 메모리는 항상 워드 단위로 관리가 되는데,
      • 32bit는 4bytes, 64bit는 8bytes 이다.
    • 메모리를 읽을 때도 항상 이 워드 단위로 읽어서 메모리를 가져와야 한다.
    • 그러나 프로세스의 크기는 항상 워드 사이즈만큼 딱 떨어지지 않기 때문에,
    • 잉여 공간이 생기게 된다. 이것을 Internal Fragmentation이라고 한다.
  • 보통 이런 Framgmentation 때문에 메모리를 1/3 정도 사용하지 못한다고 하는데,
  • 이 것을 50 percent rule이라고 한다.
  • Fragmentation 가 생기지 않도록 시도할 수 있는 방법들이 있다.

1. Compaction

  • 빈 자투리 공간이 생기지 않도록 모든 실행 중 프로세스를 위쪽 메모리 영역으로 끌어올리는 방법이다.
    • 이렇게 되면 하나의 hole만 남게 된다.
  • 이 방법이 가능하려면, Execution Time Address Binding을 MMU에서 기능을 제공해야 한다.
  • 그러나 이렇게 처리한다해도 I/O 문제는 스와핑과 같이 계속 발생하게 된다.
  • 스와핑과 마찬가지로 동일한 해결방법을 사용한다.
    • 첫 번째 방법은 빈 공간이 중간에 생긴다는 단점이 있고,
    • 두 번째 방법은 메모리 카피가 두 번 발생 하므로 성능이 떨어진다.

2. Segmentation

  • 프로세스를 구성하는 각 부분을 쪼개서 빈 공간에 넣는 방식
  • 흩어져 있어도 큰 문제가 없기 때문에 이 것을 랜덤한 공간에 집어넣을 수 있다.
  • 프로세스의 각 부분은 Segment로 부르며 이 세그먼트의 주소를 관리하게 된다.
  • 세그먼트들은 logical 한 위치는 한 곳으로 보고 phsical 한 위치는 흩어져서 들어가게 된다.
  • 이 것이 가능해지려면 주소 변환이 가능해야 한다.
  • logical address는 2차원 주소로 아래 두 개를 가진다.
    • segment address
    • offset
  • 32bit 컴퓨터라고 한다면 두 개로 쪼개서 각각 세그먼트 주소와 오프셋을 관리하게 된다.
  • MMU에서는 Segment table을 통해 physical address로 변환한다.
  • Segment table은 하나의 entry가 두 개인 필드를 가지며,
    • limit: 세그먼트 길이
    • base: 1차원 주소에서 시작한 위치
  • table 내의 엔트리 개수는 세그먼트 개수만큼 존재한다.
  • 세그먼트 테이블은 메모리에 존재하고 MMU는 cpu에 존재한다.
  • STBR
    • MMU는 세그먼트 테이블 위치를 알기 위해 레지스터 하나에 세그먼트 테이블 위치를 저장하고 가지고 있는다.
    • 그것을 Segment Table Base Register(STBR)라고 한다.
  • STLR
    • 잘못된 세그먼트 주소를 필터링하기 위해 사용하는 레지스터이다.
    • Segment Table Length Register(STLR)이라고 한다.
  • 주소변환 순서
    • STLR을 가지고 현재 세그먼트 주소가 유효한지 검사
      • 유효하지 않으면 트랩 발생
    • 유효하다면 세그먼트 테이블에서 현재 세그먼트 주소에 해당되는 값을 꺼내온다.
    • limit 값을 가지고 현재 logical address의 offset보다 작으면 그 다음으로 넘어간다.
      • offset보다 크다면 트랩 발생
    • offset 값에 base 와 limit을 더해서 physical address로 변환해준다.
profile
긍정적으로 살고 싶은 개발자

0개의 댓글