운영체제 : 주메모리 관리

김가영·2021년 6월 3일
3

computer-science

목록 보기
5/11
post-thumbnail

시작하기

프로세스는 실행중인 프로그램 (메모리에 적재된 프로그램)이라고 이야기했다. 메모리는 각각 주소가 할당된 일련의 바이트로 구성된다. CPU 는 PC가 지시하는 대로 명령어 하나를 가져와서fetch 실행한다. 이 명령어는 추가로 데이터를 또 가져올 수도 있고, 반대로 데이터를 메모리로 내보낼 수도 있다.

Basic Hardware

- 각각의 프로세스가 독립된 메모리 공간을 가지도록 보장해야 한다.
특정 프로세스만 접근할 수 있는 합법적인(legal) 메모리 주소 영역을 설정하고, 프로세스가 이러한 합법적인 영역만을 접근하도록 해야한다.
base registerlimit register, 두 개의 레지스터를 사용하여 보호한다. base register는 가장 작은 합법적인 물리 메모리 주소 값을 저장하고, limit register는 주어진 영역의 크기를 저장한다.

주소의 할당

프로그램은 디스크에 binary executable file로 존재한다. 얘를 메모리에 적재되면 프로세스가 된다.

실제로 a=1 이라는 명령어가 존재한다고 할 때 컴파일러는 symbolic하게 생성된 이러한 a의 주소(symbolic address)를 relocatable address(예를 들면 '이 모듈의 첫 번째 바이트로부터 열네 번째 바이트 주소')와 binding 시킨다.
→ 그리고 linker나 loader가 이러한 relocatable address를 절대 주소(absolute address)와 바인딩한다.

Logical address vs Physical Address

  • logical address : CPU가 생성하는 주소
  • physical address : 메모리가 취급하게 되는 주소
  • logical address space(논리 주소 공간) : 프로그램에 의해 생성된 모든 논리 주소 집합
  • physical address space(물리 주소 공간) : 이 논리 주소 공간과 일치하는 모든 물리 주소 집합

MMU

프로그램 실행 중에는 이와 같은 논리 주소(또는 가상주소)를 물리 주소로 바꾸어줘야 한다. 이러한 변환 작업을 실행하는 곳이 바로 하드웨어 장치인 메모리 관리 장치(memory management unit, MMU).

  • relocation register: a base register in MMU

Dynamic loading 동적 적재

프로세스가 실행되기 위해서는 메모리에 올라와야 하는데, 프로그램 전체를 메모리에 로드해야할까?
→ 메모리 공간을 효율적으로 사용하기 위해서 프로그램의 일부만을 load해주는 것.

각 루틴은 실제 호출되기 전까지는 메모리에 올라오지 않고, 재배치 가능한 상태로 디스크에서 대기한다. 필요한 경우에만 루틴을 적재하는 것.

Dynamic Linking & Shared Libraries

동적 연결 및 공유 라이브러리

  • DLL(동적 연결 라이브러리 또는 shared library) : 사용자 프로그램이 실행될 때, 사용자 프로그램에 연결되는 시스템 라이브러리. 프로세스간 라이브러리 공유가 가능해서 메인 메모리에 DDL 인스턴스가 하나만 존재해도 된다(→ shared library)

  • static linking : 시스템 라이브러리가 loader가 binary program code에 끼어들어간다.

  • dynamic linking(동적 연결) : 실행하는 중에 필요한 부분만 DLL 파일에 access하여 Linking하는 것, 동적 적재와 비슷하다.

연속 메모리 할당

프로세스한테 메모리를 할당하는 방식.

가장 간단한 방법 : 각 프로세스를 다른 프로세스의 영역과 인접한 하나의 메모리 영역에 적재 → contiguous memory allocation(연속 메모리 할당)

외부 단편화가 많이 일어난다.

메모리 보호

relocation register + limit register 을 이용하여 자기가 소유하지 않은 메모리에 접근할 수 없게 강제할 수 있다.

메모리 할당

variable-partition

가장 간단한 방법.

각 partition에는 하나의 프로세스만 적재될 수 있다.

  • hole: a block of available memory

그렇다면 여러개의 hole이 있을 때 어떤 hole에 할당해야할까?

  • first fit : 가장 첫번째 available memory에 할당
  • best fit : 사용 가능한 공간 중 가장 작은 곳
  • worst fit : 사용 가능한 공간 중 가장 큰 곳

단편화

  • external fragmentation(외부 단편화) : 작업에 충분한 메모리 공간이 남아있지만, 작은 hole로 나뉘어 있어 실제 이용이 불가능한 상태

  • internal framgmentation(내부 단편화) : 할당된 공간이 요구된 공간보다 조금 더 커서 그 사이의 남는 공간

contiguous memory allocation을 사용하면 외부 단편화, 페이징을 하면 내부 단편화 현상이 생긴다.

