메모리 관리를 하기 전에, 왜 메모리 관리를 해야할까?
1. OS는 각 프로세스들이 메모리에 올라왔을 때 다른 프로세스의 메모리 공간을 접근하는 것을 막아야 한다.
이를 위해 메모리에서 프로세스의 시작 위치를 저장하는 Base register와 프로세스에게 할당 된 메모리 크기인 Limit Register 값을 이용해 프로세스들의 메모리 공간의 경계를 나눈다.
즉, 실제 메모리가 가지는 범위는
Base Register <= 프로세스가 접근할 수 있는 공간 <= Base Register + Limit Register의 범위
를 가진다.
2. 바인딩 시점
주소 바인딩
은 프로세스가 접근해야 하는 값과 함수에 대한 주소가 정해지는 것
을 말한다.
우리가 작성한 프로그램에서 변수나 함수는 각자의 실제 메모리 주소를 통해 접근
하고, 프로그램은 컴파일 되어 메모리에 올라간 후 CPU에 의해 명령어가 한 문장씩 실행
되게 된다.
이 때, CPU가 명령문을 실행함으로써 발생하는 메모리 주소
를 Logical Address
또는 Virtual Address
라고 한다.
그리고 실제 접근해야 하는 메모리 주소를 Physical Address
라고 하는데, Logical Address와 Physical Address는 서로 다를 수 있다.
1. 컴파일 시점 주소 바인딩
컴파일 시점 주소 바인딩은 프로그램이 컴파일 될 때 컴파일러에서 명령어들과 변수의 메모리 주소가 정해지는 것
을 말한다.
여기서 정해지는 주소는 실제 메모리 주소
이기 때문에 CPU에서 명령어를 실행할 때 이미 주소가 정해져 있으므로 따로 주소 계산을 하지 않고 바로 접근해야 하는 주소가 된다.
따라서 컴파일 시점 바인딩에서는 Logical Address와 Physical Address는 같다.
컴파일 시점에 주소가 결정이 나면 프로그램을 다른 시스템에서 실행했을 때 해당 시스템의 메모리를 어디서부터 할당해주는지를 나타내는 Starting Point가 다르거나, 이미 그 주소에 다른 프로그램이 실행 중이라면 프로그램을 실행 할 수 없다.
2. 로드 시점 주소 바인딩
로드 시점 주소 바인딩은 프로그램이 컴파일 되고 메모리에 올라갈 때 CPU에서 주소 계산이 일어난 후 발생하는 주소
를 말한다.
컴파일 된 프로그램 내의 각 변수나 명령어의 주소는 특정 값을 기준으로 정해진다.
그리고 메모리에 올라가 CPU에서 주소를 계산할 때 프로그램이 올라간 메모리 주소의 Base Register 값에 이를 더해
주소를 만들어 낸다.
이렇게 CPU 내에서 계산되고 발생한 Logical 주소는 해당 메모리의 실제 주소인 Physical Address와 같다.
예를 들어, 프로그램이 컴파일 될 때 명령어 기준으로 0을 잡았다면, 각각의 변수나 함수들의 주소는 0을 기준으로 얼마나 떨어져 있는지를 통해 결정이된다.
int a 의 상대적 위치가 10이고 void function()의 상대적인 위치가 20이라 가정하고 메모리 주소 10000에 프로그램이 올라간다면, CPU는 int a = 10000 + 10, void function() = 10000 + 20을 한 주소를 만들어 낸다.
이렇게 로드 시점 주소 바인딩으로 주소가 정해진 프로그램은 한번 메모리에 올라가면 종료될 때 까지
그 위치에 존재한다.
3. 실행 시점 주소 바인딩
실행 시점 주소 바인딩은 메모리에 올라가 매번 명령어가 실행될 때마다 주소가 계산
된다.
이 방법을 사용하는 프로그램은 프로그램의 메모리 위치가 매번 바뀌기 때문에
그렇다.
프로세스는 여러 이유로 인해 메모리 공간 안에서 위치가 바뀔 수 있다. 그렇게 되면 시작 위치는 계속 바뀌고 프로세스 내의 주소들도 바뀌게 되는데 위의 두 가지 방법으로는 매번 바뀌는 메모리 주소에 접근을 할 수 없다.
그래서 CPU에서 나온 임의의 주소는 MMU
라는 곳을 거쳐 실제 주소로 바뀌어 접근하게 된다.
CPU에서 발생한 주소가 Logical Address이고 MMU를 통해 바뀐 주소가 메모리의 실제 주소인 Physical Address이므로 실행 시점 주소 바인딩에서는 두 주소가 다르다.
메모리 관리 장치 (Memory Management Unit, MMU)는 CPU가 메모리에 접근하는 것을 관리하는 컴퓨터 하드웨어 부품.
가상 메모리 주소를 실제 메모리 주소로 변환하며, 메모리 보호, 캐시 관리, 버스 중재 등의 역할을 담당
프로그램은 최종적으로 메모리에 올리는 로드 과정과 라이브러리 파일과 연결해주는 링킹 과정을 통해 최정적으로 메모리에 올라간다.
올라간 뒤에도 지속적으로 메모리 공간을 차지하는 것이 아니라 운영체제의 필요에 의해 Swap-in 되거나 Swap-out 되기도 한다.
Dynamic Loading
Dynamic Loading은 한정적인 메모리 공간
으로 인해 생겨난 방법이다.
메모리 공간은 한정되어있고, 공간의 크기가 그렇게 크지 않을 때 프로세스의 모든 모듈을 올리기에는 공간이 부족하여 해당 모듈이 필요하면 그때 올려주는 방법이다.
필요한 모듈만 올리기 때문에 메모리 공간을 절약할 수 있다.
하지만 현재 가상 메모리 기법을 사용해 메모리 공간이 충분히 많다고 가정해 사용되지 않는 방법이다.
Dynamic Linking
기존 링크 과정은 라이브러리 파일을 서로 다른 프로그램이 사용할 때 매번 프로세스 메모리 공간에 해당 라이브러리를 확보
해 프로세스에 함께 올렸다. 하지만 이는 같은 라이브러리 파일이 메모리 공간에 여러번 올라감으로써 메모리 공간의 낭비로 이어진다.
그리하여 나온 방법이 Dynamic Linking이다. 실행되기 전 까지는 링킹이 되지 않고
실행이 될 때 특정 라이브러리 파일이 최초로 한 번 메모리에 올리고
이 라이브러리를 사용하는 프로세스들은 라이브러리의 위치를 가리키는 stub 포인트
를 갖게 되어 라이브러리를 참조하게 된다. 그리하여 같은 라이브러리가 메모리에 여러 번 올라가는 것을 방지해 메모리 낭비를 막는다.
Swapping
Swapping은 우선순위가 높거나 중요한 프로세스가 메모리에 올라가려 할 때 공간이 부족하면
현재 메모리 위에 올라가 있는 프로세스 중 수 많은 알고리즘 중 하나를 이용해 어떤 프로세스를 잠시 디스크에 저장
을 하고, 우선순위가 높은 프로세스를 수행
한다.
작업을 마치면 다시 디스크에 있던 프로세스를 메모리에 올린다.
이렇게 우선순위가 높거나 중요한 프로세스가 중간에 들어가는 것을 Swap-in
이라 하고, 자리를 내어주어 디스크로 빠지게 되는 과정을 Swap-out
이라고 한다.
Swap-out된 프로세스가 다시 메모리에 올라갈 때는 원래 있던 자리로 돌아가지 않을 수 있다.
'OS' 카테고리의 다른 글
[리눅스]쓰레드 덤프, 힙 덤프, 코어 덤프 분석 삽질과정 (0) | 2020.01.31 |
---|---|
[Linux] 로그 모니터링을 통한 장애시 문자 알림 보내기 (1) | 2019.08.02 |
[Linux] 리눅스에 톰캣 설치 & 서비스 등록 (0) | 2019.07.05 |
댓글