<운영체제와 정보기술의 원리> 반효경 저
- 주소(address): 서로 다른 위치를 구분하기 위해 사용하는 일련의 숫자로 구성됨
컴퓨터에서는 byte 단위로 메모리 주소를 부여하기 때문에 32비트 주소 체계를 사용하면 2^32바이트만큼의 메모리 공간에 서로 다른 주소를 할당할 수 있다. 한편 컴퓨터상의 주소는 32비트를 그대로 사용하지 않고 효율적인 운영을 위해 연속된 일련의 영역을 묶어서 사용한다.
- 페이지: 4KB(=2^12byte) 단위로 묶어서 만든 하나의 행정구역
1. 주소 바인딩
- 논리적 주소(logical address): 프로그램이 실행을 위해 메모리에 적재될 때 생성되는 그 프로세스를 위한 독자적인 주소 공간
- 물리적 주소(physical address): 물리적 메모리에 실제로 올라가는 위치
프로세스가 실행되기 위해서는 해당 프로그램이 물리적 메모리에 올라가 있어야 한다. 또한 CPU가 기계어 명령을 수행하기 위해 논리적 주소를 통해 메모리 참조를 하게 되면 해당 논리적 주소가 물리적 메모리의 어느 위치에 매핑되는지 확인해야 한다.
- 주소 바인딩(address binding): 프로세스의 논리적 주소를 물리적 메모리 주소로 연결시켜주는 작업
주소 바인딩의 방식은 프로그램이 적재되는 물리적 메모리의 주소가 결정되는 시기에 따라 세 가지로 분류할 수 있다.
- 컴파일 타임 바인딩: 프로그램을 컴파일 할 때 바인딩하는 방식
- 프로그램이 올라가 있는 물리적 메모리의 위치를 변경하고 싶다면 컴파일을 다시 하는 수고가 필요
- 로드 타임 바인딩: 프로그램의 실행이 시작될 때 바인딩하는 방식
- 컴파일러가 재배치 가능 코드를 생성한 경우에 가능
- 프로그램이 종료될 때까지 물리적 메모리상의 위치가 고정됨
- 실행시간 바인딩: 프로그램이 실행을 시작한 후에도 그 프로그램이 위치한 물리적 메모리상의 주소가 변경될 수 있는 방식
- CPU가 주소를 참조할 때마다 해당 데이터가 물리적 메모리의 어느 위치에 존재하는지 주소 매핑 테이블을 이용해 바인딩을 점검해야 함
- 기준 레지스터와 한계 레지스터를 포함해 MMU(Memory Management Unit)라는 하드웨어적 지원 필요
- MMU: 논리적 주소를 물리적 주소로 매핑해주는 메모리 관리 유닛
CPU가 특정 프로세스의 논리적 주소를 참조하려고 할 때 MMU 기법은 그 주소값에 기준 레지스터의 값을 더해 물리적 주소값을 얻어낸다.
- 기준 레지스터(base register): 그 프로세스의 물리적 메모리 시작 주소를 가지고 있는 것
- 재배치 레지스터라고도 부름
프로세스는 자기 자신만의 고유한 주소 공간을 가지고 있으므로 동일한 주소값이라 하더라도 각 프로세스마다 서로 다른 내용을 담고 있다. 따라서 CPU가 논리적 주소 100번지를 참조한다고 했을 때 현재 CPU에서 수행되고 있는 프로세스가 무엇인지에 따라 이 100번지가 가리키는 내용은 상이해진다. MMU 기법에서는 문맥교환으로 CPU에서 수행 중인 프로세스가 바뀔 때마다 재배치 레지스터의 값을 그 프로세스에 해당되는 값으로 재설정함으로써 각 프로세스에 맞는, 서로 다른 100번지 위치에 접근하는 것을 지원한다.
다중 프로그래밍 환경에서 물리적 메모리 안에는 여러 개의 프로세스가 동시에 올라가 있는 경우가 대부분인데, 이 때 MMU 방식으로 주소 변환을 한 결과가 해당 프로세스의 주소 공간을 벗어나는 경우가 생길 수 있다. 운영체제는 이러한 상황이 발생하는 것을 방지하고 보안을 유지하기 위해 한계 레지스터라는 레지스터를 사용한다.
- 한계 레지스터(limit register): 프로세스가 자신의 주소 공간을 넘어서는 메모리 참조를 하려고 하는지 체크하는 용도로 사용
- 현재 CPU에서 수행 중인 프로세스의 논리적 주소의 최댓값, 즉 그 프로세스의 크기를 담고 있음
CPU가 요청한 프로세스의 논리적 주소값이 한계 레지스터보다 작은지 확인하고, 작다면 논리적 주소값에 재배치 레지스터값을 더해 물리적 주소를 구한 다음 해당 물리적 메모리 위치에 접근하도록 허락한다. 반면에 크다면 프로세스 외의 다른 프로세스의 주소 영역에 접근하려는 시도이므로 트랩을 발생시켜 해당 프로세스를 강제종료시킨다.
2. 메모리 관리와 관련된 용어
동적로딩(dynamic loading)
: 프로세스가 시작될 때 그 프로세스의 주소 공간 전체를 메모리에 다 올려놓는 것이 아니라 프로세스 내에서 실행에 필요한 부분이 실제로 불릴 때마다 적재하는 방식
- 여러 프로그램이 동시에 메모리에 올라가서 수행되는 다중 프로그래밍 환경에서 사용되지도 않는 많은 양의 코드가 메모리에 올라가는 것을 막아 효율적인 메모리 사용 가능
- 프로그램 자체나 라이브러리를 통해 구현 가능
동적연결(dynamic linking)
: 컴파일을 통해 생성된 목적 파일과 라이브러리 파일 사이의 연결을 프로그램의 실행 시점까지 지연시키는 기법
- 다수의 프로그램이 공통으로 사용하는 라이브러리를 메모리에 한 번만 적재하므로 메모리 사용의 효율성을 높일 수 있음
- 운영체제의 지원 필요
- 연결(linking): 작성된 소스 코드를 컴파일하여 생성된 목적 파일(object file)과 이미 컴파일된 라이브러리 파일(library file) 등을 묶어 하나의 실행파일을 생성하는 과정
- 정적연결(static linking): 컴파일 타임에 모든 라이브러리 함수와 프로그램 코드를 하나의 실행 파일로 결합하는 것
- 동일한 라이브러리를 각 프로세스가 개별적으로 메모리에 적재해야 하므로 물리적 메모리가 낭비됨
정적연결과 달리 라이브러리가 실행 시점에 연결된다. 즉 실행 파일에 라이브러리 코드가 포함되지 않으며, 프로그램이 실행되면서 라이브러리 함수를 호출할 때가 되어서야 라이브러리에 대한 연결이 이루어진다. 이를 가능하게 하기 위해 실행파일의 라이브러리 호출 부분에 해당 라이브러리의 위치를 찾기 위한 스텁이라는 작은 코드를 두어 해당 라이브러리의 메모리 상 존재 여부를 확인한다. 존재할 경우 그 주소의 메모리 위치에서 직접 참조하며, 그렇지 않을 경우 디스크에서 동적 라이브러리 파일을 찾아 메모리로 적재한 후 수행한다.
중첩(overlays)
: 물리적 메모리의 크기 제약으로 하나의 프로세스조차도 메모리에 한꺼번에 올릴 수 없을 때, 프로세스의 주소 공간을 분할해 필요한 일부분을 메모리에 올려 실행하고 해당 부분에 대한 실행이 끝난 후 나머지 부분을 올려 실행하는 기법
- 운영체제의 지원 없이 프로그래머에 의해 구현되어야 함
스와핑(swapping)
: 메모리에 올라온 수행 중인 프로세스의 주소 공간 전체를 디스크의 스왑 영역에 일시적으로 내려놓는 것
- 메모리에 존재하는 프로세스의 수를 조절하여 메모리에 남아 있는 프로그램들에게 실행에 필요한 적절한 메모리 공간을 보장
- 프로세스가 종료되어 그 주소 공간을 디스크로 내쫓는 것이 아니라, 특정한 이유로 수행 중인 프로세스의 주소 공간을 일시적으로 메모리에서 디스크로 내려놓는 것을 의미
- 스왑 영역(swap area): 디스크 내에 파일 시스템과는 별도로 존재하는 일정 영역
- 백킹스토어(backing store)라고도 부름
- 다수의 사용자 프로세스를 담을 수 있을 만큼 충분히 큰 저장공간이어야 하고 어느 정도의 접근 속도가 보장되어야 함
- 스왑 인: 디스크 → 메모리
- 스왑 아웃: 메모리 → 디스크
컴파일 타임 바인딩 방식과 로드 타임 바인딩 방식에서는 스왑 아웃된 프로세스가 다시 스왑 인될 때에는 원래 존재하던 메모리 위치로 다시 올라가야 한다. 반면 실행시간 바인딩 기법에서는 추후 빈 메모리 영역 아무 곳에나 프로세스를 올릴 수 있다.
3. 물리적 메모리의 할당 방식
물리적 메모리는 운영체제 상주 영역과 사용자 프로세스 영역으로 나뉘어 사용된다.
- 운영체제 상주 영역: 인터럽트 벡터와 함께 물리적 메모리의 낮은 주소 영역을 사용하며 운영체제 커널이 이곳에 위치
- 사용자 프로세스 영역: 물리적 메모리의 높은 주소 영역을 사용하며 여러 사용자 프로세스들이 이곳에 적재되어 실행됨
사용자 프로세스 영역의 관리 방법은 프로세스를 메모리에 올리는 방식에 따라 연속할당(contiguous allocation) 방식과 불연속할당(noncontiguous allocation) 방식으로 나누어볼 수 있다.
연속할당 방식
: 프로세스를 메모리에 올릴 때 그 주소 공간을 여러 개로 분할하지 않고 물리적 메모리의 한 곳에 연속적으로 적재하는 방식
물리적 메모리를 고정된 크기의 분할로 미리 나누어 놓는지 아닌지에 따라 고정분할(fixed partition allocation) 방식과 가변분할(variable partition allocation) 방식으로 나뉜다.
- 고정분할 방식: 물리적 메모리를 주어진 개수만큼의 영구적인 분할로 미리 나누어두고 각 분할에 하나의 프로세스를 적재해 실행시키는 방식으로, 분할의 크기는 모두 동일하거나 서로 다르게 할 수도 있으며, 동시에 메모리에 올릴 수 있는 프로그램의 수가 고정돼 있고, 수행 가능한 프로그램의 최대 크기 또한 제한됨
- 외부조각: 프로그램의 크기보다 분할의 크기가 작은 경우 해당 분할이 비어있는데도 프로그램을 적재하지 못해 발생하는 메모리 공간으로, 특정 프로그램에 배당된 공간이 아니기 때문에 만약 이 외부조각의 크기보다 작은 크기의 프로그램이 도착한다면 적재 가능
- 내부조각: 프로그램의 크기보다 분할의 크기가 큰 경우 해당 분할에 프로그램을 적재하고 남는 메모리 공간으로, 특정 프로그램에 이미 배당된 공간으로 볼 수 있으므로 이 내부조각에 충분히 수용할 수 있는 크기의 프로그램이 있다 해도 활용 불가
- 가변분할 방식: 메모리에 적재되는 프로그램의 크기에 따라 분할의 크기, 개수가 동적으로 변하는 방식으로, 분할의 크기를 프로그램의 크기보다 크게 할당하지는 않으므로 내부조각은 발생하지 않으나 이미 메모리에 존재하는 프로그램이 종료될 때 이 공간이 새롭게 시작되는 프로그램의 크기보다 작을 경우 외부조각이 발생할 가능성 있음
- 컴팩션: 외부조각 문제를 해결하기 위해 물리적 메모리 중에서 프로세스에 의해 사용 중인 메모리 영역을 한쪽으로 몰고 가용 공간들을 다른 한쪽으로 모아서 하나의 큰 가용 공간을 만드는 방법으로, 실행 도중에 프로세스의 주소가 동적으로 바뀔 수 있는 실행시간 바인딩 방식이 지원되는 환경에서만 수행 가능
- 동적 메모리 할당 문제: 주소 공간의 크기가 n인 프로세스를 메모리에 올릴 때 물리적 메모리 내 가용 공간 중 어떤 위치에 올릴 것인지 결정하는 문제
- 가용 공간: 사용되지 않은 메모리 공간으로, 메모리 내의 여러 곳에 산발적으로 존재 가능
- 최초적합(first-fit) 방법: 크기가 n 이상인 가용 공간 중 가장 먼저 찾아지는 곳에 할당하는 방법으로, 시각적으로 효율적
- 최적적합(best-fit) 방법: 크기가 n 이상인 가장 작은 가용 공간을 찾아 할당하는 방법으로, 시간적으로 비효율적, 공간적으로 효율적
- 최악적합(worst-fit) 방법: 가용 공간 중에서 가장 크기가 큰 곳에 할당하는 방법으로, 시간적으로 비효율적, 공간적으로 비효율적
불연속할당 방식
: 하나의 프로세스를 물리적 메모리의 여러 영역에 분산해 적재하는 방식
하나의 프로그램을 분할하는 기준에 따라 페이징(paging) 기법, 세그먼테이션(segmentation) 기법, 페이지드 세그먼테이션(paged segmentation) 기법 등으로 나뉜다.
4. 페이징 기법
: 각 프로세스의 주소 공간을 동일한 크기의 페이지로 나누어 물리적 메모리의 서로 다른 위치에 페이지 단위로 적재시키는 기법
- 각 프로세스의 주소 공간 전체를 물리적 메모리에 한꺼번에 올릴 필요가 없으며 일부는 백킹스토어에, 일부는 물리적 메모리에 혼재시키는 것이 가능함
- 물리적 메모리를 페이지와 동일한 크기의 프레임으로 미리 나누어두어 빈 프레임이 있으면 어떤 위치이든 사용될 수 있으므로 동적 메모리 할당 문제가 발생하지 않음
- 프로세스의 주소 공간과 물리적 메모리가 모두 같은 크기의 페이지 단위로 나누어지기 때문에 빈 공간은 어느 곳이든 활용할 수 있어서 외부조각 문제는 발생하지 않으나 프로그램의 크기가 항상 페이지 크기의 배수가 된다는 보장이 없기 때문에 프로세스의 주소 공간 중 제일 마지막에 위치한 페이지에서는 내부조각이 발생할 가능성이 있음
- 페이징 기법에서 모든 프로세스는 각각의 주소 변환을 위한 페이지 테이블을 가짐
- 페이지 테이블: 특정 프로세스의 몇 번째 페이지가 물리적 메모리의 몇 번째 프레임에 들어있다는 페이지별 주소 변환 정보
5. 세그먼테이션
: 크기는 일정하지 않지만 프로그램의 주소 공간을 의미 있는 단위인 세그먼트로 나누어 물리적 메모리에 적재하는 기법
- 세그먼트: 하나의 프로세스를 구성하는 주소 공간을 코드, 데이터, 스택 등의 의미 있는 단위로 나눈 것
- 세그먼트로 나누어 관리하므로 크기가 균일하지 않은 세그먼트들을 메모리에 적재하는 부가적인 관리 오버헤드가 뒤따름
- 의미 단위로 나누어져 있기 때문에 공유와 보안의 측면에서 페이징 기법에 비해 훨씬 효과적임
- 논리적 주소는 <세그먼트 번호, 오프셋>으로 나뉘어 사용됨
- 세그먼트 번호: 해당 논리적 주소가 프로세스 주소 공간 내에서 몇 번째 세그먼트에 속하는지를 나타냄
- 오프셋: 그 세그먼트 내에서 얼마만큼 떨어져 있는지에 대한 정보를 나타냄
- 세그먼트 테이블: 주소 변환을 위해 사용
- 세그먼트 테이블 기준 레지스터(STBR): 현재 CPU에서 실행 중인 프로세스의 세그먼트 테이블이 메모리의 어느 위치에 있는지 그 시작 주소를 담음
- 세그먼트 테이블 길이 레지스터(STLR): 그 프로세스의 주소 공간이 총 몇 개의 세그먼트로 구성되는지 그 세그먼트의 개수를 담음
- 각 항목은 기준점(base)과 한계점(limit)을 가지고 있고 보호비트와 유효비트를 둠
- 기준점: 물리적 메모리에서 그 세그먼트의 시작 위치
- 한계점: 그 세그먼트의 길이
- 보호비트: 각 세그먼트에 대해 읽기/쓰기/실행 등의 권한이 있는지를 나타냄
- 유효비트: 각 세그먼트의 주소 변환 정보가 유효한지, 즉 해당 세그먼트가 현재 물리적 메모리에 적재되어 있는지를 나타냄
- 논리적 주소를 물리적 주소로 변환하기 전에 두 가지 사항을 먼저 확인하고 만족하는 경우 유효한 메모리 접근 요청으로 판단해 주소 변환 작업이 이루어지며, 만족하지 않으면 예외상황을 발생시켜 메모리 접근을 봉쇄
- 요청된 세그먼트 번호 < STLR
- 논리적 주소의 오프셋값 < 한계점
- 공유 세그먼트: 여러 프로세스가 특정 세그먼트를 공유해 사용하는 개념으로, 이 세그먼트를 공유하는 모든 프로세스의 주소 공간에서 동일한 논리적 주소에 위치해야 함
- 세그먼트의 길이가 균일하지 않아 외부조각이 발생하며, 세그먼트를 어느 가용 공간에 할당할 것인지 결정하는 문제 발생
- 최초적합(first fit): 해당 세그먼트 크기보다 크거나 같은 첫 번째 가용 공간에 할당하는 방식
- 최적적합(best fit): 세그먼트의 크기보다 크거나 같은 가용 공간 중 가장 작은 공간에 할당하는 방식
6. 페이지드 세그먼테이션
: 페이징 기법과 세그먼테이션 기법의 장점만을 취하는 주소 변환 기법
- 세그먼트가 임의의 길이가 아니라 동일한 크기 페이지들의 집합으로 구성되어야 함
- 하나의 세그먼트 크기를 페이지 크기의 배수가 되도록 하여 세그먼테이션 기법에서 발생하는 외부조각의 문제점을 해결하며, 동시에 세그먼트 단위로 프로세스 간의 공유나 프로세스 내의 접근 권한 보호가 이루어지도록 함으로써 페이징 기법의 약점을 해소
- 주소 변환을 위해 외부의 세그먼트 테이블과 내부의 페이지 테이블을 이용하며, 세그먼트가 여러 개의 페이지로 구성되므로 각 세그먼트마다 페이지 테이블을 가지게 됨
'books > OS' 카테고리의 다른 글
[OS] 웹캐싱 기법 (0) | 2024.06.13 |
---|---|
[OS] 디스크 관리 (1) | 2024.06.11 |
[OS] 가상메모리 (2) | 2024.06.11 |
[OS] CPU 스케줄링 (1) | 2024.03.26 |
[OS] 프로세스 관리 (1) | 2024.03.24 |