[운영체제] 메모리 관리2

ryun·2023년 4월 20일

운영체제

목록 보기
12/16

물리적 메모리관리에서 연속과 불연속 할당이 존재

불연속 할당 - 페이징 기법

  • 프로세스 구성하는 주소공간이 동일 크기의 페이지 단위로 쪼개져있다

  • 각 페이지는 서로 다른 물리적 메모리 위치에 올라갈 수 있다

    • 당장 필요한 부분은 올려놓고 그렇지 않은 부분은 backing 스테이지, swqp area (보조기억장치)에 내려놓고 쓰게 된다
  • 물리적 메모리도 페이지 하나가 들어갈 수 있는 크기로 나누어 놓는다

    • 물리적 메모리는 페이지라고도 부르지만 페이지 프레임이라고 부른다(컨텐츠를 담을 수 있는 공간)

전통적으로 많이 사용하는 페이지는 4kb
각 페이지마다 주소변환이 필요하다 > 주소변환을 위한것이 페이지 테이블

연속할당기법과의 비교


프로그램 크기가 제각각인 프로그램이 실행되고 끝나서 빠져나가면 공간이 생기는데 이 공간이 그 다음 실행 프로그램보다 작으면 프로그램이 못들어간다 >
페이징 기법은 프로그램을 동일한 크기 페이지로 쪼갰기 때문에 빈 페이지 프레임 있으면 어떤 프레임이든 들어갈 수 있다
따라서 적어도 외부 공간이 생기지 않는다
내부 조각은 생길 수 있다 (프로그램 구성하는 주소공간을 자르다보면 마지막에 자투리 공간이 남는다)

조각: 메모리 공간 중 비어있는데 활용안하는 공간
외부조각: 작아서 못들어가는 공간
내부조각: 프로그램이 들어가고 남은 공간 (이미 할당됨)

  • 왼쪽은 하나의 프로그램 구성하는 논리적 메모리(버츄얼메모리)
    4개 페이지로 잘라놓았다
    각 페이지들은 물리적 메모리의 서로 다른 위치에 올라갈 수 있다
    주소변환을 위한 정보가 4개(페이지 개수만큼) 필요하다
  • 중간의 페이지 테이블을 통해 주소변환 한다
    • 테이블은 구현을 위해 사용된 배열이라고 생각하면 편하다
    • 각각을 엔트리라고 부른다
      4개의 엔트리로 구성된 테이블
  • 주소변환 할 때는 페이지 테이블 위에서부터 숫자를 확인 >
    1 인덱스가 4면 1이라는 페이지가 4번 프레임에 올라간다

  • CPU가 보는 주소는 논리적 주소이고 이것을 페이지 테이블 통해서 물리적 메모리 주소로 바꾸게 된다
  • 이 과정에서 페이지 번호가 있고 주소를 두 부분으로 나눈다
  • p는 페이지 번호, d는 얼만큼 떨어져있는지 나타내는 오프셋을 뜻한다
  • 페이지 테이블에서 2번 엔트리가면 3번 프레임을 얻게 된다
    2번 페이지는 3번 프레임에 올라간다
  • d는 2번 페이지 안에서 얼만큰 떨어진 위치인지 나타내는것
    떨어져있는지에 대한 정보는 3번 프레임에 가서도 변하지 않는다
  • 즉, 논리적 페이지 번호 p가 f로(물리적 프레임 번호)로 바뀌었고, 페이지 안에서 얼만큼 떨어져있는지 d는 변환시에도 그대로 오프셋d를 가진다

위를 이해하기 쉽게 말하면
서울이라는 페이지0 땅 안에서 이화여대의 주소는 이화여대길 52이다
서울시를 주소변환해서 그대로 제주에 들고간다면 이화여대가 52번지라는 것은 똑같다
주소 변환해도 서울 내에서의 위치였던 오프셋은 변하지 않는다

동적 배치

편의상 32비트로 설명
주소가 32비트면 프로그램 크기는 최대 얼마인가?
논리적이든 물리적이든 주소는 바이트 단위로 매겨진다
예를들어 1비트 주소라면 0 또는 1 메모리 두 군데, 2비트를 구분할 수 있다
2비트로 표현가능한 정보는 4가지 메모리로 서로 다른 4군데를 가리킬 수 있다

메모리 주소가 32비트면 구분할 수 있는 정보는 2의 32승 가지
바이트 단위로 주소를 매겨서 이런 상황에서 2의 32승 바이트가 메모리 공간의 최대치
2의 10승이 kilo 20승이 메가 30승이 giga
(주소가 32비트 일 경우) 프로그램 가질 수 있는 최대 메모리 크기는 4기가 바이트

페이지 하나가 4KB
4기가 바이트를 잘라보면 페이지 수는 얼마?
프로세스 구성하는 메모리는 페이지 100만 개가 넘는걸로 구성된다
그러면 페이지 테이블의 엔트리도 페이지 개수만큼 필요하다

