[Computer Science]/[운영체제(OS)]

[운영체제(OS)] 9-1. Memory-Management 메모리 시스템, 주소의 할당(Address Binding)

극꼼 2023. 3. 6. 22:33
반응형


운영체제가 하는 일은 컴퓨터 하드웨어의 자원을 관리하는 일입니다.

컴퓨터 하드웨어에는 대표적으로 CPU, Memory, I/O가 있는데요, 그래서 운영체제가 하는 일은 CPU 관리, 메모리 관리, I/O 관리라고 볼 수 있겠습니다. 

 

운영체제의 목적은 프로그래머가 메모리에 대해 잘 몰라도 하드웨어의 자원을 잘, 효율적으로 사용하게 하는 것입니다.

 

성능을 향상시키기 위해서는 여러 프로세스들이 주 메모리(Main Memory)를 공유해야 합니다.

* 메인 메모리 : CPU가 직접 접근할 수 있는 메모리. CPU는 PC가 지시하는 연산을 수행한 후에 메인 메모리에 데이터를 저장하거나 필요한 데이터를 요구합니다.

 

메모리를 관리하는 방법은 단순 하드웨어 방식에서 페이징(paging), 파편화(segment) 방법까지 다양하게 존재합니다. 9챕터에서는 이러한 것들을 공부할 예정입니다.


<Memory>

: 각각 주소가 할당된 byte들의 array로 구성. 

 

- 메모리 보호 기법은 운영체제가 개입하게 되면 성능이 떨어지기 때문에 하드웨어에서 지원해줘야 합니다.

- 개별적인 메모리 공간을 분리하기 위해 특정 프로세스만 접근할 수 있는 합법적인(legal) 메모리 주소 영역을 설정하고, 프로세스는 이 영역에만 접근할 수 있게 해야합니다.

- 할당되는 메모리 크기 = 기본 레지스터(가장 작은 합법적인 물리 메모리 주소) + 상한 레지스터(주어진 영역의 크기)

위 이미지의 알고리즘처럼 CPU가 접근하는 주소가 base보다 크고, base + limit보다 작아야 메모리에 접근할 수 있고, 그렇지 않으면 에러가 발생합니다.


<메모리 관리의 목표>

1. 프로그래밍할 때 메모리를 쉽게 사용할 수 있도록 abstraction을 제공해주는 것

2. 한정된 메모리 자원을 효율적으로 관리하는 것

3. 다른 프로세스가 메모리 영역을 침범하지 못하도록 메모리 보호

 

 

메모리 낭비 방지 기법으로는 동적 적재(Dynamic Loading), 동적 연결(Dynamic Linking), 스와핑(Swapping) 등이 있습니다. 이 3가지에 대해서는 9챕터를 계속 공부하면서 배워보겠습니다.


<주소의 할당(Address Binding)>

: 프로그램에서 메모리 주소를 결정하는 것.

프로그램이 실행되기 위해서는 메모리에 프로그램을 적재한 후, 프로세스 context내에 배치(주소 할당)해야 합니다.

- 프로그램이 메인 메모리로 올라옴 -> 프로세스가 됨.

- 프로세스들의 집합 -> input queue를 구성함.

- (single-tasking의 작업 절차에서는) input queue에서 프로세스를 하나 선택해서 할당된 메모리로 로드함 -> 해당 프로세스를 실행한 후, 종료되면 해당 프로세스가 사용했던 메모리 공간은 다시 사용할 수 있게 됨.

 

* 데이터에 메모리 주소를 할당할 때, 이 주소를 언제 할당하냐의 단계는 크게 3단계가 있습니다.

1) compile time : 프로세스가 메모리 내에 들어갈 위치를 compile time에 미리 알 수 있으면 컴파일러는 absolute code를 생성합니다. 사전에 메모리의 내용을 다 알고 어디서부터 할당해줘야 좋은지 파악된 상태에서만 가능하며, 현 멀티프로그래밍 시스템에서는 불가능합니다.

