포스트

[OS] 요구 페이징

1. 물리 메모리의 한계

  • 64비트 CPU의 물리 메모리 최대량: 16EB
  • 실체 컴퓨터에 설치되는 물리 메모리: 8~32GB
    • 왜? 비용 때문에 일부밖에 설치 못한다.

1.1. 도출되는 질문들

  • 물리 메모리의 크기 한계에서 비롯된 2가지 질문
    1. 설치된 물리 메모리보다 큰 프로세스를 실행시킬 수 있는가?
    2. 프로세스들을 합친 크기가 설치된 물리 메모리보다 클 때 이들을 실행시킬 수 있는가?
  • 질문에 숨어있는 전제
    • 프로세스 전체가 물리 메모리에 적재 되어야 실행이 가능한가?
    • 당장 실행에 필요한 프로세스의 일부 메모리만 적재한 채 실행 시킬 수는 없는가? (Overlay)
      • Locality의 개념

1. 물리 메모리의 한계

2. 가상 메모리

  • 물리 메모리 한계 극복 해결책
  • 물리 메모리를 디스크 공간으로 확장
    • 물리 메모리에서 하드디스크로 연장
    • 프로세스를 물리 메모리와 하드 디스크(보조기억장치)에 나누어 저장
    • 프로세스나 사용자가 프로세스를 실행하기에 충분히 큰 메모리가 있다고 착각하게 만드는 메모리 관리 기술

2.1. 스와핑(swapping)

  • 메모리 부족할 때, 실행에 불필요한 부분은 하드 디스크로 이동(스왑 아웃)
  • 실행에 필요할 떄, 하드 디스크로부터 물리 메모리로 이동(스왑 인)

2.1. 스와핑

2.2. 개념

  • 운영체제는 물리 메모리 영역을 하드 디스크까지 연장
    • 프로세스를 물리 메모리와 하드 디스크에 나누어 저장
    • 물리 메모리 한계 극복
  • 프로세스의 실행 시 프로세스 전체가 물리 메모리에 적재되어 있을 필요 없음
  • 운영체제는 물리 메모리의 빈 영역이 부족하게 되면,
    • 물리 메모리 일부분을 하드 디스크로 옮겨 물리 메모리의 빈 영역 확보
    • 이 방식으로 많은 프로세스를 메모리 적재 가능
    • 다중프로그래밍 정도 높임 → CPU 활용율와 처리율 높임
  • 물리 메모리를 확장하여 사용하는 디스크 영역: 스왑 영역
    • 스왑-아웃 : 물리 메모리의 일부를 스왑 영역으로 옮기는 작업
    • 스왑-인 : 스왑 영역에서 물리 메모리로 가지고 오는 작업
  • 사용자는 컴퓨터 시스템에 무한대의 메모리가 있는 것으로 착각
    • 큰 프로그램을 작성하는데 부담 없음.
    • 여러 개의 프로그램을 실행시키는 데 부담 없음
  • 가상 메모리는 운영체제마다 구현 방법이 다름

2.3. 메모리에 대한 각 시스템들의 관계

  • 사용자, 프로세스
    • 무한대에 가까운 큰 메모리를 사용하며, 0번지부터 연속되어 프로세스가 적재되는 것으로 생각
    • 가상의 전체 메모리가 있다고 생각함: 가상메모리
      • Process의 logical한 공간과 실제 physical memory와 분리 시키기 위한 개념
  • 운영체제
    • 프로세스를 물리 메모리와 하드디스크에 분산 저장, 프로세스의 일부만 물리 메모리에 적재
    • 프로세스를 최대한 많이 올리려 하기 때문에, 프로세스를 최대한 잘게 쪼개려고 시도함
  • 디스크
    • 물리 메모리에 빈 공간이 부족하여 메모리 일부를 스왑 영역에 저장
    • 없는 메모리가 있는 메모리 처럼 사용하게 해줌: 가상메모리

2.3. 메모리에 대한 각 시스템들의 관계

2.4. 연관되는 질문들

  • 메모리가 커진 효과라는 건 알겠어요. 그럼 페이지 테이블은 어떻게 되나요?
    • 가상 메모리에 대한 페이지 테이블
  • 어쨋든 실제 메모리에 올라와야하는데…! 만약 실제 메모리에 없는 애를 찾으면 어찌되요?
    • 페이지 폴트
    • 애초에 메모리가 부족해서 가상메모리 쓰는거라면서요? 그러면 어떻게 가져와요?
      • 페이지 할당
      • 그럼 누굴 뺄건간요?
        • 페이지 교체 알고리즘
      • 가져다 두는 건 어찌하는데요?
        • 스왑영역
    • 뭐 swap-in / swap-out 하겠죠. 그런데 이거도 비용이 비싼거 아니에요?
      • 스레싱 문제

