본문 바로가기
{ Computer Science }/Operating System

[운영체제OS]7. 메모리 관리 -1(주소 바인딩, 메모리 할당)

by ggyongi 2021. 3. 6.
반응형

********************************

##이 글은 제가 공부하고 있는 책을 요약해놓은 것이므로 본문 내용만 봐선 이해가 어려울 수 있습니다.

 

목차

1. 주소 바인딩

2. 메모리 관리와 관련된 용어

3. 물리적 메모리의 할당 방식

********************************

 

주소란 서로 다른 위치를 구분하기 위해 사용하는 일련의 숫자. 컴퓨터는 이진수를 사용하므로 메모리 주소는 이진수로 매겨짐. 보통의 컴퓨터 시스템은 32비트 혹은 64비트의 주소 체계를 사용하고, 32비트의 경우 2의 32승가지의 서로 다른 메모리 위치를 구분할 수 있음. 컴퓨터에서는 byte 단위로 메모리 주소를 부여하기 때문에 2의 32승 바이트만큼의 메모리 공간에 서로 다른 주소를 할당할 수 있다. 근데 컴퓨터 상의 주소는 32비트를 그대로 사용하지 않고 효율적인 운영을 위해 연속된 일련의 영역을 묶어서 사용. 보통 4KB(=2^12byte) 단위로 묶어서 페이지(page)라는 하나의 행정구역을 만든다. 페이지 하나의 크기가 2^12바이트이므로 페이지 내에서 바이트별 위치 구분을 위해선 12비트가 필요. 따라서 총 32비트의 주소 중 하위 12비트는 페이지 내에서의 주소를 나타내게 되는 것. 

 

1. 주소 바인딩

주소 공간:(address space): 프로개름이 실행을 위해 메모리에 적재되면 그 프로세스를 위한 독자적인 주소공간이 생성됨. 논리적 주소(logical address)혹은 가상 주소(virtual address)라고 부른다. 논리적 주소는 0번지부터 시작.

물리적 주소(physical address): 물리적 메모리에 실제로 올라가는 위치. 낮은 주소 영역에는 운영체제가 올라가고, 높은 주소 영역에는 사용자 프로세스들이 올라감. 

CPU가 기계어 명령 수행을 위해 논리적 주소를 통해 메모리 참조를 하게 되면 해당 논리적 주소가 물리적 메모리의 어느 위치에 매핑되는지 확인해야함. 이때 논리적 주소를 물리적 메모리 주소로 연결시켜주는 작업을 주소 바인딩(address binding)이라고 한다. 

 

주소 바인딩 방식의 세가지 분류: 컴파일 타임 바인딩/로드 타임 바인딩/실행시간 바인딩

컴파일 타임 바인딩(compile time binding): 컴파일을 하는 시점에 해당 프로그램이 물리적 메모리의 몇 번지에 위치할 것인지를 결정. 프로그램이 절대주소로 적재된다는 뜻에서 절대코드를 생성하는 바인딩 방식이라고 말하기도 함. 프로그램이 올라가 있는 물리적 메모리의 위치를 변경하려면 컴파일을 다시 해야함. 현대의 시분할 컴퓨팅 환경에서는 잘 사용하지 않는 기법.

로드 타임 바인딩(load time binding): 프로그램 실행이 시작될 때 물리적 메모리 주소가 결정. 로더(loader)의 책임하에 물리적 메모리 주소가 부여되며 위치가 고정됨. 로더란 사용자 프로그램을 메모리에 적재시키는 프로그램이다. 이 바인딩 방식은 컴파일러가 재배치 가능 코드(relocatable code)를 생성한 경우에 가능.

실행시간 바인딩(execution time binding/run time binding): 프로그램 실행 후에도 그 프로그램위 메모리상의 주소가 변경될 수 있는 바인딩 방식. CPU가 주소를 참조할 때마다 해당 데이터가 물리적 메모리의 어느 위치에 존재하는지 주소 매핑 테이블(address mapping table)을 이용해 바인딩을 점검. 또한 다른 방식들과 달리 기준 레지스터(base register)한계 레지스터(limit register)를 포함해 MMU(Memory Management Unit)라는 하드웨어적인 지원이 뒷받침 되어야 함. MMU는 논리적 주소를 물리적 주소로 매핑해주는 하드웨어 장치.

 