segmentation

통째로 메모리를 옮기는 것을 배웠다. 다음 시간에 배울 페이징은, 쪼개서 옮기는 것. 그 중간이 바로 segmentation. 쪼개긴 쪼개는데, 종류별로 쪼개는 것. subroutine-stack-symbol table/ variable size이므로 외부 단편화는 피할 수 없다.

paging이 주로 사용되기 때문에 교재에서 깊게 다루지는 않는다.

페이징

process의 물리적인 주소를 연속적이지 않게 쪼갠다. 연속 메모리 할당의 외부 단편화 발생을 방지하고, 압축(외부 단편화를 해결하기 위해 여러개의 hole들을 모아 하나의 hole로 만드는 것)의 필요성도 없애준다.

os와 hard ware의 협력

Basic Method

물리적인 메모리를 고정된 크기로 자른다(프레임). 논리 메모리도 같은 크기의 블록으로 잘리는데 page라고 불린다.

→ 논리 메모리 공간과 물리 메모리 공간의 연결이 끊어진다. 그 mapping은 운영체제가 알아서 해줘라.

논리 메모리는 페이지 넘버(p)와 페이지 오프셋(d). (ex : 2, 34) 두가지로 구성된다.

페이지 넘버는 각 프레임의 시작 주소인 프레임 테이블에 접근할 때 사용(인덱스임)되며, 페이지 오프셋은 하나의 프레임 안에서의 위치이다.

페이지 사이즈?

2의 거듭제곱이어야 함.

페이지 크기가 작으면, 페이지 테이블 크기가 커지고, 메모리가 낭비된다.

만약 logical address space 가 2^m, page size가 2^n 바이트라면, page number 은 (m-n), page offset은 n 비트 필요하다.

새로운 프로세스가 등장하면?

프로세스가 페이지를 몇개를 필요로 하는 지 조사한다. n개의 페이지를 요구한다면 실제로 n개의 프레임이 메모리에서 사용 가능한지 확인하여 프레임을 프로세스에 할당한다.

하드웨어 지원?

CPU 스케쥴러가 다음 프로세스를 결정하면, page table도 context switch를 위해 다시 로드돼야할 것이다. 페이지 테이블도 엄청 크다.
PTBR(page-table base register): 페이지 테이블 자체를 메인 메모리에 두고, 이러한 page table을 가리키는 포인터를 저장하는 것. context switch 속도는 감소시키지만, 메모리 access 시간은 증가한다. 왜? 페이지 테이블에 접근하기 위해 PTBR에 접근한 후 실제 데이터에 접근하니까, 두번씩 접근을 하게 된다.

TLB(Transloation Look-aside Buffer): 캐시 메모리를 써서, page table 일부를 저장하는 것. 하드웨어에 저장하는 것이기 때문에 굉-장히 빠르다. TLB에 있으면 빠르게 참조하고, 없으면 페이지 테이블 메모리 참조를 한다.

  • effective memory-access time:
    TLB hit : 찾으려는 page number가 TLB에 있을 때
    TLB miss : 찾으려는 page number가 TLB에 없을 때
    hit ratio : 찾으려는 page number가 TLB에서 발견되는 비율

memory protection

contiguous는 시작주소와 끝주소를 알 수 있기에, legal한 주소인지를 간단하게 판단할 수 있다.
페이징의 경우에는 protection bit를 사용한다.

valid-invalid bit 을 page table의 시작에 추가한다.

shared page

페이징의 장점, 공통의 코드를 공유할 수 있다.

만약 코드가 reentrant code 라면 공유 가능.

  • reentrant code :
    실행 중에 변경될 일이 없는 코드

페이지 테이블의 구조

페이지 테이블이 클 때, 이를 관리하는 방법

  • 계층적 페이징
  • 해시 페이지 테이블
  • 역 페이지 테이블

계층적 페이징, hierarchical paging

page table에 다시 page table을 만들어버리는 것

해시 페이지 테이블, hashed page table

역 페이지 테이블, Inverted Page Table

pid(프로세스의 고유번호)를 추가한다. 가장 효율적.

스와핑

physical memory space보다 훨씬 큰 프로그램도 존재할 수 있겠지? 실행 중에 프로세스 혹은 프로세스의 일부분을 임시로 백업 저장장치에 보냈다가 다시 가져오는 것을 스와핑이라고 한다.

standard swapping

전체 프로세스를 메모리와 disk 사이에서 스와핑하는 것.

  • 메모리에 가져오는 것 : swap in
  • 백업 저장장치로 옮기는 것 : swap out

페이징에서의 스와핑

페이지 단위로 스와핑하는 것
→ 오늘날은 그냥 paging이 페이징에서의 스와핑으로 부르면서 page out, page in용어를 쓰기로 한다.

가상 메모리에서 중요한 역할을 한다.

profile
개발블로그

0개의 댓글