본문 바로가기
CS/운영체제

메인 메모리 관리

by yhsim98 2022. 8. 14.

프로그램을 메모리에 올리기

  • 메모리 구조
    • 주소(Address) + 데이터(Data)
  • 프로그램 개발
    • Source file : 고수준 언어
    • Object file : 컴파일 또는 어셈블 결과
    • Excutable file : 링크 결과
  • 컴파일러, 어셈블러, 링커, 로더
    • 컴파일러 : Source file을 Object file로
    • 링커 : Object file과 라이브러리를 결합하여 실행 파일 생성
    • loader : 실행 파일을 메모리에 적제
  • 프로그램 실행
    • 프로그램의 실행을 위해서는 3가지가 메모리에 들어간다
    • code + data + stack
    • code는 기계어 즉 코드
    • data는 data
    • stack
  • 실행 파일을 메모리에 올리기
    • 메모리의 어느 주소에 올릴 것인가?
      • loader가 결정한다
      • 적재 시 매번 물리적인 주소는 달라진다
        • 멀티 프로그래밍 환경에서 다른 프로그램도 게속 올라오고 내려간다
        • 메모리 환경이 게속 달라짐
      • CPU는 MMU 참조하여 일관적으로 접근 가능, MMU 사용하여 mapping
        • CPU는 Memory Menagement Unit을 경유하여 메모리에 접근
        • MMU에 프로세스가 메모리에 저장되있는 시작 주소를 넣는다
        • CPU 입장에서는 그냥 주소 참조, 실제로는 시작 주소 + 주소
          • CPU가 3을 조회, MMU의 시작 주소가 5면 실제로는 8 조회
        • MMU는 애플리케이션이 악의적으로 다른 영역을 접근하도록 하는 것도 막는다

메모리 적재 방법

Dynamic Loading

  • 프로그램 실행에 반드시 필요한 루틴/데이터만 적재한다
    • 모든 루틴이 다 사용되는 것은 아니다(ex: 오류 처리)
    • 모든 데이터가 다 사용되는 것은 아니다(ex: 배열)
    • 자바 : 모든 클래스가 다 사용되는 것은 아니다(class loader)
    • 실행 시 필요하면 그때 해당 부분을 메모리에 올린다

Dynamic Linking

  • 여러 프로그램에 공통 사용되는 라이브러리
    • 공통 라이브러리 루틴를 메모리에 중복으로 올리는 것은 낭비
    • 라이브러리 루틴 연결을 실행 시까지 미룬다
    • 오직 하나의 라이브러리 루틴만 메모리에 적재되고
    • 다른 애플리케이션 실행 시 이 루틴만 연결된다
    • 리눅스에서는 공유 라이브러리, 윈도우에서는 동적 연결 라이브러리

Swapping

  • 메모리에 적재되어 있으나 현재 사용되지 않고 있는 프로세스 이미지
    • 메모리 활용도 높이기 위해 swap device(하드 디스크) 로 몰아내기
      • swap-out, swap-in
    • Relocation register 사용으로 적재 위치는 무관
      • 메인 메모리에는 Relocation register을 통해 접근한다
    • 프로세스 크기가 크면 backing store 입출력에 따른 부담이 크다

연속 메모리 할당

프로세스를 연속된 메모리 공간에 통째로 할당하는 방식

외부 단편화가 일어날 수 있다

외부 단편화

  • whole : 메모리에 있는 빈 공간
  • 외부 단편화란 공간은 충분하나 whole 이 연속되지 않아 프로세스 적재를 할 수 없는 것
  • 프로세스가 연속해서 할당되더라도 반납되고 새로 할당되고 반복되면 프로세스 사이에 빈 공간이 생긴다

연속 메모리 할당 방식

  • First fit
    • whole 에 순차적으로 적재하는 방식
    • 연산이 필요 없어 속도는 빠르다
  • Worst fit
    • 가장 크기의 차이가 큰 whole에 적재하는 방식
    • 비교적 메모리 이용률이 높았다
  • best fit
    • 프로세스와 가장 크기가 비슷한 whole에 적재
    • 비교적 메모리 이용률이 높았다

셋 중 어떤 방식을 사용하더라도 전체 메모리의 1/3은 사용하지 못한다.

그래서 나온 방식이 compaction

  • compaction
    • 프로세스의 메모리를 정리해서 whole을 한곳으로 모으는 것
    • 최적 알고리즘은 존재하지 않는다
    • 계산할 것이 많다
    • 부담이 많다

가변 메모리 할당

페이징

  • 프로세스를 일정한 단위로 분할하여 메모리에 적재하는 방식

    • 프로세스는 페이지(page)의 집합
    • 메모리는 프레임(frame)의 집합
  • 페이지를 프레임에 할당

    • MMU 내의 재배치 레지스터 값을 바꿈으로서
    • CPU는 프로세스가 연속된 메모리 공간에 위치한다고 착각
      • MMU안에 relocation register를 여러 개 두고 CPU는 MMU를 통해 메모리에 접근한다.
      • 때문에 CPU입장에서는 프로세스가 연속되어 있다.
    • 이러한 MMU는 페이지 테이블(page table)이 된다