MMU 기법(MMU scheme): CPU가 특정 프로세스의 논리적 주소를 참조하려 할 때 MMU 기법은 그 주소값에 기준 레지스터 값을 더해 물리적 주소값을 얻어냄. 이때 기준 레지스터는 재배치 레지스터(relocation register)라고도 부르며 그 프로세스의 물리적 메모리 시작 주소를 가지고 있음. MMU 기법은 프로그램 주소공간이 물리적 메모리의 한 장소에 연속적으로 적재되는 것으로 가정. 시작 주소만 알면 주소 변환이 쉽기 때문에 사용자 프로그램이나 CPU는 논리적 주소만을 다룰 뿐, 실제 물리적 주소는 알지 못하며 알 필요도 없음. 프로세스는 자신만의 고유 주소공간을 가지고 있으므로 동일한 주소값이라 해도 각 프로세스마다 서로 다른 내용을 담고 있음. CPU가 논리적 주소 100번지를 참조한다했을 때 프로세스에 따라 이 100번지가 가리키는 내용은 달라짐. MMU 기법에서는 문맥교환으로 CPU에서 수행 중인 프로세스가 바뀔 때마다 재배치 레지스터 값을 그 프로세스에 해당하는 값으로 재설정함으로써 각 프로세스에 맞는 서로 다른 100번지 위치에 접근. 

한편 다중프로그래밍 환경에서 물리적 메모리 안에는 여러 개의 프로세스가 올라가 있음. 따라서 MMU 방식을 사용하여 주소변환을 할 경우 CPU가 요청한 논리적 주소값+재배치 레지스터의 결과가 해당 프로세스의 주소 공간을 벗어나는 경우가 발생할 수 있음. 이 경우 메모리 보안이 이뤄지지 않아 시스템에 치명적인 결과를 초래할 수 있다. 이를 방지하기 위해 운영체제는 한계 레지스터라는 또 하나의 레지스터를 사용. 자신의 주소 공간을 넘어서는 메모리 참조를 하려고 하는지 체크하는 용도. 현재 CPU에서 수행 중인 프로세스의 논리적 주소의 최댓값, 즉 그 프로세스의 크기를 담고 있음. 즉 CPU에서 요청한 프로세스의 논리적 주소값이 한계 레지스터 내에 저장된 그 프로세스의 크기보다 작은지 확인. 벗어날 경우 트랩을 발생시켜 해당 프로세스를 강제종료시킴.

 

2. 메모리 관리와 관련된 용어

 

-동적로딩

동적로딩(dynamic loading): 여러 프로그램이 동시에 메모리에 올라가서 수행되는 다중 프로그래밍 환경에서 메모리 사용의 효율성을 높이기 위해 사용. 동적로딩에서는 프로세스가 시작될 때 프로세스의 주소 공간 전체를 메모리에 다 올려놓지 않고 해당 부분이 불릴 때 그 부분만을 메모리에 적재. 실제로 프로그램 코드의 상당 부분은 오류 처리루틴과 같이 가끔 사용되는 방어용 코드이다. 따라서 프로세스의 주소 공간 전체를 물리적 메모리에 올리는 건 메모리 낭비가 될 수 있다. 동적로딩은 기존 방식에 비해 더 많은 프로그램을 적재할 수 있어서 메모리 이용의 효율성이 향상됨. 또한 운영체제의 특별한 지원없이 프로그램 자체에서 구현이 가능. 

 

-동적연결

연결(linking)이란 프로그래머가 작성한 소스 코드를 컴파일하여 생성된 목적 파일(object file)과 이미 컴파일된 라이브러리 파일들을 묶어 하나의 실행파일을 생성하는 과정을 말한다. 동적연결(dynamic linking)은 컴파일을 통해 생성된 목적 파일과 라이브러리 파일 사이의 연결을  프로그램의 실행 시점까지 지연시키는 기법. 반대개념인 정적연결(static linking)은 프로그래머가 작성한 코드와 라이브러리 코드가 모두 합쳐져 실행파일이 생성됨. 따라서 실행 파일 크기가 상대적으로 크며 동일한 라이브러리를 각 프로세스가 개별적으로 메모리에 적재해야 하므로 물리적 메모리가 낭비됨. 이에 비해 동적연결에서는 라이브러리가 실행 시점에 연결되기 때문에, 실행파일에 라이브러리 코드가 포함되지 않으며 프로그램이 실행되면서 라이브러리 함수를 호출할 때 라이브러리에 대한 연결이 이루어짐. 동적연결을 가능하게 하기 위해 실행파일의 라이브러리 호출 부분에 해당 라이브러리의 위치를 찾기 위한 스텁(stub)이라는 작은 코드를 둔다. 스텁을 통해 라이브러리가 메모리에 이미 존재하는지 살펴보고 그럴 경우 그 주소의 메모리 위치에서 직접 참조, 그렇지 않을 경우 디스크에서 동적 라이브러리 파일을 찾아 메모리로 적재한 후 수행. 동적 연결은 다수의 프로그램이 공통으로 사용하는 라이브러리를 메모리에 한번만 적재하므로 메모리 효율성을 높임. 동적연결 기법은 운영체제 지원이 필요. 

 

