메모리 관리 관련 용어 정리
-
Logical Address(virtual address): 프로세스마다 독립적으로 가지는 주소 공간으로 각 프로세스 모두 0번지부터 시작, CPU가 보는 주소는 logical address임
-
Physical Address: 메모리에 실제로 올라가는 위치
-
Symbolic Address: 프로그래머는 주소가 아닌 변수 이름 혹은 함수 이름을 사용하여 프로그래밍 하는데, 이렇게 컴파일 전 변수들을 symbolic address라 일컬음
-
주소바인딩: 어떤 프로그램이 물리적인 메모리의 어디로 올라갈지 결정하는 것
-
주소 바인딩 결정 방법 3가지
-
Compile Time Binding:컴파일 시 물리주소까지 결정
- 실행 시점에 비어있는 메모리 주소가 많더라도 이미 확정된 메모리 주소를 사용함
- 예전에 프로그램이 컴퓨터에서 하나만 실행될 때 사용, 지금은 비효율적이라 X
- 메모리 위치를 바꾸고 싶으면 컴파일을 다시해야 함
-
Load Time Binding: 메모리에 load 할 때 비어있는 번지부터 매핑해서 binding
- 컴파일 마다 다른 위치의 메모리에 올라갈 수 있음, 숫자 얼마(비어 있는 메모리주소 시작위치)를 더해주기만 하면 됨
-
Run Time Binding: 메모리에 load 할 때 비어있는 번지부터 매핑해서 binding, but 실행 도중에 메모리 위치가 변할 수 있음
- 디스크로 쫓겨 났다가 다시 들어오는 경우 등에 원래 30번지 였던 주소가 300번지로 옮겨지는 등의 경우가 발생
- 지금의 시스템은 run time binding
- cpu가 메모리 주소를 요청할 때마다 바인딩을 체크해야 함, 실행시마다 주소가 바뀔 수 있으므로, 이를 위해 HW적 지원이 필요(MMU)
Q. java run time 동적 실행은 뭔 원리지 그럼?
Q. CPU가 바라보는 주소는 Logical Address or Physical Address?
- 컴파일 된 실행파일에 대한 instruction은 메모리에 load 되더라도 address가 그대로 유지됨, 컴파일된 코드의 메모리 주소는 유지가 되기 때문, CPU가 instruction을 수행할 때 logical address를 통해 값을 요청하면 그때 주소 변환을 통해 physical address를 구해와서 값을 구함
Q. 그럼 각 프로그램들은 컴파일을 언제 하는거야? 우리가 일반적으로 사용하는 실행파일은 이미 컴파일이 된 상태인 건가? 그렇다면 모든 실행파일의 논리적 메모리 주소는 이미 결정이 되어 있는 거겠네?
Q. 그럼 컴파일 될 때마다 논리적 주소는 변경될 수 있는 건가?
MMU
-
Memory-Management Unit: logical address를 physical address로 매핑해주는 Hardware device
-
MMU scheme
- 사용자 프로세스가 CPU에서 수행되며 생성해내는 모든 주소값에 대해 base register(=relocation register)의 값을 더함
-
메모리 물리 위치가 고정되어 있다고 가정하고 우선 설명함
-
relocation register에 시작위치를 저장하고 가상 메모리에서 해당 코드가 어디에 위치하는지를 확인하여 더함
-
limit register는 논리주소가 해당 프로그램의 크기보다 크다면 트랩을 걸어서 악의적으로 다른 메모리 공간을 침범하는 것을 막음
-
user program은 logical address만을 다루며 실제 physical address는 user program이 볼 수 없고 알 필요도 없음
Dynamic Loading
- 프로세스 전체를 메모리에 미리 다 올리는 것이 아니라 해당 루틴이 불려질 때 메모리에 load하는 것
- momory utilization의 향상
- 가끔식 사용되는 많은 양의 코드의 경우 유용
- 프로그래밍은 아주 보수적이어서 사소한 예외까지도 처리가 필요한데 이러한 코드는 많이 사용되지 않기 때문에 동적 로딩이 효율적
- 현재 각 프로그램들이 필요한 부분만 메모리에 올라가고 내려가는 것은 O.S의 paging system에 의한 것, dynamic loading은 이와는 다른 개념으로 프로그래머가 직접 메모리를 올리고 내리는 것을 O.S가 제공하는 라이브러리를 이용해 구현하는 것, 지금은 두 개념을 dynamic loading으로 섞어 쓰기도 함.
Swapping
- Swapping: 프로세스를 일시적으로 메모리에서 backing store로 쫓아내는 것
- backing store = swap area, 하드 디스크 등 보조기억공간
- 많은 사용자의 프로세스 이미지를 담을 만큼 충분히 빠르고 큰 저장 공간
- Swap in / Swap out
-
swapping이 효율적으로 사용되려면 run time binding이 필요
- 원래 자리로 돌아가지 못 한다면 다른 자리로 들어갈 수 있어야 공간을 잘 사용할 수 있는데 그렇지 못 한다면 비효율적
-
디스크에 접근하는 시간은 디스크 헤드가 이동하는 시간이 거의 대부분, 실제로 데이터를 전송하는 transfer time은 굉장히 미미, 그렇지만 용량이 굉장히 방대한 프로세스의 swapping system에서는 transfer time이 상당부분 차지
-
본연의 swapping에 의미는 프로그램이 메모리에서 통째로 쫓겨나는 것이지만 최근에는 paging system에서는 프로그램의 주소공간이 잘게 짤려서 일부만 쫓겨나는 것 마저도 swap out 됐다는 표현을 사용하기도 함, 원칙적으로는 프로그램 구성하는 주소 공간 전부가 쫓겨났을 때를 의미
Dynamic Linking
Linking: 프로그램을 작성한 다음에 컴파일 후 링크에서 실행파일을 만듦, 링크라는 건 여러군데 존재하던 컴파일 된 파일들을 묶어서 하나의 실행파일을 만드는 과정
물리적인 메모리를 어떻게 관리할 것인가?
Contiguous Allocation
-
각 프로세스가 메모리의 연속적인 공간에 적재되도록 함, 프로세스가 분리되지 않음.
-
고정 분할(Fixed partition) 방식
- 물리적 메모리를 몇 개의 영구적 분할로 나눔
- 분할의 크기가 모두 동일한 방식과 서로 다른 방식 존재
- 분할당 하나의 프로그램 적재
- 융통성이 없음
- 동시에 메모리에 load되는 프로그램의 수가 고정됨
- 최대 수행 가능 프로그램 크기 제한
- Internal, External fragmentation 발생
→ 내부 단편화: 한 partition에 한 프로세스만 할당 가능하므로 partition의 일부분이 낭비되는 경우
→ 외부 단편화: 남은 메모리 크기가 process 크기보다 크지만 연속된 공간이 아니어서 할당이 불가능해 메모리가 낭비되는 경우
-
가변 분할(Variable partition) 방식
- 프로그램의 크기를 고려해서 할당
- 분할의 크기, 개수가 동적으로 변함
- 기술적 관리 기법 필요
- External fragmentation 발생
-
External fragmentation?
- 프로그램의 크기보다 분할의 크기가 작은 경우
- 아무 프로그램에도 배정되지 않은 빈 곳인데도 프로그램이 올라갈 수 없는 작은 분할
-
Internal fragmentation ?
- 프로그램의 크기보다 분할의 크기가 큰 경우
- 하나의 분할 내부에서 발생하는 사용되지 않는 메모리 조각
- 특정 프로그램에 배정되었지만 사용되지 않는 공간
-
외부조각도 나중에 더 작은 프로그램이 들어오고 남는 공간이 생기면 내부조각이 되는 등 그때그때마다 조각에 대한 해석이 달라질 수 있음
-
Hole: 메모리 공간 중 할당되지 않은 가용 공간으로 다양한 크기의 hole들이 메모리 여러 곳에 흩어져 있음, 프로세스가 도착하면 수용 가능한 hole을 할당하게 됨
- 운영체제는 할당공간과 가용공간(hole)의 정보를 가지고 있음
Dynamic Storage-Allocaition Problem
-
가변 분할 방식에서 size n인 요청을 만족하는 가장 적절한 hole을 찾는 문제
- First-fit: search 하면서 size를 만족하는 가장 첫 번째 hole을 할당
- Best-fit: search를 통해 size를 만족하는 가장 작은 hole을 할당
- Hole들의 리스트가 크기 순으로 정렬되지 않은 경우 모든 hole 탐색 해야 함
- 많은 수의 아주 작은 hole들이 만들어짐
- Worst-fit: search를 통해 size를 만족하는 가장 큰 hole을 할당
- 역시 모든 리스트를 탐색해야 함
- 상대적으로 아주 큰 hole 들이 생성됨
-
First-fit, Best-fit이 worst-fit보다 속도와 공간 이용률 측면에서 효과적인 것으로 알려짐(실험결과)
- First-fit의 경우 속도 빠름
- Worst-fit의 경우 가용 가능한 큰 공간을 계속 분할하여, 충분히 큰 공간이 필요한 프로세스를 로드하지 못 하는 반면, Best-fit의 경우 최대한 공간을 아껴씀
Q.고정 분할 방식에서는 프로세스 배치를 어떻게 하지 그럼?
- Compaction
- 주소 바인딩도 점검해야 하는 등 많은 고려사항이 필요해 비용이 많이 듦
Noncontiguous allocation
- segmentation: 의미있는 단위로 자름
- EX) code segment, data segment, stack segment, code => function segment
- segment 크기가 균일하지 않기 때문에 dynamic storage allocation problem 발생