3. 가상 메모리를 만드는 방법

3.1. Demand paging(요구 페이징)

  • 페이징 기법을 토대로 프로세스의 일부 페이지들만 메모리에 할당하고, 페이지가 필요할 때 메모리를 할당받고 페이지를 적재시키기는 메모리 관리 기법
  • 현재 실행에 필요한 일부 페이지만 메모리에 적재하고 나머지는 하드 디스크에 두고, 특정 페이지가 필요할 때 메모리에 적재하는 방식
  • 요구 페이징 = 페이징 + Swapping
  • 프로세스의 페이지가 있는 디스크 영역 = 스왑 영역 + 실행 파일

3.2. Swap area

  • 스왑 영역
    • 메모리가 부족할 때, 메모리를 비우고 페이지를 저장해두는 하드 디스크의 영역
    • 리눅스 : 디스크 내 특별한 위치, 혹은 스왑 파티션에 구성
    • Windows : C:/pagefile.sys 파일

3.3. 페이지 테이블 엔트리

3.2. Swap area

  • 페이지 번호
  • 플래그 비트
    • access
      • 페이지가 메모리에 올라온 후 사용한 적이 있는지 여부
    • modified (dirty bit)
      • 해당 페이지가 수정되었는지 여부 (c.f., 캐시)
      • 이 비트가 1이면, 해당 페이지가 프레임에 적재된 이후 수정되었음, 나중에 쫓겨날 때 스왑-아웃
    • valid (presence)
      • 해당 페이지가 물리 메모리에 있는지 여부
      • 이 비트가 1이면, 해당 페이지가 프레임 번호의 메모리에 있음, 0이면 디스크의 블록 번호에 있음.
    • rwx
      • 읽기, 쓰기, 실행 비트 : 페이지에 대한 읽기 권한, 쓰기 권한, 실행 권한을 나타내는 비트
  • 프레임 번호

3.4. 가상 메모리와 페이지 테이블

3.4. 가상 메모리와 페이지 테이블

4. Page fault

  • 페이지 폴트
    • 메모리 참조를 하려하는데 물리 메모리에 원하는 페이지가 없는 경우
    • CPU가 액세스하려는 페이지가 물리 메모리에 없을 때, 페이지 폴트 발생
    • 페이지 폴트가 일어나면 빈 프레임을 할당하고 스왑 영역이나 실행 파일로부터 페이지 적재
  • 페이지 폴트(부재)
    • 요구 페이징에서 가장 중요한 상황
    • CPU가 발생시킨 가상 주소의 페이지가 메모리 프레임에 없는 상황
    • MMU가 가상 주소를 물리 주소로 바뀌는 과정에서 발생
  • 페이지 폴트 처리과정
    • 프로세스가 페이지 n을 요청할 때, 페이지 테이블의 유효 비트가 0이면 페이지 폴트가 발생
    • MMU는 PTE에 기재된 블록번호에 접근하여, 해당 데이터를 메모리의 빈 프레임으로 가져옴
      • 비어 있는 공간이 없다? → 페이지 교체 알고리즘 동작
    • 해당 프레임으로 접근하여 해당 데이터를 프로세스에 넘김
    • 유효비트를 1로 업데이트하고, 프레임 번호도 업데이트.

4.1. 가용 프레임 리스트

  • 비어있는 프레임은 OS가 리스트 형태로 관리함
  • Zero fill-on-demend
    • 메모리에 쓰레기 값 남지 않게 하는 것
    • 보안을 위해 할당시에는 값들을 0으로 초기화
  • 잘 쓰이지는 않음(메모리에 가용 영역이 있는 경우가 드묾)

4.1. 가용 프레임 리스트

4.2. 예제

  • main() 함수와 전역 변수 n을 가진 C 프로그램
    • 전역 변수 n의 가상 주소는 0x11111234, 페이지 번호는 0x11111 이라 가정

4.2. 예제

  • n = 10 의 컴파일된 기계어 코드
mov eax, 10 ; eax 레지스터에 10 저장
mov [11111234], eax ; eax 값을 0x1111234 번지에 저장
  • [111111234]에 접근할 때, page fault가 발생한다면?

5. 프로세스의 실행

  • 운영체제는 첫 페이지만 물리 메모리에 적재, 실행 중 다음 페이지가 필요하면 그때 적재!
    • 어떤 운영체제의 경우 첫 페이지도 물리 메모리에 적재하지 않고 실행시키고 첫 페이지가 필요할 때 그 때부터 적재시키는 방법 사용