외부 단편화는 없지만, 일정한 크기로 분할하기 때문에 내부 단편화가 일어난다.

  • 내부 단편화
    • 프로세스 크기가 페이지 크기의 배수가 아니라면
    • 마지막 페이지는 한 프레임을 다 채울 수 없다
    • 남은 공간은 메모리 낭비로 이어진다
    • 외부 단편화에 비해서는 미미하다

주소 변환

cpu는 논리 주소로 메모리에 접근하게 되고, 페이지 테이블이 이런 논리 주소를 물리 주로로 변환하여 준다

  • 논리 주소(Logical address)
    • CPU가 내는 주소는 2진수로 표현
    • 하이 n 비트는 offset
    • 상위 m-n비트는 페이지 번호
  • 주소 변환 : 논리주소 -> 물리주소
    • 페이지 번호(p)는 페이지 테이블 인덱스 값
      • p에 해당되는 테이블 내용이 프레임 번호(l)
    • 변위(d)는 변하지 않음

보호와 공유

  • 보호 : 해킹 등 방지
    • 모든 주소는 페이지 테이블을 경유하므로
    • 페이지 테이블 엔트리마다 r, w, x 비트 두어
      • read, write, execute
    • 해당 페이지에 대한 접근 제어 가능
  • 공유 : 메모리 낭비 방지
    • 같은 프로그램을 쓰는 복수 개의 프로세스가 있다면
      • ex) 아래한글 여러 개 실행
    • code + stack + data 에서 code는 공유 가능
    • 프로세스의 페이지 테이블 코드 영역이 같은 곳을 가리키게 한다
    • 물론 한 프로세스가 코드를 변경하면 안된다
      • 이것을 non-self modifying code 라 한다
      • 컴퓨터 용어로는 pure code 라 한다

세그멘테이션

프로세스를 논리적인 단위(세그먼트)로 분할하여 메모리에 적재하는 방식

  • 프로세스는 세그먼트의 집합

  • 세그먼트의 크기는 일반적으로 같지 않다

  • 세그먼트를 메모리에 할당

    • MMU 내의 재배치 레지스터 값을 바꿈으로서
    • CPU는 프로세스가 연속된 메모리 공간에 위치한다고 착각

주소 변환(Address Translation)

  • 논리주소(Logical address)
    • CPU가 내는 주소는 segment 번호(s) + 변위(d)
  • 주소변환: 논리주소 -> 물리주소
    • 세그먼트 테이블 내용 : base + limit
    • 세그먼트 번호(s)는 세그먼트 테이블 인덱스 값
    • s에 해당되는 테이블 내용으로 시작 위치 및 한계값 파악
    • 한계(limit)를 넘어서면 segment violation 예외 상황 처리
    • 물리주소 = base[s] + d

보호와 공유

  • 보호
    • 모든 주소는 세그먼트 테이블을 공유하므로
    • 세그먼트 테이블 엔트리마다 r, w, x 비트 두어
    • 해당 세그먼트에 대한 접근 제어 가능
      • limit를 통해 접근 제한
  • 공유 : 메모리 낭비 방지
    • 같은 프로그램을 쓰는 복수 개의 프로세스가 있다면
      • ex) 아래한글 여러 개 실행
    • code + stack + data 에서 code는 공유 가능
    • 프로세스의 세그먼트 테이블 코드 영역이 같은 곳을 가리키게 한다
    • 물론 한 프로세스가 코드를 변경하면 안된다
      • 이것을 non-self modifying code 라 한다
      • 컴퓨터 용어로는 pure code 라 한다

페이징과 세그멘테이션

  • 세그멘테이션은 의미 있는 단위로 자르기 때문에 페이징보다 보호와 공유 측면에서 더 나은 방법이다

    • 페이징은 일관적으로 자르다 보니 논리적으로 상관 없는 데이터가 묶일 수 있다
      • 코드와 데이터가 같은 프레임에 있다면 코드 실행 시 데이터에는 접근하면 안되지만
      • 페이지 테이블에서 막기가 곤란하다
    • 관계있는 세그먼트가 묶여 있기 때문에 공유하기도 좋다
  • 세그멘테이션은 외부 단편화가 발생할 수 있다

    • 세그먼트 크기는 고정이 아니라 가변적
    • 크기가 다른 각 세그먼트를 메모리에 두려면 동적 메모리 할당을 해야 한다
  • 세그멘테이션 + 페이징

    • 세그멘테이션은 보호와 공유면에서 효과적
    • 페이징은 외부 단편화 문제를 해결
    • 따라서 세그먼트를 페이징하자!?!?
      • CPU - 세그먼트 테이블 - 페이지 테이블 - 메모리
      • 주소 변환 과정을 여러 번 거쳐야 하므로 부담

'CS > 운영체제' 카테고리의 다른 글

blocking, non-blocking, Sync, Async  (0) 2022.08.27
가상 메모리  (0) 2022.08.14
Deadlock  (0) 2022.08.04
프로세스 동기화  (0) 2022.07.29
CPU Scheduling  (0) 2022.07.24