페이지 테이블


페이지 개수가 프로세스마다 백만개 넘는 상황
페이지 테이블을 레지스터에 집어넣을 수 없기 때문에 페이지 테이블 자체가 메인 메모리에 들어가게 된다

  • 레지스터 두 개

    • 페이지 테이블 베이스 레지스터
      페이지 테이블 시작위치
    • 페이지 테이블 렝스 레지스터
      페이지 테이블 크기를 보관하는 용도
  • 메모리는 두 번 접근해야한다

    • 주소변환을 위해 메모리 페이지 테이블 접근
    • 주소변환 됐으면 실제 데이터 접근하기 위해 메모리 접근
  • 성능 저하를 막기 위해 빠른 주소 변환 전담하는 빠른 캐시 메모리를 TLB라고 부른다

  • 캐시 메모리는 두 종류
    메모리와 CPU 사이 속도 차이 완충해주는것이 캐시메모리(데이터 담는것)인데
    여기서의 TLB는 주소변환을 빠르게 하기 위한 캐시메모리

TLB 사용한 페이징

  • CPU가 논리적 주소를 주고 주소를 변환해달라고 요청했을 때 >
    페이지 테이블 가기 전에 TLB 먼저 확인 >
    TLB에 페이지 P가 있으면 주소변환해서 바로 메모리에 접근 >
    TLB 캐시가 없으면 페이지 테이블을 통해 주소변환 >
    페이지 번호 p를 주면 페이지 테이블에서 p번째 엔트리에 가서 프레임 번호를 얻고,
    주소변환이 끝나면 위에서부터 f번째 프레임에서 가서 내에서 d번째 떨어진 곳에 위치

  • 페이지 테이블은 테이블이라는 자료구조는 배열

  • 페이지 테이블은 인덱스 자체가 논리적 페이지 번호 역할이기 때문에 논리적 페이지 번호가 필요없다

  • TLB는 일부만 담고있기 때문에 페이지 번호와 프레임 번호를 쌍으로 가지고 있어야 한다(어떤 페이지에 대한 주소변환인지에 대한 정보)

    • 변환할 때 페이지 테이블처럼 바로 되는게 아니라 주소변환정보가 TLB에 있는지 전부다 탐색 해야한다 > 오버헤드가 크다
  • 변환 정보를 TLB에서 발견 못하면 TLB 미스 > 페이지 테이블에서 주소변환 해야함

  • TLB는 보통 병렬적으로 찾겠다는 것 (화살표 여러개)

    • 그렇게 되는 하드웨어가 있어야 한다
      순차적으로 하면 오래걸리기 때문에 associative register를 사용해 탐색한다
  • 각 프로세스 마다 페이지 테이블 존재
    만약 문맥변환 발생해서 cpu가 프로세스 a로부터 b로 넘어갔다고 하면 논리적 주소는 0번째부터 시작하는 주소가 a와 b 별도로 잇어서 tlb가 완전 달라져야 한다
    또 문맥 변환할 때 모든 엔트리가 지워져야 한다
    이는 상당한 오버헤드

효과적 메모리 접근 시간


메모리 접근 시간이 얼마나 걸리는가?

TLB를 통해 이루어지는 주소변환 비율(hit ratio)이 알파
TLB를 통해 안돼서 미스가 나는 비율은 1-알파

TLB 접근하는 시간을 입실론
메모리 접근 시간 1
(입실론은 1보다 작다)

주소변환이 TLB를 통해 될 때 입실론 시간으로 변환 끝나고 실제 데이터 접근 시간은 1
주소변환 TLB 통해 안되는 경우 1-알파의 비율만큼 입실론은 여전히 걸림
페이지 테이블 통해 주소변환 메모리 접근 1 + 실제 데이터를 읽느라 1 = 2
TLB의 히트 래티오가 1에 가까운 값을 가지기 때문에 메모리 접근 시간을 크게 줄이는 효과가 있다

  • 페이지 테이블 사용하면 좋은 점
    프로그램을 동일 크기로 잘라서 위치 아무데나 올릴 수 있다 > 필요한 페이지만 올리면서 효율적으로 사용
    페이지 개수가 프로세스마다 백만개 넘고 엔트리 수가 백만 개가 넘는다
    엔트리 하나하나가 프레임 번호를 담고 있다
    (엔트리 하나가 4바이트 정도가 된다 4바이트 엔트리가 백만 개 존재)
    프로세스당 페이지 테이블에 4메가바이트 이상의 메모리 공간이 필요하다
    페이지 테이블은 프로세스마다 각각 존재