-중첩

중첩(overlays)이란 프로세스의 주소 공간을 분할, 필요한 부분만을 메모리에 적재하는 기법. 동적로딩과 유사하지만 사용 이유가 다름. 동적로딩은 메모리에 더 많은 프로세스를 동시에 올려놓고 실행하기 위한 용도인 반면, 중첩은 단일 프로세스만을 메모리에 올려놓는 환경(초창기의 컴퓨터시스템)에서 메모리 용량보다 큰 프로세스를 실행하기 위한 어쩔 수 없는 선택이었다. 중첩은 운영체제 지원없이 프로그래머에 의해 구현. 수작업 중첩(manual overlays)이라고도 부른다. 하지만 이는 상당히 복잡한 작업. 

 

-스와핑

스와핑(swapping)이란 메모리에 올라온 프로세스의 주소 공간 전체를 디스크의 스왑 영역(swap area)에 일시적으로 내려놓는 것. 스왑 영역을 백킹스토어(backing store)라고도 함. 디스크 내에 파일 시스템과는 별도로 존재하는 일정 영역. 스왑 영역은 프로세스가 수행 중인 동안에만 디스크에 일시적으로 저장하는 공간이므로 저장 기간이 짧은 저장공간. 스왑 영역은 다수의 사용자 프로세스를 담을 수 있을 만큼 충분히 큰 저장공간이어야 하고 어느 정도 접근 속도가 보장되어야 함. 주의할 점은 스와핑 개념이 프로세스가 종료되어 그 주소 공간을 디스크로 내쫓는 게 아니라, 특정한 이유로 수행중인 프로세스의 주소 공간을 일시적으로 메모리에서 디스크로 내려놓는 것. 스와핑의 작업 방향에 따라 스왑 인(디스크->메모리)/ 스왑 아웃(메모리->디스크)이라고 부름. 

스와핑 과정은 스와퍼(swapper)라고 불리는 중기 스케줄러(medium-term scheduler)에 의해 스왑 아웃시킬 프로세스를 선정해 그 프로세스에 대해서 메모리에 올라가 있는 주소 공간의 내용을 통째로 디스크 스왑영역에 스왑 아웃시킴. 스와핑의 가장 중요한 역할은 메모리에 존재하는 프로세스의 수를 조절하는 것. 앞의 컴파일 타임 바인딩 방식로드 타임 바인딩 방식에서는 스왑 아웃된 프로세스가 스왑 인될 때 원래 존재하던 메모리 위치로 올라가야 한다. 반면 실행시간 바인딩 기법에선 빈 메모리 영역 아무곳에나 올릴 수 있다. 

스와핑에선 보통 디스크내의 스왑 영역에 프로세스 주소 공간이 순차적으로 저장되기 때문에 스와핑에 소요되는 시간은 디스크의 탐색시간(seek time)이나 회전지연시간(rotational latency)보다는 디스크 섹터에서 실제 데이터를 읽고 쓰는 전송시간(transfer time)이 대부분.

 

3. 물리적 메모리의 할당 방식

물리적 메모리는 운영체제 상주 영역과 사용자 프로세스 영역으로 나뉘어 사용된다.

운영체제 상주 영역: 인터럽트 벡터와 함께 물리적 메모리의 낮은 주소 영역 사용, 운영체제 커널이 이곳에 위치.

사용자 프로세스 영역: 물리적 메모리의 높은 주소 영역을 사용, 여러 사용자 프로세스들이 이곳에 적재되어 실행.

사용자 프로세스 영역의 관리 방법: 연속할당/ 불연속할당

연속할당(contiguous allocation): 각각의 프로세스를 물리적 메모리의 연속적인 공간에 올리는 방식. 물리적 메모리를 다수의 분할로 나누어 하나의 분할에 하나의 프로세스를 적재. 분할을 관리하는 방식에 따라 고정분할 방식과 가변분할 방식으로 다시 나뉨.