2) load time : compile time에 메모리 위치를 알지 못할 경우, load time에 relocatable(재배치 가능한) code로 만듭니다.

3) execution time : 프로세스가 실행하는 중간에 메모리 내의 한 segment가 다른 segment로 옮겨진다면, "바인딩이 execution time에 이뤄졌다(허용되었다)"라고 합니다. 

1. Compile time

: 소스 코드를 Managed Module, assembly로 컴파일 할 때 생성되는 absolute code가 올라갈 메모리가 결정됩니다. 이게 컴파일 타임에 결정되는 메모리 할당입니다. 

 

* absolute code : 물리적으로 고정되는 코드입니다. 아래 예시 이미지에서 보이는 보라색 영역이고, 고정된 메모리 영역을 차지합니다

(= 프로그램 내부에서 사용하는 주소와 physical 주소가 똑같음).


2. Load Time

: 로딩할 때 결정됩니다. 컴파일 타임 바인딩과는 다르게 relocatable code를 생성하며, 상대 주소를 사용하기 때문에 프로그램 내부에서 사용하는 주소와 physical 주소가 다릅니다. 

메모리 어디에서나 수행될 수 있어 멀티 프로그래밍이 가능해진다는 장점이 있지만, 메모리에 올라가는 프로그램 안의 code segment의 명령어와 메모리를 참조하는 명령어 모두의 주소를 바꿔줘야 하므로 메모리 로딩 시간이 엄청 오래 걸린다는 단점이 있습니다. 그래서 로딩 타임에 메모리 주소를 결정하는 방법은 실제로 쓰이지 않고, 더 좋은 대안이 런타임 바인딩입니다.

 


3. Execution Time

: MMU(Memory Management Unit) 하드웨어가 명령어를 수행할 때 주소를 그때그때 변환시켜 변환된 주소로 만들어줍니다. 

로드 타임 바인딩과의 차이점은, 로드 타임 바인딩은 메모리에 로딩할 때 이 작업을 미리 다 해놓는 것이고, 런타임 바인딩(= 실행 타임 바인딩)은 그 코드가 실행될 때마다 변환 작업을 해주는 겁니다. 런타임 바인딩이 더 안 좋아 보이겠지만 하드웨어 내에 로직이 있기 때문에 성능상 문제가 없다고 합니다. 반면 로드 타임 바인딩은 메모리 로딩할 때 오버헤드가 크기에 사용하지 않습니다. 


compile time, load time의 바인딩에서는 논리적 주소와 물리적 주소가 같고, Execution time의 바인딩에서는 논리적 주소와 물리적 주소가 달라집니다.

* 논리적 주소를 가상 주소(virtual address)라고도 합니다.

<물리적 주소와 논리적 주소>

- Physical Address(물리적 주소)

: 메모리가 일반적으로 취급하는 주소. 

프로그램을 실행시킨다 = 그 데이터가 메인 메모리를 n기가 차지하면서 실행함 -> 여기서 n기가만큼의 공간이 물리적 주소입니다. 

 

- Logical Address(논리적 주소)

: CPU가 생성하는 가상의 주소.

 

프로그램 실행 중에는 이 가상 주소를 물리 주소로 바꿔줘야 하는데 이 변환 작업은 하드웨어 장치인 MMU(Memory Management Unit)에 의해 실행됩니다. 주소가 메모리로 전송될 때 유저 프로세스에 의해 생성된 모든 주소에 기본 레지스터 값이 추가됩니다. 유저 프로그램은 실제 물리적 주소에 절대 접근할 수 없습니다.

위의 그림을 해석하자면, CUP가 생성한 논리적 주소가 346이고 relocation register의 값이 14000이라면 MMU는 논리적 주소를 14346으로 변환해줍니다. 

유저 프로그램은 실제 물리 주소(14346)를 알 수 없고, 346에 대한 포인터만 생성해서 저장, 연산, 비교 등의 작업을 수행할 수 있습니다. 

반응형