5.1. 예제

  • 100개 이상의 페이지로 구성된 C프로그램

5.1. 예제-1

  • 프로세스 실행
    • 프로세스 실행을 시작할 떄 첫 페이지를 메모리에 적재

5.1. 예제-2

  • 페이지 폴트를 통해 실행파일로부터 페이지들 적재

5.1. 예제-3

  • 메모리가 부족하면 스왑-아웃/스왑-인

5.1. 예제-4

  • 스왑-아웃된 페이지 100의 스왑-인 후 n++ 실행

5.1. 예제-5

  • 수정된 페이지를 스왑 영역에 쓰기
  • 시간이 흐르고 운영체제가 빈 프레임을 만들기 위해 페이지 30을 희생 페이지로 선택하였다면, 다음과 같이 처리
    • 페이지 테이블 항목에 M비트=1이라면, 운영체제는 페이지 30이 들어 있는 프레임을 스왑-영역에 다시 기록
    • 하지만, M비트=0이라면(적재된 후 수정되지 않음) 스왑 영역에 저장할 필요가 없음. 그냥 페이지 30이 있었던 프레임에 다른 프로세스의 페이지를 적재하면 됨.

5.2. Page fault 해결

5.2. Page fault 해결

6. fork() 다시보기

  • 프로세스는 부모 프로세스의 fork() 시스템 호출로 생성
  • fork()를 사용하는 이유 중 하나는…
    • “매번 프로세스를 처음부터 만드는게 너무 무거워요! 있는거 복사해서 하는게 간편해요!”
    • 질문: 있는거 복사하는건 시간 오래걸리는 작업아닌가?
      • 만약에 프로세스가 4GB를 정말 다쓴다면… → 이것의 fork()는 4GB를 복사해야한다. → 낭비낭비낭비!

6. fork() 다시보기

  • 많은 응용프로그램들이, fork() 후 생성된 자식프로세스가 exec()를 호출하여 곧 바로 다른 프로그램을 실행하도록 작성되는 경우가 많다…
    • int pid= fork(); if(!pid) execlp(“/bin/ls”, “ls”, NULL);
    • execlp()에 의해 자식 프로세스의 메모리가 모두 반환되고 실행파일 ls로부터 새로 페이지 적재
  • 낭비가 심해도 너무 심하다!

6. fork() 다시보기-2

6.1. COW, Copy-on-write

  • 쓰기 시 복사
    • 자식 프로세스를 위해 부모 프로세스의 페이지 테이블만 복사
    • 자식 프로세스는 초기에 부모 프로세스의 메모리 프레임을 완전 공유
    • 자식 프로세스의 페이지 테이블 항목에 ‘쓰기시 복사’ 표시
    • 자식이나 부모 중 누군가 페이지를 수정할 때, 그때 새로운 프레임 할당 받아 내용을 수정하고 프레임 번호 업데이트!
  • 즉, 실제론 페이지 테이블만 복사가 일어나는 것만으로 새로운 프로세스가 하나 생성!

6.1. COW-1

6.1. COW-2

6.1.1. 장점

  • 프로세스 생성 시간 절약
    • 부모 프로세스의 페이지 테이블만 복사하여 자식 프로세스를 만들기 때문에 프로세스 생성이 매우 빠름
    • fork() 후 exec()으로 인한 괜한 복사 시간의 낭비 없음
  • 메모리 절약
    • 부모와 자식 프로세스가 둘 다 읽기만 하는 페이지는 새로운 프레임을 할당할 필요가 없으므로 메모리 절약
    • 예) 프로세스의 코드 페이지. 코드와 같이 읽기 용 페이지 프레임은 자동 공유

7. 생각해 볼 문제

  • Page 가 물리 메모리에 없다? → Page fault
    • Page fault가 생기면? → 디스크에서 가져와야지.
    • ㅇㅋ. 가져는 왔다. 이제 메모리 어디에 둘 것인가?
      • 메모리가 비어있으면 → 문제 없다
      • 메모리가 꽉 차있으면?
        • 누군간 방빼야지! → 누구를? ⇒ 페이지 교체 문제
    • 앞으로 페이지 폴트가 덜 나게는 못할까? ⇒ 프레임 할당 문제
  • 요걸 잘 해결하면, 요구 페이징의 성능이 향상됩니다! 페이지 폴트를 줄여서!
이 포스팅은 작성자의 CC BY-NC 4.0 라이선스를 준수합니다.