-고정분할(fixed partition allocation): 물리적 메모리를 고정된 크기의 분할로 미리 나누어두는 방식

-가변분할(variable partition allocation): 분할을 미리 나누어놓지 않은 채 프로그램이 실행되고 종료되는 순서에 따라 분할을 관리

불연속할당(noncontiguous allocation): 하나의 프로세스를 물리적 메모리의 여러 영역에 분산해 적재. 페이징 기법, 세그먼테이션기법, 페이지드 세그먼테이션 기법 등이 있다.

 

1) 연속 할당 방식

고정분할 방식: 물리적 메모리를 주어진 개수만큼의 영구적인 분할로 미리 나눠두고 각 분할에 하나의 프로세스를 적재해 실행. 분할의 크기는 모두 다를 수도 있다. 연속 할당 방식은 동시에 메모리에 올릴 수 있는 프로그램 수가 고정됨. 수행 가능한 프로그램의 최대 크기 또한 제한됨. 외부조각과 내부조각이 발생할 수 있다. 외부조각은 프로그램의 크기보다 분할의 크기가 작은 경우 해당 분할이 비어있는데도 프로그램을 적재하지 못해 낭비되는 메모리 공간. 내부조각은 프로그램의 크기보다 분할의 크기가 큰 경우 해당 분할에 프로그램 적재 뒤 남게되는 메모리 공간을 뜻함.

 

가변분할 방식: 프로그램의 크기에 따라 분할의 크기, 개수가 동적으로 변하는 방식. 가변분할 방식에선 분할의 크기를 프로그램 크기보다 일부러 크게 할당하진 않기 때문에 내부조각이 발생하지 않는다. 하지만 이미 메모리에 존재하는 프로그램이 종료될 경우 중간에 빈공간이 발생하여, 이 공간이 새 프로그램 크기보다 작을 경우 외부조각이 발생할 가능성이 있다. 가변분할 방식에서의 주요 쟁점은 크기 n의 프로세스를 메모리에 올릴 때 물리적 메모리 내 가용 공간 중 어떤 위치에 올릴 지 결정하는 문제. 이를 동적 메모리 할당 문제(dynamic storage-allocation problem)이라고 부른다. 운영체제는 가용 공간을 더 효율적으로 관리하기 위해 사용중인 메모리 공간과 사용하고 있지 않은 가용 공간에 대한 정보를 유지하고 있다. 

동적 메모리 할당 문제 해결 방법 3가지: 최초적합/ 최적적합/ 최악적합

최초적합(first-fit)방법: 가용 공간을 차례대로 살펴보며 프로그램 크기보다 큰 가용 공간이 최초로 발견되면 그 공간에 프로그램을 올림. 가용 공간을 모두 탐색하지 않기 때문에 시간적 측면에서 효율적.

최적적합(best-fit)방법: 크기가 n 이상인 가장 작은 가용 공간을 찾아 그곳에 프로그램을 올림. 모든 가용 공간 리스트를 탐색하므로 시간적 오버헤드 발생. 공간적 측면에선 효율적. 

최악적합(worst-fit)방법: 가용 공간 중에서 가장 크기가 큰 곳에 새로운 프로그램을 할당. 모든 가용 공간 리스트를 탐색. 

컴팩션(compaction): 가변분할 방식에서 외부조각 문제를 해결하기 위한 방법. 컴팩션은 물리적 메모리 중에서 프로세스에 의해 사용 중인 메모리 영역을 한 쪽으로 몰고 가용 공간들을 다른 한쪽으로 모아서 하나의 큰 가용 공간을 만드는 방법. 현재 수행 중인 프로세스의 메모리상의 위치를 상당 부분 이동시켜야 하므로 비용이 매우 많이 드는 작업. 또한 수행 중인 프로세스의 물리적 메모리 위치를 옮겨야 하므로 실행시간 바인딩 방식이 지원되는 환경에서만 수행될 수 있음.

 

2) 불연속할당 기법

페이징 기법: 하나의 프로그램을 분할하는 기준에 따라 동일한 크기로 나누어 메모리에 적재.

세그먼테이션 기법: 크기는 일정하지 않지만 의미 단위로 나누어 메모리에 적재.

페이지드 세그먼테이션 기법: 세그먼테이션을 기본으로 하되 이를 다시 동일 크기의 페이지로 나누어 메모리에 적재.

 

비전공자 네카라 신입 취업 노하우

시행착오 끝에 얻어낸 취업 노하우가 모두 담긴 전자책!

kmong.com

댓글