32비트 주소체계 사용하는 현대 운영체제에서 페이지 테이블 위해 많은 공간낭비
페이지 테이블은 1M개 엔트리도 1M개가 필요하게 된다
결국 대단히 많은 메모리 공간이 주소 변환을 위해 사용되므로 페이지 테이블을 위한 매모리 공간낭비가 너무 심하다
따라서 2단계 페이지 테이블이 고안 (시간이 아니라 공간을 줄이는 것을 목표)

2단계 페이지 테이블


  • 2단계 페이지 테이블 또는 이상의 다단계 페이지 테이블
    두 단계로 돠어있다(바깥쪽, 안쪽)
  • 논리적 주소 주면 바깥쪽 테이블을 통과해 안쪽 통과해서 메모리 상에 위치를 놓게된다
  • 2단계를 쓰면 주소변환을 위해 메모리를 두번 거쳐야 한다
    주소변환하느라 2번 + 데이터 하느라 1번 > 시간상으로 손해
  • 공간상으로 이득을 보려고 사용한다
    • 밖 테이블을 따라가면 안쪽있고 따라가면 메모리인 구조
      밖에서 사용안되는 부분에 대해서 안쪽 테이블 자체가 안만들어진다

  • 실제로 프로세스 주소공간 구성하는 백만개 이상 페이지 중에서 정말 사용되는 페이지는 얼마되지 않는다
    • 논리적 메모리에서 사용되는 부분 지극히 일부분
    • 하지만 진짜 낭비는 주소변환을 위한 페이지 테이블에서 발생
    • 엔트리 백만 중 사용안되는 공간을 없애지 못한다
      없애버리면 페이지 번호를 가지고 바로 접근을 못하게 된다
      p번째 엔트리를 보겠다고 하면 바로 확인하는데 없애면 접근이 불가

2단계 페이징 주소 변환 스킴


2단계 페이지 테이블에서 주소변환이 되는 과정
32비트 주소가 세부분으로 나뉨 >
d는 페이지 오프셋(얼마나 떨어져있는지)>
p2는 4k로 구분하려면 2의 12승
12비트가 있으면 4k페이지의 바이트 단위 위치구분이 가능

  • d

    • 32비트 중에서
      페이지 크기 4kb 페이지 내 바이트는 총 4k = 2의 12승 개가 있다
      구분하기 위해 12비트 사용
  • p2

    • 페이지 테이블 엔트리 1개가 4바이트이기 때문에 페이지 하나에 4kb/4b = 1k(2의 10승)개 엔트리가 있다 > 이를 구별하기 위해 10비트 필요
    • 위에서부터 몇 번째 엔트리인지 구분하기 위한 번호가 p2
  • p1

    • 자동적으로 32에서 뺀 것이 10비트


오른쪽 페이지 하나가 4키로바이트. 그안에서 바이트 단위로 위치 구분을 위해 12비트가 필요했던 것


이것도 4키로바이트 바이트 단위
위치 구분이 아니고 엔트리 하나가 4바이트기 때문에 4키로 바이트를 4바이트로 나눈 1024개를 구분하기 위한 번호
이걸 구분하려면 2의 10승이라 10비트가 필요

나머지는 자동적으로 32에서 뺀 것이 10비트

p2 안쪽 페이지 번호 통해 인덱싱을하고 들어가면 페이지 프레임 번호가 나온다
그걸 통해 d번재 바이트 위치 가면 로지컬에 대응하는 피지컬 위치가 나온다

서로다른 n군데를 비교하려면 몇 비트 필요?
서로다른 2의 n승 군데 구분하기 위해 몇비트 필요? n비트
n비트로 구분가능한 서로 다른 위치는 2의 n승가지

다단계(3단계 이상) 페이징

  • 문제점

    • 주소 공간중에 상당부분이 사용안되기 때문에 공간은 크게 줄일 수 있다
      최외곽만 만들어지고 사용안되는건 만들어지지 않기 때문에
    • 하지만 시간이 오래걸린다
      ex) 주소 변환 위해 메모리 4번 접근해야하고 실제 데이터를 얻기 위해 한번 접근
  • TLB는 지극히 일부만 캐싱하지만
    주소공간 중에 지극히 일부만 사용되면 TLB가 사용되는 페이지 상당 부분을 캐싱하고 있을 수 있다
    4단계 쓰더라도 TLB를 통해 주소 변환 비율 높일 수 있다

  • 페이징 테이블에 프레임뿐만 아니라 비트가 하나 더 사용
  • 왼쪽 번호가 정말 프레임번호일 수 있지만 아예 디스크에서 내려가 있을 수 있다
  • 비트를 하나 이용해서 비트가 valid로 표시되어잇으면 메모리에 올라가 있는 것
  • invalid면 메모리에 올라가 있지 않다고 구분
    (페이지가 내려가 있는 경우일 수 있고 또 아예 페이지를 사용 안하는 경우일 수도 있다)

엔트리는 무조건 만들어져야 한다
엔트리가 사용안되는 경우 > invalid

0개의 댓글